From: Roy Marples Date: Sat, 20 Apr 2024 13:48:10 +0000 (+0000) Subject: dhcpcd: Only drop/release address family specified when given X-Git-Tag: v10.0.7~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5dd6ee143729df625c6395a9286260fc796ecfeb;p=thirdparty%2Fdhcpcd.git dhcpcd: Only drop/release address family specified when given Fixes #311 --- diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 3571aae0..d9e07157 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -401,30 +401,43 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) } static void -dhcpcd_drop(struct interface *ifp, int stop) +dhcpcd_drop_af(struct interface *ifp, int stop, int af) { + if (af == AF_UNSPEC || af == AF_INET6) { #ifdef DHCP6 - dhcp6_drop(ifp, stop ? NULL : "EXPIRE6"); + dhcp6_drop(ifp, stop ? NULL : "EXPIRE6"); #endif #ifdef INET6 - ipv6nd_drop(ifp); - ipv6_drop(ifp); + ipv6nd_drop(ifp); + ipv6_drop(ifp); #endif + } + + if (af == AF_UNSPEC || af == AF_INET) { #ifdef IPV4LL - ipv4ll_drop(ifp); + ipv4ll_drop(ifp); #endif #ifdef INET - dhcp_drop(ifp, stop ? "STOP" : "EXPIRE"); + dhcp_drop(ifp, stop ? "STOP" : "EXPIRE"); #endif #ifdef ARP - arp_drop(ifp); + arp_drop(ifp); + } #endif + #if !defined(DHCP6) && !defined(DHCP) UNUSED(stop); #endif } +static void +dhcpcd_drop(struct interface *ifp, int stop) +{ + + dhcpcd_drop_af(ifp, stop, AF_UNSPEC); +} + static void stop_interface(struct interface *ifp, const char *reason) { @@ -1512,7 +1525,8 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc, char **argv) { struct interface *ifp; - unsigned long long opts; + struct if_options *ifo; + unsigned long long opts, orig_opts; int opt, oi, oifind, do_reboot, do_renew, af = AF_UNSPEC; size_t len, l, nifaces; char *tmp, *p; @@ -1641,20 +1655,40 @@ dumperr: } if (opts & (DHCPCD_EXITING | DHCPCD_RELEASE)) { - if (oifind == argc) { + if (oifind == argc && af == AF_UNSPEC) { stop_all_interfaces(ctx, opts); eloop_exit(ctx->eloop, EXIT_SUCCESS); return 0; } - for (oi = oifind; oi < argc; oi++) { - if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL) - continue; + + TAILQ_FOREACH(ifp, ctx->ifaces, next) { if (!ifp->active) continue; - ifp->options->options |= opts; + for (oi = oifind; oi < argc; oi++) { + if (strcmp(ifp->name, argv[oi]) == 0) + break; + } + if (oi == argc) + continue; + + ifo = ifp->options; + orig_opts = ifo->options; + ifo->options |= opts; if (opts & DHCPCD_RELEASE) - ifp->options->options &= ~DHCPCD_PERSISTENT; - stop_interface(ifp, NULL); + ifo->options &= ~DHCPCD_PERSISTENT; + switch (af) { + case AF_INET: + ifo->options &= ~DHCPCD_IPV4; + break; + case AF_INET6: + ifo->options &= ~DHCPCD_IPV6; + break; + } + if (af != AF_UNSPEC) + dhcpcd_drop_af(ifp, 1, af); + else + stop_interface(ifp, NULL); + ifo->options = orig_opts; } return 0; } @@ -2173,11 +2207,11 @@ printpidfile: ctx.options |= DHCPCD_MANAGER; /* - * If we are given any interfaces, we + * If we are given any interfaces or a family, we * cannot send a signal as that would impact * other interfaces. */ - if (optind != argc) + if (optind != argc || family != AF_UNSPEC) sig = 0; } if (ctx.options & DHCPCD_PRINT_PIDFILE) {