odhcpd: only enable packet socket if really needed
authorSteven Barth <steven@midlink.org>
Mon, 14 Jul 2014 13:39:12 +0000 (15:39 +0200)
committerSteven Barth <steven@midlink.org>
Mon, 14 Jul 2014 13:39:44 +0000 (15:39 +0200)
src/ndp.c

index 50529b536f6fa4949d377ea819820e5b48266feb..44884be7395f83aa8c90c50d1f20eea393475c14 100644 (file)
--- a/src/ndp.c
+++ b/src/ndp.c
@@ -17,6 +17,7 @@
 #include <signal.h>
 #include <errno.h>
 
+#include <unistd.h>
 #include <arpa/inet.h>
 #include <sys/socket.h>
 #include <net/ethernet.h>
@@ -90,25 +91,6 @@ int init_ndp(void)
        send(rtnl_event.uloop.fd, &req2, sizeof(req2), MSG_DONTWAIT);
        odhcpd_register(&rtnl_event);
 
-
-       // Create socket for intercepting NDP
-       int sock = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
-                       htons(ETH_P_ALL)); // ETH_P_ALL for ingress + egress
-       if (sock < 0) {
-               syslog(LOG_ERR, "Unable to open packet socket: %s",
-                               strerror(errno));
-               return -1;
-       }
-
-       if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER,
-                       &bpf_prog, sizeof(bpf_prog))) {
-               syslog(LOG_ERR, "Failed to set BPF: %s", strerror(errno));
-               return -1;
-       }
-
-       ndp_event.uloop.fd = sock;
-       odhcpd_register(&ndp_event);
-
        // Open ICMPv6 socket
        ping_socket = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
        if (ping_socket < 0) {
@@ -201,6 +183,39 @@ int setup_ndp_interface(struct interface *iface, bool enable)
                }
        }
 
+       bool enable_packet = false;
+       struct interface *i;
+       list_for_each_entry(i, &interfaces, head) {
+               if (i == iface && !enable)
+                       continue;
+
+               if (i->ndp == RELAYD_RELAY)
+                       enable_packet = true;
+       }
+
+       if (enable_packet && ndp_event.uloop.fd < 0) {
+               // Create socket for intercepting NDP
+               int sock = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
+                               htons(ETH_P_ALL)); // ETH_P_ALL for ingress + egress
+               if (sock < 0) {
+                       syslog(LOG_ERR, "Unable to open packet socket: %s",
+                                       strerror(errno));
+                       return -1;
+               }
+
+               if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER,
+                               &bpf_prog, sizeof(bpf_prog))) {
+                       syslog(LOG_ERR, "Failed to set BPF: %s", strerror(errno));
+                       return -1;
+               }
+
+               ndp_event.uloop.fd = sock;
+               odhcpd_register(&ndp_event);
+       } else if (!enable_packet && ndp_event.uloop.fd >= 0) {
+               close(ndp_event.uloop.fd);
+               ndp_event.uloop.fd = -1;
+       }
+
        return 0;
 }