]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Instead of opening link, ipv6, ipv6rs and ipv6ns sockets globally,
authorRoy Marples <roy@marples.name>
Fri, 15 Feb 2013 20:14:32 +0000 (20:14 +0000)
committerRoy Marples <roy@marples.name>
Fri, 15 Feb 2013 20:14:32 +0000 (20:14 +0000)
only open when the first link wanting this features needs it.
Hopefully fixes #263 and #264.

dhcpcd.c
ipv6.c
ipv6ns.c
ipv6rs.c

index 7046a4dc4941d0a99e00ecefff46faa81e76c34b..669eb9592dbb95e493837b6666a7933add1bfd5d 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -96,7 +96,7 @@ static char **ifv;
 static int ifc;
 static char *cffile;
 static char *pidfile;
-static int linkfd = -1, ipv6rsfd = -1, ipv6nsfd = -1;
+static int linkfd = -1;
 static uint8_t *packet;
 
 struct dhcp_op {
@@ -1268,10 +1268,19 @@ start_interface(void *arg)
                start_reboot(iface);
 }
 
+/* ARGSUSED */
+static void
+handle_link(_unused void *arg)
+{
+       if (manage_link(linkfd) == -1)
+               syslog(LOG_ERR, "manage_link: %m");
+}
+
 static void
 init_state(struct interface *iface, int argc, char **argv)
 {
        struct if_state *ifs;
+       struct if_options *ifo;
 
        if (iface->state)
                ifs = iface->state;
@@ -1282,6 +1291,23 @@ init_state(struct interface *iface, int argc, char **argv)
        ifs->reason = "PREINIT";
        ifs->nakoff = 0;
        configure_interface(iface, argc, argv);
+       ifo = ifs->options;
+
+       if (if_options->options & DHCPCD_LINK && linkfd == -1) {
+               linkfd = open_link_socket();
+               if (linkfd == -1)
+                       syslog(LOG_ERR, "open_link_socket: %m");
+               else
+                       add_event(linkfd, handle_link, NULL);
+       }
+
+       if (ifo->options & DHCPCD_IPV6RS && !check_ipv6(NULL))
+               options &= ~DHCPCD_IPV6RS;
+       if (ifo->options & DHCPCD_IPV6RS && ipv6_open() == -1) {
+               options &= ~DHCPCD_IPV6RS;
+               syslog(LOG_ERR, "ipv6_open: %m");
+       }
+
        if (!(options & DHCPCD_TEST))
                run_script(iface);
        /* We need to drop the leasefile so that start_interface
@@ -1452,14 +1478,6 @@ handle_ifa(int type, const char *ifname,
        }
 }
 
-/* ARGSUSED */
-static void
-handle_link(_unused void *arg)
-{
-       if (manage_link(linkfd) == -1)
-               syslog(LOG_ERR, "manage_link: %m");
-}
-
 static void
 if_reboot(struct interface *iface, int argc, char **argv)
 {
@@ -2023,13 +2041,6 @@ main(int argc, char **argv)
                syslog(LOG_ERR, "init_socket: %m");
                exit(EXIT_FAILURE);
        }
-       if (if_options->options & DHCPCD_LINK) {
-               linkfd = open_link_socket();
-               if (linkfd == -1)
-                       syslog(LOG_ERR, "open_link_socket: %m");
-               else
-                       add_event(linkfd, handle_link, NULL);
-       }
 
 #if 0
        if (options & DHCPCD_IPV6RS && disable_rtadv() == -1) {
@@ -2038,32 +2049,6 @@ main(int argc, char **argv)
        }
 #endif
 
-       if (options & DHCPCD_IPV6RS && !check_ipv6(NULL))
-               options &= ~DHCPCD_IPV6RS;
-       if (options & DHCPCD_IPV6RS && ipv6_open() == -1) {
-               options &= ~DHCPCD_IPV6RS;
-               syslog(LOG_ERR, "ipv6_open: %m");
-       }
-       if (options & DHCPCD_IPV6RS) {
-               ipv6rsfd = ipv6rs_open();
-               if (ipv6rsfd == -1) {
-                       syslog(LOG_ERR, "ipv6rs: %m");
-                       options &= ~DHCPCD_IPV6RS;
-               } else {
-                       add_event(ipv6rsfd, ipv6rs_handledata, NULL);
-//                     atexit(restore_rtadv);
-               }
-               if (options & DHCPCD_IPV6RA_OWN ||
-                   options & DHCPCD_IPV6RA_OWN_DEFAULT)
-               {
-                       ipv6nsfd = ipv6ns_open();
-                       if (ipv6nsfd == -1)
-                               syslog(LOG_ERR, "ipv6nd: %m");
-                       else
-                               add_event(ipv6nsfd, ipv6ns_handledata, NULL);
-               }
-       }
-
        ifc = argc - optind;
        ifv = argv + optind;
 
diff --git a/ipv6.c b/ipv6.c
index c20d98adfad19449ba9c3f8d43d89fd8ead25ffc..971f84dafae76c7d6747172cf09383f48e35a342 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
+#include <unistd.h>
 
 #include "common.h"
 #include "configure.h"
@@ -47,7 +48,7 @@
 #  define s6_addr32 __u6_addr.__u6_addr32
 #endif
 
-int socket_afnet6;
+int socket_afnet6 = -1;
 static struct rt6head *routes;
 
 #ifdef DEBUG_MEMORY
@@ -67,11 +68,21 @@ ipv6_cleanup()
 int
 ipv6_open(void)
 {
+
+       if (socket_afnet6 != -1)
+               return socket_afnet6;
+
        socket_afnet6 = socket(AF_INET6, SOCK_DGRAM, 0);
        if (socket_afnet6 == -1)
                return -1;
        set_cloexec(socket_afnet6);
-       routes = xmalloc(sizeof(*routes));
+       routes = malloc(sizeof(*routes));
+       if (routes == NULL) {
+               close(socket_afnet6);
+               socket_afnet6 = -1;
+               return -1;
+       }
+
        TAILQ_INIT(routes);
 #ifdef DEBUG_MEMORY
        atexit(ipv6_cleanup);
index c66770c258d5939d68ebae94faa413668a649b59..8bfac4c852867502f94039ef42fc4f9823f82617 100644 (file)
--- a/ipv6ns.c
+++ b/ipv6ns.c
@@ -39,6 +39,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
+#include <unistd.h>
 
 #ifdef __linux__
 #  define _LINUX_IN6_H
@@ -59,7 +60,7 @@
 /* Debugging Neighbor Solicitations is a lot of spam, so disable it */
 //#define DEBUG_NS
 
-static int sock;
+static int sock = -1;
 static struct sockaddr_in6 from;
 static struct msghdr sndhdr;
 static struct iovec sndiov[2];
@@ -92,19 +93,19 @@ ipv6ns_open(void)
                return -1;
        on = 1;
        if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
-               &on, sizeof(on)) == -1)
-               return -1;
+           &on, sizeof(on)) == -1)
+               goto eexit;
 
        on = 1;
        if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
-               &on, sizeof(on)) == -1)
-               return -1;
+           &on, sizeof(on)) == -1)
+               goto eexit;
 
        ICMP6_FILTER_SETBLOCKALL(&filt);
        ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
        if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
-               &filt, sizeof(filt)) == -1)
-               return -1;
+           &filt, sizeof(filt)) == -1)
+               goto eexit;
 
        set_cloexec(sock);
 #if DEBUG_MEMORY
@@ -112,17 +113,17 @@ ipv6ns_open(void)
 #endif
 
        len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
-       sndbuf = xzalloc(len);
+       sndbuf = calloc(1, len);
        if (sndbuf == NULL)
-               return -1;
+               goto eexit;
        sndhdr.msg_namelen = sizeof(struct sockaddr_in6);
        sndhdr.msg_iov = sndiov;
        sndhdr.msg_iovlen = 1;
        sndhdr.msg_control = sndbuf;
        sndhdr.msg_controllen = len;
-       rcvbuf = xzalloc(len);
+       rcvbuf = calloc(1, len);
        if (rcvbuf == NULL)
-               return -1;
+               goto eexit;
        rcvhdr.msg_name = &from;
        rcvhdr.msg_namelen = sizeof(from);
        rcvhdr.msg_iov = rcviov;
@@ -132,6 +133,15 @@ ipv6ns_open(void)
        rcviov[0].iov_base = ansbuf;
        rcviov[0].iov_len = sizeof(ansbuf);
        return sock;
+
+eexit:
+       close(sock);
+       sock = -1;
+       free(sndbuf);
+       sndbuf = NULL;
+       free(rcvbuf);
+       rcvbuf = NULL;
+       return -1;
 }
 
 static int
@@ -142,7 +152,7 @@ ipv6ns_makeprobe(struct ra *rap)
 
        free(rap->ns);
        rap->nslen = sizeof(*ns) + ROUNDUP8(rap->iface->hwlen + 2);
-       rap->ns = xzalloc(rap->nslen);
+       rap->ns = calloc(1, rap->nslen);
        if (rap->ns == NULL)
                return -1;
        ns = (struct nd_neighbor_solicit *)(void *)rap->ns;
@@ -182,9 +192,17 @@ ipv6ns_sendprobe(void *arg)
        int hoplimit = HOPLIMIT;
        struct timeval tv, rtv;
 
-       if (!rap->ns) {
-               if (ipv6ns_makeprobe(rap) == -1)
+       if (sock == -1) {
+               if (ipv6ns_open() == -1) {
+                       syslog(LOG_ERR, "%s: ipv6ns_open: %m", __func__);
                        return;
+               }
+               add_event(sock, ipv6ns_handledata, NULL);
+       }
+
+       if (!rap->ns && ipv6ns_makeprobe(rap) == -1) {
+               syslog(LOG_ERR, "%s: ipv6ns_makeprobe: %m", __func__);
+               return;
        }
 
        memset(&dst, 0, sizeof(dst));
@@ -220,7 +238,8 @@ ipv6ns_sendprobe(void *arg)
            rap->iface->name, rap->sfrom);
 #endif
        if (sendmsg(sock, &sndhdr, 0) == -1)
-               syslog(LOG_ERR, "%s: sendmsg: %m", rap->iface->name);
+               syslog(LOG_ERR, "%s: %s: sendmsg: %m",
+                   __func__, rap->iface->name);
 
 
        ms_to_tv(&tv, rap->retrans ? rap->retrans : RETRANS_TIMER);
index 8e371a8f691d5a6a13505cd0fbb51f8ea6713d63..c6b4102ac79611b9cbb3081280f223d50ba57d43 100644 (file)
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -38,6 +38,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
+#include <unistd.h>
 
 #ifdef __linux__
 #  define _LINUX_IN6_H
@@ -101,7 +102,7 @@ struct nd_opt_dnssl {               /* DNSSL option RFC 6106 */
 
 struct rahead ipv6_routers = TAILQ_HEAD_INITIALIZER(ipv6_routers);
 
-static int sock;
+static int sock = -1;
 static struct sockaddr_in6 allrouters, from;
 static struct msghdr sndhdr;
 static struct iovec sndiov[2];
@@ -129,31 +130,32 @@ ipv6rs_open(void)
        int len;
        struct icmp6_filter filt;
 
+       sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+       if (sock == -1)
+               return -1;
+
        memset(&allrouters, 0, sizeof(allrouters));
        allrouters.sin6_family = AF_INET6;
 #ifdef SIN6_LEN
        allrouters.sin6_len = sizeof(allrouters);
 #endif
        if (inet_pton(AF_INET6, ALLROUTERS, &allrouters.sin6_addr.s6_addr) != 1)
-               return -1;
-       sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
-       if (sock == -1)
-               return -1;
+               goto eexit;
        on = 1;
        if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
                &on, sizeof(on)) == -1)
-               return -1;
+               goto eexit;
 
        on = 1;
        if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
                &on, sizeof(on)) == -1)
-               return -1;
+               goto eexit;
 
        ICMP6_FILTER_SETBLOCKALL(&filt);
        ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
        if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
                &filt, sizeof(filt)) == -1)
-               return -1;
+               goto eexit;
 
        set_cloexec(sock);
 #if DEBUG_MEMORY
@@ -161,17 +163,17 @@ ipv6rs_open(void)
 #endif
 
        len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
-       sndbuf = xzalloc(len);
+       sndbuf = calloc(1, len);
        if (sndbuf == NULL)
-               return -1;
+               goto eexit;
        sndhdr.msg_namelen = sizeof(struct sockaddr_in6);
        sndhdr.msg_iov = sndiov;
        sndhdr.msg_iovlen = 1;
        sndhdr.msg_control = sndbuf;
        sndhdr.msg_controllen = len;
-       rcvbuf = xzalloc(len);
+       rcvbuf = calloc(1, len);
        if (rcvbuf == NULL)
-               return -1;
+               goto eexit;
        rcvhdr.msg_name = &from;
        rcvhdr.msg_namelen = sizeof(from);
        rcvhdr.msg_iov = rcviov;
@@ -181,6 +183,15 @@ ipv6rs_open(void)
        rcviov[0].iov_base = ansbuf;
        rcviov[0].iov_len = sizeof(ansbuf);
        return sock;
+
+eexit:
+       close(sock);
+       sock = -1;
+       free(sndbuf);
+       sndbuf = NULL;
+       free(rcvbuf);
+       rcvbuf = NULL;
+       return -1;
 }
 
 static int
@@ -462,7 +473,7 @@ ipv6rs_handledata(_unused void *arg)
                syslog(LOG_ERR, "RA for unexpected interface from %s", sfrom);
                return;
        }
-       if (!(ifp->options->options & DHCPCD_IPV6RS)) {
+       if (!(ifp->state->options->options & DHCPCD_IPV6RS)) {
 #ifdef DEBUG_RS
                syslog(LOG_DEBUG, "%s: unexpected RA from %s",
                    ifp->name, sfrom);
@@ -798,8 +809,8 @@ ipv6rs_handledata(_unused void *arg)
 
        /* If we're owning the RA then we need to try and ensure the
         * router is actually reachable */
-       if (options & DHCPCD_IPV6RA_OWN ||
-           options & DHCPCD_IPV6RA_OWN_DEFAULT)
+       if (ifp->state->options->options & DHCPCD_IPV6RA_OWN ||
+           ifp->state->options->options & DHCPCD_IPV6RA_OWN_DEFAULT)
        {
                rap->nsprobes = 0;
                ipv6ns_sendprobe(rap);
@@ -1067,19 +1078,33 @@ ipv6rs_start(struct interface *ifp)
 {
        struct rs_state *state;
 
+       if (sock == -1) {
+               if (ipv6rs_open() == -1) {
+                       syslog(LOG_ERR, "%s: ipv6rs_open: %m", __func__);
+                       return -1;
+               }
+               add_event(sock, ipv6rs_handledata, NULL);
+       }
+
        delete_timeout(NULL, ifp);
 
        state = RS_STATE(ifp);
        if (state == NULL) {
-               ifp->if_data[IF_DATA_IPV6RS] = xzalloc(sizeof(*state));
+               ifp->if_data[IF_DATA_IPV6RS] = calloc(1, sizeof(*state));
                state = RS_STATE(ifp);
+               if (state == NULL) {
+                       syslog(LOG_ERR, "%s: %m", __func__);
+                       return -1;
+               }
        }
 
        /* Always make a new probe as the underlying hardware
         * address could have changed. */
        ipv6rs_makeprobe(ifp);
-       if (state->rs == NULL)
+       if (state->rs == NULL) {
+               syslog(LOG_ERR, "%s: ipv6rs_makeprobe: %m", __func__);
                return -1;
+       }
 
        state->rsprobes = 0;
        ipv6rs_sendprobe(ifp);