ubus: use safe iterator
[project/odhcpd.git] / src / ndp.c
index 89bcd3c..17ec8b4 100644 (file)
--- a/src/ndp.c
+++ b/src/ndp.c
@@ -111,6 +111,10 @@ int init_ndp(void)
 
        // Open ICMPv6 socket
        ping_socket = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
+       if (ping_socket < 0) {
+               syslog(LOG_ERR, "Unable to open raw socket: %s", strerror(errno));
+                       return -1;
+       }
 
        int val = 2;
        setsockopt(ping_socket, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val));
@@ -160,19 +164,37 @@ int setup_ndp_interface(struct interface *iface, bool enable)
 
                if (iface->static_ndp_len) {
                        char *entry = alloca(iface->static_ndp_len), *saveptr;
+                       if (!entry) {
+                               syslog(LOG_ERR, "Alloca failed for static NDP list");
+                               return -1;
+                       }
                        memcpy(entry, iface->static_ndp, iface->static_ndp_len);
 
                        for (entry = strtok_r(entry, " ", &saveptr); entry; entry = strtok_r(NULL, " ", &saveptr)) {
+                               char *sep;
                                struct ndp_neighbor *n = malloc(sizeof(*n));
+                               if (!n) {
+                                       syslog(LOG_ERR, "Malloc failed for static NDP-prefix %s", entry);
+                                       return -1;
+                               }
+
                                n->iface = iface;
                                n->timeout = 0;
 
-                               char ipbuf[INET6_ADDRSTRLEN];
-                               if (sscanf(entry, "%45s/%hhu", ipbuf, &n->len) < 2
-                                               || n->len > 128 || inet_pton(AF_INET6, ipbuf, &n->addr) != 1) {
+                               sep = strchr(entry, '/');
+                               if (!sep) {
+                                       free(n);
                                        syslog(LOG_ERR, "Invalid static NDP-prefix %s", entry);
                                        return -1;
                                }
+                               
+                               *sep = 0;
+                               n->len = atoi(sep + 1);
+                               if (inet_pton(AF_INET6, entry, &n->addr) != 1 || n->len > 128) {
+                                       free(n);
+                                       syslog(LOG_ERR, "Invalid static NDP-prefix %s/%s", entry, sep + 1);
+                                       return -1;
+                               }
 
                                list_add(&n->head, &neighbors);
                        }
@@ -225,7 +247,7 @@ static void handle_solicit(void *addr, void *data, size_t len,
 
        char ipbuf[INET6_ADDRSTRLEN];
        inet_ntop(AF_INET6, &req->nd_ns_target, ipbuf, sizeof(ipbuf));
-       syslog(LOG_NOTICE, "Got a NS for %s", ipbuf);
+       syslog(LOG_DEBUG, "Got a NS for %s", ipbuf);
 
        uint8_t mac[6];
        odhcpd_get_mac(iface, mac);
@@ -237,7 +259,7 @@ static void handle_solicit(void *addr, void *data, size_t len,
 
        struct ndp_neighbor *n = find_neighbor(&req->nd_ns_target, false);
        if (n && (n->iface || abs(n->timeout - now) < 5)) {
-               syslog(LOG_NOTICE, "%s is on %s", ipbuf,
+               syslog(LOG_DEBUG, "%s is on %s", ipbuf,
                                (n->iface) ? n->iface->ifname : "<pending>");
                if (!n->iface || n->iface == iface)
                        return;
@@ -355,41 +377,12 @@ static void free_neighbor(struct ndp_neighbor *n)
        --neighbor_count;
 }
 
-
-static bool match_neighbor(struct ndp_neighbor *n, struct in6_addr *addr)
-{
-       if (n->len <= 32)
-               return ntohl(n->addr.s6_addr32[0]) >> (32 - n->len) ==
-                               ntohl(addr->s6_addr32[0]) >> (32 - n->len);
-
-       if (n->addr.s6_addr32[0] != addr->s6_addr32[0])
-               return false;
-
-       if (n->len <= 64)
-               return ntohl(n->addr.s6_addr32[1]) >> (64 - n->len) ==
-                               ntohl(addr->s6_addr32[1]) >> (64 - n->len);
-
-       if (n->addr.s6_addr32[1] != addr->s6_addr32[1])
-               return false;
-
-       if (n->len <= 96)
-               return ntohl(n->addr.s6_addr32[2]) >> (96 - n->len) ==
-                               ntohl(addr->s6_addr32[2]) >> (96 - n->len);
-
-       if (n->addr.s6_addr32[2] != addr->s6_addr32[2])
-               return false;
-
-       return ntohl(n->addr.s6_addr32[3]) >> (128 - n->len) ==
-                       ntohl(addr->s6_addr32[3]) >> (128 - n->len);
-}
-
-
 static struct ndp_neighbor* find_neighbor(struct in6_addr *addr, bool strict)
 {
        time_t now = time(NULL);
        struct ndp_neighbor *n, *e;
        list_for_each_entry_safe(n, e, &neighbors, head) {
-               if ((!strict && match_neighbor(n, addr)) ||
+               if ((!strict && !odhcpd_bmemcmp(&n->addr, addr, n->len)) ||
                                (n->len == 128 && IN6_ARE_ADDR_EQUAL(&n->addr, addr)))
                        return n;
 
@@ -525,8 +518,8 @@ static void handle_rtnetlink(_unused void *addr, void *data, size_t len,
 
                /* TODO: See if this is required for optimal operation
                // Keep neighbor entries alive so we don't loose routes
+                */
                if (add && (ndm->ndm_state & NUD_STALE))
                        ping6(addr, iface);
-               */
        }
 }