]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
dhcpcd: Only drop/release address family specified when given
authorRoy Marples <roy@marples.name>
Sat, 20 Apr 2024 13:48:10 +0000 (13:48 +0000)
committerRoy Marples <roy@marples.name>
Sat, 27 Apr 2024 11:12:29 +0000 (11:12 +0000)
Fixes #311

src/dhcpcd.c

index 3571aae0c5dd959064db95829019a447f652e90e..d9e071577e2f756e3ad117f5a9f66660ee983c19 100644 (file)
@@ -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) {