[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r10420: Unit tests [and debugging] for tor_inet_ntop() and tor_inet_ (in tor/trunk: . src/common src/or)



Author: nickm
Date: 2007-05-31 14:48:25 -0400 (Thu, 31 May 2007)
New Revision: 10420

Modified:
   tor/trunk/
   tor/trunk/src/common/compat.c
   tor/trunk/src/or/test.c
Log:
 r13101@catbus:  nickm | 2007-05-31 12:57:42 -0400
 Unit tests [and debugging] for tor_inet_ntop() and tor_inet_pton()



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r13101] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/src/common/compat.c
===================================================================
--- tor/trunk/src/common/compat.c	2007-05-31 18:36:00 UTC (rev 10419)
+++ tor/trunk/src/common/compat.c	2007-05-31 18:48:25 UTC (rev 10420)
@@ -821,7 +821,6 @@
 #ifdef HAVE_INET_NTOP
   return inet_ntop(af,src,dst,(socklen_t)len);
 #else
-  /* XXXX needs testing. !!!! */
   if (af == AF_INET) {
     if (tor_inet_ntoa(src, dst, len) < 0)
       return NULL;
@@ -839,9 +838,15 @@
     if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
         words[4] == 0 && (words[5] == 0 || words[5] == 0xffff) && words[6]) {
       /* This is an IPv4 address. */
-      tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
-                   addr->s6_addr[12], addr->s6_addr[13],
-                   addr->s6_addr[14], addr->s6_addr[15]);
+      if (words[5] == 0) {
+        tor_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
+                     addr->s6_addr[12], addr->s6_addr[13],
+                     addr->s6_addr[14], addr->s6_addr[15]);
+      } else {
+        tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
+                     addr->s6_addr[12], addr->s6_addr[13],
+                     addr->s6_addr[14], addr->s6_addr[15]);
+      }
       if (strlen(buf) > len)
         return NULL;
       strlcpy(dst, buf, len);
@@ -863,11 +868,15 @@
         ++i;
       }
     }
+    if (longestGapLen<=1)
+      longestGapPos = -1;
+
     cp = buf;
     for (i = 0; i < 8; ++i) {
       if (words[i] == 0 && longestGapPos == i) {
+        if (i == 0)
+          *cp++ = ':';
         *cp++ = ':';
-        *cp++ = ':';
         while (i < 8 && words[i] == 0)
           ++i;
         --i; /* to compensate for loop increment. */
@@ -878,6 +887,7 @@
           *cp++ = ':';
       }
     }
+    *cp = '\0';
     if (strlen(buf) > len)
       return NULL;
     strlcpy(dst, buf, len);
@@ -903,13 +913,11 @@
 #ifdef HAVE_INET_PTON
   return inet_pton(af, src, dst);
 #else
-  /* XXXX needs testing. !!!! */
   if (af == AF_INET) {
     return tor_inet_aton(src, dst);
   } else if (af == AF_INET6) {
     struct in6_addr *out = dst;
     uint16_t words[8];
-    struct in_addr in;
     int gapPos = -1, i, setWords=0;
     const char *dot = strchr(src, '.');
     const char *eow; /* end of words. */
@@ -918,16 +926,25 @@
     else if (!dot)
       eow = src+strlen(src);
     else {
-      uint32_t a;
+      int byte1,byte2,byte3,byte4;
+      char more;
       for (eow = dot-1; eow >= src && TOR_ISDIGIT(*eow); --eow)
         ;
       ++eow;
 
-      if (tor_inet_aton(eow, &in) != 1)
+      /* We use "scanf" because some platform inet_aton()s are too lax
+       * about IPv4 addresses of the form "1.2.3" */
+      if (sscanf(eow, "%d.%d.%d.%d%c", &byte1,&byte2,&byte3,&byte4,&more) != 4)
         return 0;
-      a = ntohl(in.s_addr);
-      words[6] = a >> 16;
-      words[7] = a & 0xFFFF;
+
+      if (byte1 > 255 || byte1 < 0 ||
+          byte2 > 255 || byte2 < 0 ||
+          byte3 > 255 || byte3 < 0 ||
+          byte4 > 255 || byte4 < 0)
+        return 0;
+
+      words[6] = (byte1<<8) | byte2;
+      words[7] = (byte3<<8) | byte4;
       setWords += 2;
     }
 
@@ -948,7 +965,7 @@
         words[i++] = (uint16_t)r;
         setWords++;
         src = next;
-        if (*src != ':')
+        if (*src != ':' && src != eow)
           return 0;
         ++src;
       } else if (*src == ':' && i > 0 && gapPos==-1) {
@@ -966,9 +983,12 @@
       return 0;
 
     if (gapPos >= 0) {
+      int nToMove = setWords - (dot ? 2 : 0) - gapPos;
       int gapLen = 8 - setWords;
+      tor_assert(nToMove >= 0);
       memmove(&words[gapPos+gapLen], &words[gapPos],
-              sizeof(uint16_t)*(8-gapPos));
+              sizeof(uint16_t)*nToMove);
+      memset(&words[gapPos], 0, sizeof(uint16_t)*gapLen);
     }
     for (i = 0; i < 8; ++i) {
       out->s6_addr[2*i  ] = words[i] >> 8;

Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c	2007-05-31 18:36:00 UTC (rev 10419)
+++ tor/trunk/src/or/test.c	2007-05-31 18:48:25 UTC (rev 10420)
@@ -310,6 +310,7 @@
   test_memeq(str, (char*)_buf_peek_raw_buffer(buf), 10); /* XXX Check rest. */
   test_eq(eof, 0);
 
+
   i = read_to_buf(s, 1024, buf, &eof);
   test_eq(i, 0);
   test_eq(buf_capacity(buf), MAX_BUF_SIZE);
@@ -969,6 +970,127 @@
 }
 
 static void
+_test_eq_ip6(struct in6_addr *a, struct in6_addr *b, const char *e1,
+             const char *e2, int line)
+{
+  int i;
+  int ok = 1;
+  for (i = 0; i < 16; ++i) {
+    if (a->s6_addr[i] != b->s6_addr[i]) {
+      ok = 0;
+      break;
+    }
+  }
+  if (ok) {
+    printf("."); fflush(stdout);
+  } else {
+    char buf1[128], *cp1;
+    char buf2[128], *cp2;
+    have_failed = 1;
+    cp1 = buf1; cp2 = buf2;
+    for (i=0; i<16; ++i) {
+      tor_snprintf(cp1, sizeof(buf1)-(cp1-buf1), "%02x", a->s6_addr[i]);
+      tor_snprintf(cp2, sizeof(buf2)-(cp2-buf2), "%02x", b->s6_addr[i]);
+      cp1 += 2; cp2 += 2;
+      if ((i%2)==1 && i != 15) {
+        *cp1++ = ':';
+        *cp2++ = ':';
+      }
+    }
+    *cp1 = *cp2 = '\0';
+    printf("Line %d: assertion failed: (%s == %s)\n"
+           "      %s != %s\n", line, e1, e2, buf1, buf2);
+    fflush(stdout);
+  }
+}
+#define test_eq_ip6(a,b) _test_eq_ip6((a),(b),#a,#b,__LINE__)
+
+#define test_pton6_same(a,b) do {                 \
+    r = tor_inet_pton(AF_INET6, a, &a1);         \
+    test_assert(r==1);                           \
+    r = tor_inet_pton(AF_INET6, b, &a2);         \
+    test_assert(r==1);                           \
+    test_eq_ip6(&a1,&a2);                        \
+  } while(0)
+
+#define test_pton6_bad(a)                       \
+  test_eq(0, tor_inet_pton(AF_INET6, a, &a1))
+
+#define test_ntop6_reduces(a,b) do {                                    \
+    r = tor_inet_pton(AF_INET6, a, &a1);                                \
+    test_assert(r==1);                                                  \
+    test_streq(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), b);      \
+    r = tor_inet_pton(AF_INET6, b, &a2);                                \
+    test_assert(r==1);                                                  \
+    test_eq_ip6(&a1, &a2);                                              \
+  } while (0)
+
+static void
+test_ip6_helpers(void)
+{
+  char buf[64];
+  struct in6_addr a1, a2;
+  int r, i;
+  //  struct in_addr b1, b2;
+  /* Test tor_inet_ntop and tor_inet_pton: IPv6 */
+
+  /* === Test pton: valid af_inet6 */
+  /* Simple, valid parsing. */
+  r = tor_inet_pton(AF_INET6,
+                    "0102:0304:0506:0708:090A:0B0C:0D0E:0F10", &a1);
+  test_assert(r==1);
+  for (i=0;i<16;++i) { test_eq(i+1, (int)a1.s6_addr[i]); }
+  /* ipv4 ending. */
+  test_pton6_same("0102:0304:0506:0708:090A:0B0C:0D0E:0F10",
+                  "0102:0304:0506:0708:090A:0B0C:13.14.15.16");
+  /* shortened words. */
+  test_pton6_same("0001:0099:BEEF:0000:0123:FFFF:0001:0001",
+                  "1:99:BEEF:0:0123:FFFF:1:1");
+  /* zeros at the beginning */
+  test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001",
+                  "::9:c0a8:1:1");
+  test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001",
+                  "::9:c0a8:0.1.0.1");
+  /* zeros in the middle. */
+  test_pton6_same("fe80:0000:0000:0000:0202:1111:0001:0001",
+                  "fe80::202:1111:1:1");
+  /* zeros at the end. */
+  test_pton6_same("1000:0001:0000:0007:0000:0000:0000:0000",
+                  "1000:1:0:7::");
+
+  /* === Test ntop: af_inet6 */
+  test_ntop6_reduces("0:0:0:0:0:0:0:0", "::");
+
+  test_ntop6_reduces("0001:0099:BEEF:0000:0123:FFFF:0001:0001",
+                     "1:99:beef:0:123:ffff:1:1");
+
+  test_ntop6_reduces("0:0:0:0:0:0:c0a8:0101", "::192.168.1.1");
+  test_ntop6_reduces("0:0:0:0:0:ffff:c0a8:0101", "::ffff:192.168.1.1");
+  test_ntop6_reduces("0000:0000:0000:0000:0009:C0A8:0001:0001",
+                     "::9:c0a8:1:1");
+  test_ntop6_reduces("fe80:0000:0000:0000:0202:1111:0001:0001",
+                     "fe80::202:1111:1:1");
+  test_ntop6_reduces("1000:0001:0000:0007:0000:0000:0000:0000",
+                     "1000:1:0:7::");
+
+  /* === Test pton: invalid in6. */
+  test_pton6_bad("foobar.");
+  test_pton6_bad("55555::");
+  test_pton6_bad("9:-60::");
+  test_pton6_bad("1:2:33333:4:0002:3::");
+  // test_pton6_bad("1:2:3333:4:00002:3::"); //XXXX not bad.
+  test_pton6_bad("1:2:3333:4:fish:3::");
+  test_pton6_bad("1:2:3:4:5:6:7:8:9");
+  test_pton6_bad("1:2:3:4:5:6:7");
+  test_pton6_bad("1:2:3:4:5:6:1.2.3.4.5");
+  test_pton6_bad("1:2:3:4:5:6:1.2.3");
+  test_pton6_bad("::1.2.3");
+  test_pton6_bad("::1.2.3.4.5");
+  test_pton6_bad("99");
+  test_pton6_bad("");
+}
+
+static void
 test_smartlist(void)
 {
   smartlist_t *sl;
@@ -2277,6 +2399,7 @@
   test_crypto_dh();
   test_crypto_s2k();
   puts("\n========================= Util ============================");
+  test_ip6_helpers();
   test_gzip();
   test_util();
   test_smartlist();