]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
When OS reports new and removed interfaces, dhcpcd sees this and either starts or...
authorRoy Marples <roy@marples.name>
Thu, 4 Sep 2008 11:30:11 +0000 (11:30 +0000)
committerRoy Marples <roy@marples.name>
Thu, 4 Sep 2008 11:30:11 +0000 (11:30 +0000)
dhcpcd.c
dhcpcd.h
if-bsd.c
net.h

index 1afa77a2b446582395128d1f401f1f9748a9eb0f..306f4d02321eb920fa188a0623e6dc62ecb54483 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -66,6 +66,8 @@ const char copyright[] = "Copyright (c) 2006-2008 Roy Marples";
 
 int master = 0;
 int pidfd = -1;
+static char **ifv = NULL;
+static int ifc = 0;
 static int linkfd = -1;
 static char cffile[PATH_MAX];
 static char pidfile[PATH_MAX] = { '\0' };
@@ -195,6 +197,7 @@ stop_interface(struct interface *iface)
 {
        struct interface *ifp, *ifl = NULL;
 
+       logger(LOG_ERR, "%s: removing interface", iface->name);
        drop_config(iface, "STOP");
        close_sockets(iface);
        delete_timeout(NULL, iface);
@@ -272,8 +275,6 @@ send_message(struct interface *iface, int type,
        }
        free(dhcp);
        if (r == -1) {
-               logger(LOG_ERR, "%s: removing interface from dhcpcd",
-                      iface->name);
                stop_interface(iface);
        } else {
                if (callback)
@@ -592,44 +593,29 @@ open_sockets(struct interface *iface)
 }
 
 static void
-handle_link(_unused void *arg)
+handle_carrier(struct interface *iface)
 {
-       struct interface *iface;
-       int retval;
-
-       retval = link_changed(linkfd, ifaces);
-       if (retval == -1) {
-               logger(LOG_ERR, "link_changed: %s", strerror(errno));
+       if (!(iface->state->options->options & DHCPCD_LINK))
                return;
-       }
-       if (retval == 0)
-               return;
-       for (iface = ifaces; iface; iface = iface->next) {
-               if (iface->state->options->options & DHCPCD_LINK) {
-                       switch (carrier_status(iface->name)) {
-                       case -1:
-                               logger(LOG_ERR, "carrier_status: %s",
-                                      strerror(errno));
-                               break;
-                       case 0:
-                               if (iface->state->carrier != LINK_DOWN) {
-                                       iface->state->carrier = LINK_DOWN;
-                                       logger(LOG_INFO, "%s: carrier lost",
-                                              iface->name);
-                                       close_sockets(iface);
-                                       delete_timeouts(iface, start_expire, NULL);
-                               }
-                               break;
-                       default:
-                               if (iface->state->carrier != LINK_UP) {
-                                       iface->state->carrier = LINK_UP;
-                                       logger(LOG_INFO, "%s: carrier acquired",
-                                              iface->name);
-                                       start_interface(iface);
-                               }
-                               break;
-                       }
+       switch (carrier_status(iface->name)) {
+       case -1:
+               logger(LOG_ERR, "carrier_status: %s", strerror(errno));
+               break;
+       case 0:
+               if (iface->state->carrier != LINK_DOWN) {
+                       iface->state->carrier = LINK_DOWN;
+                       logger(LOG_INFO, "%s: carrier lost", iface->name);
+                       close_sockets(iface);
+                       delete_timeouts(iface, start_expire, NULL);
+               }
+               break;
+       default:
+               if (iface->state->carrier != LINK_UP) {
+                       iface->state->carrier = LINK_UP;
+                       logger(LOG_INFO, "%s: carrier acquired", iface->name);
+                       start_interface(iface);
                }
+               break;
        }
 }
 
@@ -785,6 +771,43 @@ init_state(struct interface *iface, int argc, char **argv)
                start_interface(iface);
 }
 
+static void
+handle_new_interface(const char *name)
+{
+       struct interface *ifs, *ifp;
+       const char * const argv[] = { "dhcpcd", name };
+       int i;
+
+       /* If running off an interface list, check it's in it. */
+       if (ifc) {
+               for (i = 0; i < ifc; i++)
+                       if (strcmp(ifv[i], name) == 0)
+                               break;
+               if (i >= ifc)
+                       return;
+       }
+
+       if ((ifs = discover_interfaces(2, UNCONST(argv)))) {
+               for (ifp = ifs; ifp; ifp = ifp->next)
+                       init_state(ifp, 2, UNCONST(argv));
+               if (ifaces) {
+                       ifp = ifaces;
+                       while (ifp->next)
+                               ifp = ifp->next;
+                       ifp->next = ifs;
+               } else
+                       ifaces = ifs;
+       }
+}
+
+static void
+handle_link(_unused void *arg)
+{
+       if (manage_link(linkfd, ifaces, handle_carrier,
+                       handle_new_interface, stop_interface) == -1)
+               logger(LOG_ERR, "manage_link: %s", strerror(errno));
+}
+
 static void
 handle_signal(_unused void *arg)
 {
@@ -1091,13 +1114,15 @@ main(int argc, char **argv)
        }
        free_options(ifo);
 
-       argc -= optind;
-       argv += optind;
-       ifaces = discover_interfaces(argc, argv);
-       argc += optind;
-       argv -= optind;
+       ifc = argc - optind;
+       ifv = argv + optind;
+       ifaces = discover_interfaces(ifc, ifv);
        for (iface = ifaces; iface; iface = iface->next)
                init_state(iface, argc, argv);
+       if (!ifaces && ifc == 1) {
+               logger(LOG_ERR, "interface `%s' does not exist", ifv[0]);
+               exit(EXIT_FAILURE);
+       }
        start_eloop();
        /* NOTREACHED */
 }
index ccb7ba2fb216ab2accf923ef78bbe4f2fbdfde78..608a41d09f5e6f382275a3d36394cc163c371809 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
@@ -105,6 +105,7 @@ struct interface
 };
 
 extern int pidfd;
+
 int handle_args(int, char **);
 void handle_exit_timeout(void *);
 void send_request(void *);
index bad76832ba7def589cfb8440b2d89cf6f3cc7d39..58aa10ffc1ca05ad5dc62c9d0427641f3126f4c3 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -187,23 +187,29 @@ open_link_socket(void)
        int fd;
 
        fd = socket(PF_ROUTE, SOCK_RAW, 0);
-       if (fd != -1)
+       if (fd != -1) {
                set_cloexec(fd);
+               set_nonblock(fd);
+       }
        return fd;
 }
 
 #define BUFFER_LEN     2048
 int
-link_changed(int fd, const struct interface *ifaces)
+manage_link(int fd, struct interface *ifaces,
+           void (*if_carrier)(struct interface *),
+           void (*if_add)(const char *),
+           void (*if_remove)(struct interface *))
 {
        char buffer[2048], *p;
        ssize_t bytes;
        struct rt_msghdr *rtm;
+       struct if_announcemsghdr *ifa;
        struct if_msghdr *ifm;
-       const struct interface *iface;
+       struct interface *iface;
 
        for (;;) {
-               bytes = recv(fd, buffer, BUFFER_LEN, MSG_DONTWAIT);
+               bytes = read(fd, buffer, BUFFER_LEN);
                if (bytes == -1) {
                        if (errno == EAGAIN)
                                return 0;
@@ -216,12 +222,31 @@ link_changed(int fd, const struct interface *ifaces)
                     p += ((struct rt_msghdr *)p)->rtm_msglen)
                {
                        rtm = (struct rt_msghdr *)p;
-                       if (rtm->rtm_type != RTM_IFINFO)
-                               continue;
-                       ifm = (struct if_msghdr *)p;
-                       for (iface = ifaces; iface; iface = iface->next)
-                               if (ifm->ifm_index == if_nametoindex(iface->name))
-                                       return 1;
+                       switch(rtm->rtm_type) {
+                       case RTM_IFANNOUNCE:
+                               ifa = (struct if_announcemsghdr *)p;
+                               switch(ifa->ifan_what) {
+                               case IFAN_ARRIVAL:
+                                       if_add(ifa->ifan_name);
+                                       break;
+                               case IFAN_DEPARTURE:
+                                       for (iface = ifaces; iface; iface = iface->next)
+                                               if (strcmp(ifa->ifan_name, iface->name) == 0) {
+                                                       if_remove(iface);
+                                                       break;
+                                               }
+                                       break;
+                               }
+                               break;
+                       case RTM_IFINFO:
+                               ifm = (struct if_msghdr *)p;
+                               for (iface = ifaces; iface; iface = iface->next)
+                                       if (ifm->ifm_index == if_nametoindex(iface->name)) {
+                                               if_carrier(iface);
+                                               break;
+                                       }
+                               break;
+                       }
                }
        }
 }
diff --git a/net.h b/net.h
index bf8e4ba5aa4821cedb42276e515d609cb7f3fced..08e29efc51f36653a42d58dcc0e5b7edaf20bac7 100644 (file)
--- a/net.h
+++ b/net.h
@@ -149,6 +149,9 @@ ssize_t send_raw_packet(const struct interface *, int,
 ssize_t get_raw_packet(struct interface *, int, void *, ssize_t);
 
 int open_link_socket(void);
-int link_changed(int, const struct interface *);
+int manage_link(int, struct interface *,
+               void (*)(struct interface *),
+               void (*)(const char *),
+               void (*)(struct interface *));
 int carrier_status(const char *);
 #endif