Implement str_to_addr() and unit test.
authorEmil Mikulic <emikulic@gmail.com>
Tue, 10 May 2011 12:51:49 +0000 (22:51 +1000)
committerEmil Mikulic <emikulic@gmail.com>
Sat, 28 May 2011 10:10:52 +0000 (20:10 +1000)
addr.c
addr.h
test_addr.c [new file with mode: 0644]

diff --git a/addr.c b/addr.c
index 2291176..055e12b 100644 (file)
--- a/addr.c
+++ b/addr.c
@@ -11,6 +11,7 @@
 
 #include <assert.h>
 #include <string.h> /* for memcmp */
+#include <netdb.h> /* for getaddrinfo */
 
 int addr_equal(const struct addr * const a, const struct addr * const b)
 {
@@ -38,4 +39,32 @@ const char *addr_to_str(const struct addr * const a)
    }
 }
 
+int str_to_addr(const char *s, struct addr *a)
+{
+   struct addrinfo hints, *ai;
+   int ret;
+
+   memset(&hints, 0, sizeof(hints));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_flags = AI_NUMERICHOST;
+
+   if ((ret = getaddrinfo(s, NULL, &hints, &ai)) != 0)
+      return (ret);
+
+   if (ai->ai_family == AF_INET) {
+      a->family = IPv4;
+      a->ip.v4 = ((const struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr;
+   } else if (ai->ai_family == AF_INET6) {
+      a->family = IPv6;
+      memcpy(&(a->ip.v6),
+             ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr,
+             sizeof(a->ip.v6));
+   } else {
+      ret = EAI_FAMILY;
+   }
+
+   freeaddrinfo(ai);
+   return (ret);
+}
+
 /* vim:set ts=3 sw=3 tw=78 et: */
diff --git a/addr.h b/addr.h
index 55c58c4..1edf02d 100644 (file)
--- a/addr.h
+++ b/addr.h
@@ -23,5 +23,8 @@ 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);
 
+/* Returns 0 on success, gai_strerror() code otherwise. */
+int str_to_addr(const char *s, struct addr *a);
+
 #endif
 /* vim:set ts=3 sw=3 tw=78 et: */
diff --git a/test_addr.c b/test_addr.c
new file mode 100644 (file)
index 0000000..4780ccd
--- /dev/null
@@ -0,0 +1,77 @@
+/* darkstat 3
+ * copyright (c) 2011 Emil Mikulic.
+ *
+ * test_addr.c: tests for addr module
+ *
+ * You may use, modify and redistribute this file under the terms of the
+ * GNU General Public License version 2. (see COPYING.GPL)
+ */
+
+#include "addr.h"
+
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+void test(const char *in, const char *expect_out, int expect_result)
+{
+   struct addr a;
+   int success, ret;
+   const char *out;
+
+   success = 1;
+   ret = str_to_addr(in, &a);
+
+   if (ret != expect_result)
+      success = 0;
+
+   if (ret == 0)
+      out = addr_to_str(&a);
+   else
+      out = "(error)";
+
+   if (expect_out && (strcmp(out, expect_out) != 0))
+         success = 0;
+
+   printf("%s:", success ? "PASS" : "FAIL");
+
+   printf(" \"%s\" -> \"%s\"", in, out);
+   if (expect_out && (strcmp(out, expect_out) != 0))
+      printf(" (expected \"%s\")", expect_out);
+
+   if (ret != expect_result)
+      printf(" [ret %d, expected %d]", ret, expect_result);
+
+   if (ret != 0)
+      printf(" [err: %s]", gai_strerror(ret));
+   
+   printf("\n");
+}
+
+int main()
+{
+   test("0.0.0.0", "0.0.0.0", 0);
+   test("192.168.1.2", "192.168.1.2", 0);
+
+   test("::", "::", 0);
+   test("::0", "::", 0);
+   test("::00", "::", 0);
+   test("::000", "::", 0);
+   test("::0000", "::", 0);
+
+   test("::1", "::1", 0);
+   test("::01", "::1", 0);
+   test("::001", "::1", 0);
+   test("::0001", "::1", 0);
+
+   test("2404:6800:8004::68", "2404:6800:8004::68", 0);
+   test("2404:6800:8004:0000:0000:0000:0000:0068", "2404:6800:8004::68", 0);
+
+   test(".", NULL, EAI_NONAME);
+   test(":", NULL, EAI_NONAME);
+   test("23.75.345.200", NULL, EAI_NONAME);
+
+   return 0;
+}
+
+/* vim:set ts=3 sw=3 tw=78 et: */