DHCPv4 only for specific interface with privsep
Discussed in https://github.com/NetworkConfiguration/dhcpcd/discussions/166
Originally posted by guyyur January 15, 2023 Hi,
Is configuration of IPv4 only on specific interface supported? Example: dhcpcd.conf
...
allowinterfaces wan0 lan0 tun0
noipv4
...
interface wan0
ipv4
...
With privsep I get "Bad file descriptor" after renew fails. dhcpcd[1072]: wan0: failed to renew DHCP, rebinding dhcpcd[1072]: ps_root_recvmsg: Bad file descriptor
With privsep, ctx->udp_wfd is only initialized if global options have DHCPCD_IPV4 so ctx->ufd_wfd is -1 for ps_inet_sendmsg (called from dhcp_sendudp) with above config. I think ctx->udp_rfd will also be -1 but I haven't verified it.
When not using privsep, dhcp_start1 checks the interface options for DHCPCD_IPV4 so ctx->udp_wfd and ctx->udp_rfd will be initialized as long as there is one interface with ipv4 option set.
@guyyur can you test this please to ensure it's fixed for you?
Hi, udp_wfd in [privileged proxy] also needs to be created (currently still -1 because of check for global options) https://github.com/NetworkConfiguration/dhcpcd/blob/always_start_inet_proxy/src/privsep-root.c#L707
used in: https://github.com/NetworkConfiguration/dhcpcd/blob/always_start_inet_proxy/src/privsep-inet.c#L269
Some options:
-
Always create it - socket will exist even if IPv4 not used at all but version is compiled with IPv4.
-
Create it in ps_root_startcb() for global options and in ps_inet_sendmsg if it is -1. For example, convert the udp_wfd create code from ps_root_startcb() into a function and use it in both ps_root_startcb() and always in ps_inet_sendmsg(). ps_inet_sendmsg will only be called if there is an interface with DHCPv4 enabled. But once created it will always exist, unlike non-privsep where dhcp_free closes the socket if interfaces are removed.
-
Add new message flags (PS_CREATE, PF_FREE?) to send to [privileged proxy] to init and destroy bootp that will create/destroy the socket and be sent from dhcp_start1 / dhcp_free. This should mimic non-privsep behavior the best.
@rsmarples I played around with implementing option 3 (sending messages to create/destroy the sockets) in case you are interested. ~~A bit rough and only implemented for bootp at the moment (ipv6 nd and dhcp6 probably have same issues with only checking global options)~~ Edit: First version didn't work, I didn't notice that ps_inet doesn't run under ps_root so ps_root cannot pass the message, I will try to send messages separately to ps_inet and ps_root. Edit 2: Updated version with bootp, nd and dhcp6 but nd since nd socket is raw so cannot be dynamically created/destroyed it has to be created before dropping privileges so no way to keep non-privsep behavior for all sockets. Commit: https://github.com/guyyur/dhcpcd/commit/f9e3d6a0474f82aaf3670ac1f004cd5f59a5eb0f
Probably best to go with option 1, which just needs always init udp_wfd added to your changes.