dhcpcd icon indicating copy to clipboard operation
dhcpcd copied to clipboard

DHCPv4 only for specific interface with privsep

Open rsmarples opened this issue 3 years ago • 3 comments

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.

rsmarples avatar Jan 16 '23 11:01 rsmarples

@guyyur can you test this please to ensure it's fixed for you?

rsmarples avatar Jan 16 '23 12:01 rsmarples

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:

  1. Always create it - socket will exist even if IPv4 not used at all but version is compiled with IPv4.

  2. 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.

  3. 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.

guyyur avatar Jan 16 '23 16:01 guyyur

@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.

guyyur avatar Jan 16 '23 21:01 guyyur