Implement addr_mask and addr_inside and tests.
authorEmil Mikulic <emikulic@gmail.com>
Tue, 10 May 2011 13:28:21 +0000 (23:28 +1000)
committerEmil Mikulic <emikulic@gmail.com>
Sat, 28 May 2011 10:10:52 +0000 (20:10 +1000)
addr.c
addr.h
test_addr.c

diff --git a/addr.c b/addr.c
index 055e12b..dc23e32 100644 (file)
--- a/addr.c
+++ b/addr.c
@@ -67,4 +67,31 @@ int str_to_addr(const char *s, struct addr *a)
    return (ret);
 }
 
+void addr_mask(struct addr *a, const struct addr * const mask)
+{
+   assert(a->family == mask->family);
+   if (a->family == IPv4)
+      a->ip.v4 &= mask->ip.v4;
+   else {
+      size_t i;
+
+      assert(a->family == IPv6);
+      for (i=0; i<sizeof(a->ip.v6.s6_addr); i++)
+         a->ip.v6.s6_addr[i] &= mask->ip.v6.s6_addr[i];
+   }
+}
+
+int addr_inside(const struct addr * const a,
+   const struct addr * const net, const struct addr * const mask)
+{
+   struct addr masked;
+
+   assert(a->family == net->family);
+   assert(a->family == mask->family);
+
+   masked = *a;
+   addr_mask(&masked, mask);
+   return (addr_equal(&masked, net));
+}
+
 /* vim:set ts=3 sw=3 tw=78 et: */
diff --git a/addr.h b/addr.h
index 1edf02d..2fd2ca1 100644 (file)
--- a/addr.h
+++ b/addr.h
@@ -22,6 +22,9 @@ struct addr {
 
 int addr_equal(const struct addr * const a, const struct addr * const b);
 const char *addr_to_str(const struct addr * const a);
+void addr_mask(struct addr *a, const struct addr * const mask);
+int addr_inside(const struct addr * const a,
+   const struct addr * const net, const struct addr * const mask);
 
 /* Returns 0 on success, gai_strerror() code otherwise. */
 int str_to_addr(const char *s, struct addr *a);
index 4780ccd..63f23ca 100644 (file)
@@ -48,6 +48,19 @@ void test(const char *in, const char *expect_out, int expect_result)
    printf("\n");
 }
 
+void test_inside(const char *a, const char *net, const char *mask, int expect)
+{
+   struct addr aa, anet, amask;
+
+   str_to_addr(a, &aa);
+   str_to_addr(net, &anet);
+   str_to_addr(mask, &amask);
+
+   printf("%s: %s in %s/%s\n",
+      addr_inside(&aa, &anet, &amask) ? "PASS" : "FAIL",
+      a, net, mask);
+}
+
 int main()
 {
    test("0.0.0.0", "0.0.0.0", 0);
@@ -71,6 +84,11 @@ int main()
    test(":", NULL, EAI_NONAME);
    test("23.75.345.200", NULL, EAI_NONAME);
 
+   test_inside("192.168.1.2", "192.168.0.0", "255.255.0.0", 1);
+   test_inside("2001:0200::3eff:feb1:44d7",
+               "2001:0200::",
+               "ffff:ffff::", 1);
+
    return 0;
 }