Check subnet mask's sanity
authorJoseph C. Lehner <joseph.c.lehner@gmail.com>
Sat, 19 Nov 2016 12:02:29 +0000 (13:02 +0100)
committerJoseph C. Lehner <joseph.c.lehner@gmail.com>
Sat, 19 Nov 2016 12:02:29 +0000 (13:02 +0100)
nmrp.c
nmrpd.h
util.c

diff --git a/nmrp.c b/nmrp.c
index da665cfa856aa892e89f3350ed53799bf010205a..c1bfb9c747936bd60d79e33219a391d93cf74748 100644 (file)
--- a/nmrp.c
+++ b/nmrp.c
@@ -430,7 +430,9 @@ int nmrp_do(struct nmrpd_args *args)
                return 1;
        }
 
-       if ((ipconf.mask.s_addr = inet_addr(args->ipmask)) == INADDR_NONE) {
+       ipconf.mask.s_addr = inet_addr(args->ipmask);
+       if (ipconf.mask.s_addr == INADDR_NONE
+                       || netmask(bitcount(ipconf.mask.s_addr)) != ipconf.mask.s_addr) {
                fprintf(stderr, "Invalid subnet mask '%s'.\n", args->ipmask);
                return 1;
        }
diff --git a/nmrpd.h b/nmrpd.h
index e061155b83dc1370bab3dc8cfbb9bd4d09c8a1fe..af9699ac3a2713a753c08be73aefc700c56e25fd 100644 (file)
--- a/nmrpd.h
+++ b/nmrpd.h
@@ -133,4 +133,6 @@ int ethsock_ip_del(struct ethsock *sock, struct ethsock_ip_undo **undo);
 
 time_t time_monotonic();
 char *lltostr(long long ll, int base);
+uint32_t bitcount(uint32_t n);
+uint32_t netmask(uint32_t count);
 #endif
diff --git a/util.c b/util.c
index 4422442dea94197604636dcd1f4e6d12fa947b3d..a1b2c521b6d5f10000bdd6263a5c9354f4a9c5d2 100644 (file)
--- a/util.c
+++ b/util.c
@@ -35,3 +35,17 @@ char *lltostr(long long ll, int base)
        snprintf(buf, sizeof(buf) - 1, (base == 16 ? "%llx" : (base == 8 ? "%llo" : "%lld")), ll);
        return buf;
 }
+
+uint32_t bitcount(uint32_t n)
+{
+       uint32_t c;
+       for (c = 0; n; ++c) {
+               n &= n - 1;
+       }
+       return c;
+}
+
+uint32_t netmask(uint32_t count)
+{
+       return htonl(count <= 32 ? 0xffffffff << (32 - count) : 0);
+}