diff --git a/src/common/address.c b/src/common/address.c
index d0c2d5e..2803540 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -53,9 +53,9 @@
 #include <assert.h>
 
 /** Convert the tor_addr_t in <b>a</b>, with port in <b>port</b>, into a
- * sockaddr object in *<b>sa_out</b> of object size <b>len</b>.  If not enough
- * room is available in sa_out, or on error, return 0.  On success, return
- * the length of the sockaddr.
+ * sockaddr_storage object in *<b>sa_out</b> of object size <b>len</b>.
+ * If not enough room is available in sa_out, or on error, return 0.
+ * On success, return the length of the sockaddr.
  *
  * Interface note: ordinarily, we return -1 for error.  We can't do that here,
  * since socklen_t is unsigned on some platforms.
@@ -63,18 +63,24 @@
 socklen_t
 tor_addr_to_sockaddr(const tor_addr_t *a,
                      uint16_t port,
-                     struct sockaddr *sa_out,
+                     struct sockaddr_storage *sa_out,
                      socklen_t len)
 {
+  /*
+   * Require sockaddr_storage to be used throughout the code
+   * as that is the only way to be future proof
+   * We could swap tor_addr_t with sockaddr_storage completely actually
+   */
   sa_family_t family = tor_addr_family(a);
+  tor_assert(len == sizeof(*sa_out));
+  memset(sa_out, 0, len);
   if (family == AF_INET) {
     struct sockaddr_in *sin;
-    if (len < (int)sizeof(struct sockaddr_in))
+    if (len < (int)sizeof(*sin))
       return 0;
     sin = (struct sockaddr_in *)sa_out;
-    memset(sin, 0, sizeof(struct sockaddr_in));
 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
-    sin->sin_len = sizeof(struct sockaddr_in);
+    sin->sin_len = sizeof(*sin);
 #endif
     sin->sin_family = AF_INET;
     sin->sin_port = htons(port);
@@ -82,17 +88,16 @@ tor_addr_to_sockaddr(const tor_addr_t *a,
     return sizeof(struct sockaddr_in);
   } else if (family == AF_INET6) {
     struct sockaddr_in6 *sin6;
-    if (len < (int)sizeof(struct sockaddr_in6))
+    if (len < (int)sizeof(*sin6))
       return 0;
     sin6 = (struct sockaddr_in6 *)sa_out;
-    memset(sin6, 0, sizeof(struct sockaddr_in6));
 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
-    sin6->sin6_len = sizeof(struct sockaddr_in6);
+    sin6->sin6_len = sizeof(*sin6);
 #endif
     sin6->sin6_family = AF_INET6;
     sin6->sin6_port = htons(port);
     memcpy(&sin6->sin6_addr, tor_addr_to_in6(a), sizeof(struct in6_addr));
-    return sizeof(struct sockaddr_in6);
+    return sizeof(*sin6);
   } else {
     return 0;
   }
@@ -123,33 +128,6 @@ tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa,
   return 0;
 }
 
-/** Return a newly allocated string holding the address described in
- * <b>sa</b>.  AF_UNIX, AF_UNSPEC, AF_INET, and AF_INET6 are supported. */
-char *
-tor_sockaddr_to_str(const struct sockaddr *sa)
-{
-  char address[TOR_ADDR_BUF_LEN];
-  char *result;
-  tor_addr_t addr;
-  uint16_t port;
-#ifdef HAVE_SYS_UN_H
-  if (sa->sa_family == AF_UNIX) {
-    struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
-    tor_asprintf(&result, "unix:%s", s_un->sun_path);
-    return result;
-  }
-#endif
-  if (sa->sa_family == AF_UNSPEC)
-    return tor_strdup("unspec");
-
-  if (tor_addr_from_sockaddr(&addr, sa, &port) < 0)
-    return NULL;
-  if (! tor_addr_to_str(address, &addr, sizeof(address), 1))
-    return NULL;
-  tor_asprintf(&result, "%s:%d", address, (int)port);
-  return result;
-}
-
 /** Set address <b>a</b> to the unspecified address.  This address belongs to
  * no family. */
 void
@@ -173,24 +151,20 @@ tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr)
   /* Perhaps eventually this should be replaced by a tor_getaddrinfo or
    * something.
    */
-  struct in_addr iaddr;
-  struct in6_addr iaddr6;
   tor_assert(name);
   tor_assert(addr);
   tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
   if (!*name) {
     /* Empty address is an error. */
     return -1;
-  } else if (tor_inet_pton(AF_INET, name, &iaddr)) {
+  } else if (tor_inet_pton(AF_INET, name, addr)) {
     /* It's an IPv4 IP. */
     if (family == AF_INET6)
       return -1;
-    tor_addr_from_in(addr, &iaddr);
     return 0;
-  } else if (tor_inet_pton(AF_INET6, name, &iaddr6)) {
+  } else if (tor_inet_pton(AF_INET6, name, addr)) {
     if (family == AF_INET)
       return -1;
-    tor_addr_from_in6(addr, &iaddr6);
     return 0;
   } else {
 #ifdef HAVE_GETADDRINFO
@@ -287,8 +261,7 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening)
 {
   uint32_t iph4 = 0;
   uint32_t iph6[4];
-  sa_family_t v_family;
-  v_family = tor_addr_family(addr);
+  sa_family_t v_family = tor_addr_family(addr);
 
   if (v_family == AF_INET) {
     iph4 = tor_addr_to_ipv4h(addr);
@@ -333,7 +306,7 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening)
 
   /* unknown address family... assume it's not safe for external use */
   /* rather than tor_assert(0) */
-  log_warn(LD_BUG, "tor_addr_is_internal() called with a non-IP address.");
+  log_warn(LD_BUG, "tor_addr_is_internal() called with a non-IPv%u (AF%u) address.", v_family == AF_INET6 ? 6 : 4, v_family);
   return 1;
 }
 
@@ -343,8 +316,11 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening)
  *  brackets.
  */
 const char *
-tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
+tor_addr_to_str(const tor_addr_t *addr, char *dest, size_t len, int decorate)
 {
+#ifdef HAVE_SYS_UN_H
+  struct sockaddr_un *s_un;
+#endif
   const char *ptr;
   tor_assert(addr && dest);
 
@@ -366,6 +342,17 @@ tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
         ptr = dest;
       }
       break;
+#ifdef HAVE_SYS_UN_H
+    case AF_UNIX:
+      s_un = (struct sockaddr_un *)addr; /* XXX-IPv6: broken */
+      tor_snprintf(dest, len, "unix:%s", s_un->sun_path);
+      ptr = dest;
+      break;
+#endif
+    case AF_UNSPEC:
+      tor_snprintf(dest, len, "unspec");
+      ptr = dest;
+      break;
     default:
       return NULL;
   }
@@ -391,7 +378,8 @@ tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address,
     /* We have an in-addr.arpa address. */
     char buf[INET_NTOA_BUF_LEN];
     size_t len;
-    struct in_addr inaddr;
+    unsigned a,b,c,d;
+    char more;
     if (family == AF_INET6)
       return -1;
 
@@ -401,18 +389,15 @@ tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address,
 
     memcpy(buf, address, len);
     buf[len] = '\0';
-    if (tor_inet_aton(buf, &inaddr) == 0)
-      return -1; /* malformed. */
 
-    /* reverse the bytes */
-    inaddr.s_addr = (uint32_t)
-      (((inaddr.s_addr & 0x000000ff) << 24)
-       |((inaddr.s_addr & 0x0000ff00) << 8)
-       |((inaddr.s_addr & 0x00ff0000) >> 8)
-       |((inaddr.s_addr & 0xff000000) >> 24));
-
-    if (result) {
-      tor_addr_from_in(result, &inaddr);
+    /* The %c is there to make sure that the full string is taken as input */
+    if (tor_sscanf(buf, "%3u.%3u.%3u.%3u%c", &d,&c,&b,&a,&more) == 4) {
+      if (a > 255) return 0;
+      if (b > 255) return 0;
+      if (c > 255) return 0;
+      if (d > 255) return 0;
+      if (result) tor_addr_from_ipv4n(result, htonl((a<<24) | (b<<16) | (c<<8) | d));
+      return 1;
     }
     return 1;
   }
@@ -534,8 +519,6 @@ tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out,
   char *endptr;
   int any_flag=0, v4map=0;
   sa_family_t family;
-  struct in6_addr in6_tmp;
-  struct in_addr in_tmp;
 
   tor_assert(s);
   tor_assert(addr_out);
@@ -586,12 +569,10 @@ tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out,
     family = AF_INET; /* AF_UNSPEC ???? XXXX_IP6 */
     tor_addr_from_ipv4h(addr_out, 0);
     any_flag = 1;
-  } else if (tor_inet_pton(AF_INET6, address, &in6_tmp) > 0) {
+  } else if (tor_inet_pton(AF_INET6, address, addr_out) > 0) {
     family = AF_INET6;
-    tor_addr_from_in6(addr_out, &in6_tmp);
-  } else if (tor_inet_pton(AF_INET, address, &in_tmp) > 0) {
+  } else if (tor_inet_pton(AF_INET, address, addr_out) > 0) {
     family = AF_INET;
-    tor_addr_from_in(addr_out, &in_tmp);
   } else {
     log_warn(LD_GENERAL, "Malformed IP %s in address pattern; rejecting.",
              escaped(address));
@@ -603,7 +584,7 @@ tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out,
   /* Parse mask */
   if (maskbits_out) {
     int bits = 0;
-    struct in_addr v4mask;
+    tor_addr_t v4mask;
 
     if (mask) {  /* the caller (tried to) specify a mask */
       bits = (int) strtol(mask, &endptr, 10);
@@ -617,7 +598,7 @@ tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out,
         }
       } else {  /* mask might still be an address-style mask */
         if (tor_inet_pton(AF_INET, mask, &v4mask) > 0) {
-          bits = addr_mask_get_bits(ntohl(v4mask.s_addr));
+          bits = tor_addr_mask_get_bits(&v4mask);
           if (bits < 0) {
             log_warn(LD_GENERAL,
                      "IPv4-style mask %s is not a prefix address; rejecting.",
@@ -743,12 +724,12 @@ tor_addr_is_loopback(const tor_addr_t *addr)
   tor_assert(addr);
   switch (tor_addr_family(addr)) {
     case AF_INET6: {
-      /* ::1 */
+      /* ::1  - we compare the last 32bits by first converting to the correct local endian */
       uint32_t *a32 = tor_addr_to_in6_addr32(addr);
-      return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) && (a32[3] == 1);
+      return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) && (ntohl(a32[3]) == 1);
     }
     case AF_INET:
-      /* 127.0.0.1 */
+      /* 127.0.0.1 - tor_addr_to_ipv4h handles endianess */
       return (tor_addr_to_ipv4h(addr) & 0xff000000) == 0x7f000000;
     case AF_UNSPEC:
       return 0;
@@ -758,6 +739,25 @@ tor_addr_is_loopback(const tor_addr_t *addr)
   }
 }
 
+/* XXX: Get rid of the difference with tor_addr_make_null() */
+void
+tor_addr_from_null(tor_addr_t *dest)
+{
+  memset(dest, 0, sizeof(*dest));
+  dest->family = AF_INET;
+}
+
+void
+tor_addr_from_loopback(tor_addr_t *dest, sa_family_t family)
+{
+  if (family == AF_INET) tor_addr_from_ipv4n(dest, htonl(0x7f000001u));
+  else
+  {
+    uint32_t bits[4] = {0,0,0,htonl(1)};
+    tor_addr_from_ipv6_bytes(dest, (const char *)bits);
+  }
+}
+
 /** Set <b>dest</b> to equal the IPv4 address in <b>v4addr</b> (given in
  * network order). */
 void
@@ -838,6 +838,12 @@ tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
 #define TRISTATE(a,b) (((a)<(b))?-1: (((a)==(b))?0:1))
   sa_family_t family1, family2, v_family1, v_family2;
 
+  /* When one of the two addresses is not there... */
+  /* (Might happen because of node address compares, should fix there maybe) */
+  if (!addr1 && addr2) return -1;
+  if (addr1 && !addr2) return 1;
+  if (!addr1 && !addr2) return 0;
+
   tor_assert(addr1 && addr2);
 
   v_family1 = family1 = tor_addr_family(addr1);
@@ -945,7 +951,7 @@ char *
 tor_dup_addr(const tor_addr_t *addr)
 {
   char buf[TOR_ADDR_BUF_LEN];
-  tor_addr_to_str(buf, addr, sizeof(buf), 0);
+  tor_addr_to_str(addr, buf, sizeof(buf), 0);
   return tor_strdup(buf);
 }
 
@@ -958,20 +964,7 @@ fmt_addr(const tor_addr_t *addr)
 {
   static char buf[TOR_ADDR_BUF_LEN];
   if (!addr) return "<null>";
-  tor_addr_to_str(buf, addr, sizeof(buf), 0);
-  return buf;
-}
-
-/** Like fmt_addr(), but takes <b>addr</b> as a host-order IPv4
- * addresses. Also not thread-safe, also clobbers its return buffer on
- * repeated calls. */
-const char *
-fmt_addr32(uint32_t addr)
-{
-  static char buf[INET_NTOA_BUF_LEN];
-  struct in_addr in;
-  in.s_addr = htonl(addr);
-  tor_inet_ntoa(&in, buf, sizeof(buf));
+  tor_addr_to_str(addr, buf, sizeof(buf), 0);
   return buf;
 }
 
@@ -986,18 +979,14 @@ tor_addr_from_str(tor_addr_t *addr, const char *src)
 {
   char *tmp = NULL; /* Holds substring if we got a dotted quad. */
   int result;
-  struct in_addr in_tmp;
-  struct in6_addr in6_tmp;
   tor_assert(addr && src);
   if (src[0] == '[' && src[1])
     src = tmp = tor_strndup(src+1, strlen(src)-2);
 
-  if (tor_inet_pton(AF_INET6, src, &in6_tmp) > 0) {
+  if (tor_inet_pton(AF_INET6, src, addr) > 0) {
     result = AF_INET6;
-    tor_addr_from_in6(addr, &in6_tmp);
-  } else if (tor_inet_pton(AF_INET, src, &in_tmp) > 0) {
+  } else if (tor_inet_pton(AF_INET, src, addr) > 0) {
     result = AF_INET;
-    tor_addr_from_in(addr, &in_tmp);
   } else {
     result = -1;
   }
@@ -1128,24 +1117,6 @@ get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr)
   return r;
 }
 
-/* ======
- * IPv4 helpers
- * XXXX023 IPv6 deprecate some of these.
- */
-
-/** Return true iff <b>ip</b> (in host order) is an IP reserved to localhost,
- * or reserved for local networks by RFC 1918.
- */
-int
-is_internal_IP(uint32_t ip, int for_listening)
-{
-  tor_addr_t myaddr;
-  myaddr.family = AF_INET;
-  myaddr.addr.in_addr.s_addr = htonl(ip);
-
-  return tor_addr_is_internal(&myaddr, for_listening);
-}
-
 /** Parse a string of the form "host[:port]" from <b>addrport</b>.  If
  * <b>address</b> is provided, set *<b>address</b> to a copy of the
  * host portion of the string.  If <b>addr</b> is provided, try to
@@ -1158,7 +1129,7 @@ is_internal_IP(uint32_t ip, int for_listening)
  */
 int
 parse_addr_port(int severity, const char *addrport, char **address,
-                uint32_t *addr, uint16_t *port_out)
+                tor_addr_t *addr, uint16_t *port_out)
 {
   const char *colon;
   char *_address = NULL;
@@ -1190,10 +1161,10 @@ parse_addr_port(int severity, const char *addrport, char **address,
 
   if (addr) {
     /* There's an addr pointer, so we need to resolve the hostname. */
-    if (tor_lookup_hostname(_address,addr)) {
+    if (tor_addr_lookup(_address, AF_UNSPEC, addr)) {
       log_fn(severity, LD_NET, "Couldn't look up %s", escaped(_address));
       ok = 0;
-      *addr = 0;
+      tor_addr_from_null(addr);
     }
   }
 
@@ -1213,9 +1184,10 @@ parse_addr_port(int severity, const char *addrport, char **address,
 /** If <b>mask</b> is an address mask for a bit-prefix, return the number of
  * bits.  Otherwise, return -1. */
 int
-addr_mask_get_bits(uint32_t mask)
+tor_addr_mask_get_bits(tor_addr_t *msk)
 {
   int i;
+  uint32_t mask = tor_addr_to_ipv4h(msk);
   if (mask == 0)
     return 0;
   if (mask == 0xFFFFFFFFu)
@@ -1228,30 +1200,41 @@ addr_mask_get_bits(uint32_t mask)
   return -1;
 }
 
-/** Compare two addresses <b>a1</b> and <b>a2</b> for equality under a
+/** Compare two addresses <b>a</b> and <b>b</b> for equality under a
  * netmask of <b>mbits</b> bits.  Return -1, 0, or 1.
- *
- * XXXX_IP6 Temporary function to allow masks as bitcounts everywhere.  This
- * will be replaced with an IPv6-aware version as soon as 32-bit addresses are
- * no longer passed around.
  */
 int
-addr_mask_cmp_bits(uint32_t a1, uint32_t a2, maskbits_t bits)
+tor_addr_mask_cmp_bits(tor_addr_t *a, tor_addr_t *b, maskbits_t bits)
 {
-  if (bits > 32)
-    bits = 32;
+  int maxbits;
+  const uint8_t *aa, *bb;
+  int aaa, bbb;
+  if (a->family < b->family) return -1;
+  if (a->family > b->family) return 1;
+
+  maxbits = a->family == AF_INET ? 32 : 128;
+  if (bits > maxbits)
+    bits = maxbits;
   else if (bits == 0)
     return 0;
 
-  a1 >>= (32-bits);
-  a2 >>= (32-bits);
+  aa = tor_addr_raw(a);
+  bb = tor_addr_raw(b);
 
-  if (a1 < a2)
-    return -1;
-  else if (a1 > a2)
-    return 1;
-  else
-    return 0;
+  for (; bits >= 8; aa++, bb++, bits -= 8) {
+    if (*aa < *bb) return -1;
+    if (*aa > *bb) return 1;
+  }
+
+  if (bits > 0) {
+    aaa = *aa >> (8-bits);
+    bbb = *bb >> (8-bits);
+
+    if (aaa < bbb) return -1;
+    if (aaa > bbb) return 1;
+  }
+
+  return 0;
 }
 
 /** Parse a string <b>s</b> in the format of (*|port(-maxport)?)?, setting the
@@ -1311,13 +1294,13 @@ parse_port_range(const char *port, uint16_t *port_min_out,
  * *out pointers as appropriate.  Return 0 on success, -1 on failure.
  */
 int
-parse_addr_and_port_range(const char *s, uint32_t *addr_out,
+parse_addr_and_port_range(const char *s, tor_addr_t *addr_out,
                           maskbits_t *maskbits_out, uint16_t *port_min_out,
                           uint16_t *port_max_out)
 {
   char *address;
   char *mask, *port, *endptr;
-  struct in_addr in;
+  tor_addr_t maskbits;
   int bits;
 
   tor_assert(s);
@@ -1341,9 +1324,9 @@ parse_addr_and_port_range(const char *s, uint32_t *addr_out,
    */
 
   if (strcmp(address,"*")==0) {
-    *addr_out = 0;
-  } else if (tor_inet_aton(address, &in) != 0) {
-    *addr_out = ntohl(in.s_addr);
+    tor_addr_from_null(addr_out);
+  } else if (tor_inet_pton(AF_UNSPEC, address, addr_out) != 0) {
+   /* All ok */
   } else {
     log_warn(LD_GENERAL, "Malformed IP %s in address pattern; rejecting.",
              escaped(address));
@@ -1366,8 +1349,8 @@ parse_addr_and_port_range(const char *s, uint32_t *addr_out,
         goto err;
       }
       *maskbits_out = bits;
-    } else if (tor_inet_aton(mask, &in) != 0) {
-      bits = addr_mask_get_bits(ntohl(in.s_addr));
+    } else if (tor_inet_pton(AF_INET, mask, &maskbits) != 0) {
+      bits = tor_addr_mask_get_bits(&maskbits);
       if (bits < 0) {
         log_warn(LD_GENERAL,
                  "Mask %s on address range isn't a prefix; dropping",
@@ -1408,35 +1391,14 @@ tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
                       (int)(uint8_t)((a    )&0xff));
 }
 
-/** Given a host-order <b>addr</b>, call tor_inet_ntop() on it
+/** Given a tor_addr_t <b>addr</b>, call tor_inet_ntop() on it
  *  and return a strdup of the resulting address.
  */
 char *
-tor_dup_ip(uint32_t addr)
+tor_dup_ip(tor_addr_t *addr)
 {
   char buf[TOR_ADDR_BUF_LEN];
-  struct in_addr in;
-
-  in.s_addr = htonl(addr);
-  tor_inet_ntop(AF_INET, &in, buf, sizeof(buf));
+  if (!tor_addr_to_str(addr, buf, sizeof(buf),1)) return NULL;
   return tor_strdup(buf);
 }
 
-/**
- * Set *<b>addr</b> to the host-order IPv4 address (if any) of whatever
- * interface connects to the Internet.  This address should only be used in
- * checking whether our address has changed.  Return 0 on success, -1 on
- * failure.
- */
-int
-get_interface_address(int severity, uint32_t *addr)
-{
-  tor_addr_t local_addr;
-  int r;
-
-  r = get_interface_address6(severity, AF_INET, &local_addr);
-  if (r>=0)
-    *addr = tor_addr_to_ipv4h(&local_addr);
-  return r;
-}
-
diff --git a/src/common/address.h b/src/common/address.h
index e41e4c2..f58a31a 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -36,15 +36,14 @@ static INLINE uint32_t tor_addr_to_ipv4n(const tor_addr_t *a);
 static INLINE uint32_t tor_addr_to_ipv4h(const tor_addr_t *a);
 static INLINE uint32_t tor_addr_to_mapped_ipv4h(const tor_addr_t *a);
 static INLINE sa_family_t tor_addr_family(const tor_addr_t *a);
+static INLINE unsigned int tor_addr_protocol(const tor_addr_t *a);
 static INLINE const struct in_addr *tor_addr_to_in(const tor_addr_t *a);
-static INLINE int tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u);
+static INLINE const uint8_t *tor_addr_raw(const tor_addr_t *a);
 
 socklen_t tor_addr_to_sockaddr(const tor_addr_t *a, uint16_t port,
-                               struct sockaddr *sa_out, socklen_t len);
-int tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa,
-                           uint16_t *port_out);
+                               struct sockaddr_storage *sa_out, socklen_t len);
+int tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa, uint16_t *port_out);
 void tor_addr_make_unspec(tor_addr_t *a);
-char *tor_sockaddr_to_str(const struct sockaddr *sa);
 
 /** Return an in6_addr* equivalent to <b>a</b>, or NULL if <b>a</b> is not
  * an IPv6 address. */
@@ -100,6 +99,13 @@ tor_addr_family(const tor_addr_t *a)
 {
   return a->family;
 }
+/** Return the address family of <b>a</b>.  Possible values are:
+ * AF_INET6, AF_INET, AF_UNSPEC. */
+static INLINE unsigned int
+tor_addr_protocol(const tor_addr_t *a)
+{
+  return a->family == AF_INET ? PF_INET : (a->family == AF_INET6 ? PF_INET6 : PF_UNSPEC);
+}
 /** Return an in_addr* equivalent to <b>a</b>, or NULL if <b>a</b> is not
  * an IPv4 address. */
 static INLINE const struct in_addr *
@@ -107,12 +113,11 @@ tor_addr_to_in(const tor_addr_t *a)
 {
   return a->family == AF_INET ? &a->addr.in_addr : NULL;
 }
-/** Return true iff <b>a</b> is an IPv4 address equal to the host-ordered
- * address in <b>u</b>. */
-static INLINE int
-tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
+/** Return the raw bits of <b>a</b> */
+static INLINE const uint8_t *
+tor_addr_raw(const tor_addr_t *a)
 {
-  return a->family == AF_INET ? (tor_addr_to_ipv4h(a) == u) : 0;
+  return a->family == AF_INET ? (uint8_t *)&a->addr.in_addr.s_addr : tor_addr_to_in6_addr8(a);
 }
 
 /** Length of a buffer that you need to allocate to be sure you can encode
@@ -127,7 +132,6 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
 int tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out);
 char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC;
 const char *fmt_addr(const tor_addr_t *addr);
-const char * fmt_addr32(uint32_t addr);
 int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr);
 
 /** Flag to specify how to do a comparison between addresses.  In an "exact"
@@ -143,9 +147,10 @@ int tor_addr_compare(const tor_addr_t *addr1, const tor_addr_t *addr2,
                      tor_addr_comparison_t how);
 int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
                             maskbits_t mask, tor_addr_comparison_t how);
-/** Return true iff a and b are the same address.  The comparison is done
+/** Return true if a and b are the same address.  The comparison is done
  * "exactly". */
 #define tor_addr_eq(a,b) (0==tor_addr_compare((a),(b),CMP_EXACT))
+#define tor_addr_cmp(a,b) tor_addr_compare((a),(b),CMP_EXACT)
 
 unsigned int tor_addr_hash(const tor_addr_t *addr);
 int tor_addr_is_v4(const tor_addr_t *addr);
@@ -164,7 +169,7 @@ int tor_addr_port_parse(const char *s, tor_addr_t *addr_out,
 int tor_addr_parse_mask_ports(const char *s,
                               tor_addr_t *addr_out, maskbits_t *mask_out,
                               uint16_t *port_min_out, uint16_t *port_max_out);
-const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len,
+const char * tor_addr_to_str(const tor_addr_t *addr, char *dest, size_t len,
                              int decorate);
 int tor_addr_from_str(tor_addr_t *addr, const char *src);
 void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src);
@@ -180,23 +185,23 @@ void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *bytes);
 void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
 int tor_addr_is_null(const tor_addr_t *addr);
 int tor_addr_is_loopback(const tor_addr_t *addr);
+void tor_addr_from_loopback(tor_addr_t *dest,sa_family_t family);
+void tor_addr_from_null(tor_addr_t *dest);
 
-/* IPv4 helpers */
-int is_internal_IP(uint32_t ip, int for_listening) ATTR_PURE;
+/* IP helpers */
 int parse_addr_port(int severity, const char *addrport, char **address,
-                    uint32_t *addr, uint16_t *port_out);
+                    tor_addr_t *addr, uint16_t *port_out);
 int parse_port_range(const char *port, uint16_t *port_min_out,
                      uint16_t *port_max_out);
-int parse_addr_and_port_range(const char *s, uint32_t *addr_out,
+int parse_addr_and_port_range(const char *s, tor_addr_t *addr_out,
                               maskbits_t *maskbits_out, uint16_t *port_min_out,
                               uint16_t *port_max_out);
-int addr_mask_get_bits(uint32_t mask);
-int addr_mask_cmp_bits(uint32_t a1, uint32_t a2, maskbits_t bits);
+int tor_addr_mask_get_bits(tor_addr_t *mask);
+int tor_addr_mask_cmp_bits(tor_addr_t *a, tor_addr_t *b, maskbits_t bits);
 /** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/
 #define INET_NTOA_BUF_LEN 16
 int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
-char *tor_dup_ip(uint32_t addr) ATTR_MALLOC;
-int get_interface_address(int severity, uint32_t *addr);
+char *tor_dup_ip(tor_addr_t *addr) ATTR_MALLOC;
 
 #endif
 
diff --git a/src/common/compat.c b/src/common/compat.c
index 436d882..38c2fd6 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -969,14 +969,15 @@ tor_open_socket(int domain, int type, int protocol)
 
 /** As socket(), but counts the number of open sockets. */
 int
-tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len)
+tor_accept_socket(int sockfd, struct sockaddr_storage *addr, socklen_t *len)
 {
   int s;
+  tor_assert(*len == sizeof(*addr));
 #if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
 #define LINUX_CLOEXEC_ACCEPT
-  s = accept4(sockfd, addr, len, SOCK_CLOEXEC);
+  s = accept4(sockfd, (struct sockaddr *)addr, len, SOCK_CLOEXEC);
 #else
-  s = accept(sockfd, addr, len);
+  s = accept(sockfd, (struct sockaddr *)addr, len);
 #endif
   if (s >= 0) {
 #if !defined(LINUX_CLOEXEC_ACCEPT) && defined(FD_CLOEXEC)
@@ -1069,8 +1070,8 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
     int listener = -1;
     int connector = -1;
     int acceptor = -1;
-    struct sockaddr_in listen_addr;
-    struct sockaddr_in connect_addr;
+    struct sockaddr_storage listen_addr;
+    struct sockaddr_storage connect_addr;
     int size;
     int saved_errno = -1;
 
@@ -1109,15 +1110,14 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
     size = sizeof(connect_addr);
     if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
       goto tidy_up_and_fail;
-    if (size != sizeof (connect_addr))
+    if (size > sizeof (connect_addr))
       goto abort_tidy_up_and_fail;
     if (connect(connector, (struct sockaddr *) &connect_addr,
                 sizeof(connect_addr)) == -1)
       goto tidy_up_and_fail;
 
     size = sizeof(listen_addr);
-    acceptor = tor_accept_socket(listener,
-                                 (struct sockaddr *) &listen_addr, &size);
+    acceptor = tor_accept_socket(listener, &listen_addr, &size);
     if (acceptor < 0)
       goto tidy_up_and_fail;
     if (size != sizeof(listen_addr))
@@ -1127,10 +1127,10 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
        two sockets.  */
     if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
       goto tidy_up_and_fail;
-    if (size != sizeof (connect_addr)
-        || listen_addr.sin_family != connect_addr.sin_family
-        || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
-        || listen_addr.sin_port != connect_addr.sin_port) {
+    if (size > sizeof (connect_addr)
+        || listen_addr.sa_family != connect_addr.sa_family
+        || listen_addr.sa_addr.s_addr != connect_addr.sin_addr.s_addr /* XXX-IPv6 */
+        || listen_addr.sa_port != connect_addr.sa_port) {
       goto abort_tidy_up_and_fail;
     }
     fd[0] = connector;
@@ -1522,25 +1522,6 @@ get_user_homedir(const char *username)
 }
 #endif
 
-/** Set *addr to the IP address (in dotted-quad notation) stored in c.
- * Return 1 on success, 0 if c is badly formatted.  (Like inet_aton(c,addr),
- * but works on Windows and Solaris.)
- */
-int
-tor_inet_aton(const char *str, struct in_addr* addr)
-{
-  unsigned a,b,c,d;
-  char more;
-  if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
-    return 0;
-  if (a > 255) return 0;
-  if (b > 255) return 0;
-  if (c > 255) return 0;
-  if (d > 255) return 0;
-  addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
-  return 1;
-}
-
 /** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or
  * <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the
  * address and store it in the <b>len</b>-byte buffer <b>dst</b>.  Returns
@@ -1639,12 +1620,25 @@ tor_inet_ntop(int af, const void *src, char *dst, size_t len)
  * sometimes needs to format ipv6 addresses even on platforms without ipv6
  * support.) */
 int
-tor_inet_pton(int af, const char *src, void *dst)
-{
-  if (af == AF_INET) {
-    return tor_inet_aton(src, dst);
+tor_inet_pton(int af, const char *src, tor_addr_t *dst)
+{
+  if (af == AF_UNSPEC) {
+    if (tor_inet_pton(AF_INET, src, dst) == 1) return 1;
+    return tor_inet_pton(AF_INET6, src, dst);
+  } else if (af == AF_INET) {
+    unsigned a,b,c,d;
+    char more;
+    /* XXX: There are 5 parameters (4x %u, 1x %c), why compare to 4 as a result!? */
+    if (tor_sscanf(src, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) == 4) {
+      if (a > 255) return 0;
+      if (b > 255) return 0;
+      if (c > 255) return 0;
+      if (d > 255) return 0;
+      if (dst) tor_addr_from_ipv4n(dst, htonl((a<<24) | (b<<16) | (c<<8) | d));
+      return 1;
+    }
   } else if (af == AF_INET6) {
-    struct in6_addr *out = dst;
+    tor_addr_t *out = dst ? dst : NULL;
     uint16_t words[8];
     int gapPos = -1, i, setWords=0;
     const char *dot = strchr(src, '.');
@@ -1718,38 +1712,13 @@ tor_inet_pton(int af, const char *src, void *dst)
               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;
-      out->s6_addr[2*i+1] = words[i] & 0xff;
+    for (i = 0; dst && i < 8; ++i) {
+      out->addr.in6_addr.s6_addr[2*i  ] = words[i] >> 8;
+      out->addr.in6_addr.s6_addr[2*i+1] = words[i] & 0xff;
     }
 
     return 1;
-  } else {
-    return -1;
   }
-}
-
-/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
- * *<b>addr</b> to the proper IP address, in host byte order.  Returns 0
- * on success, -1 on failure; 1 on transient failure.
- *
- * (This function exists because standard windows gethostbyname
- * doesn't treat raw IP addresses properly.)
- */
-int
-tor_lookup_hostname(const char *name, uint32_t *addr)
-{
-  tor_addr_t myaddr;
-  int ret;
-
-  if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
-    return ret;
-
-  if (tor_addr_family(&myaddr) == AF_INET) {
-    *addr = tor_addr_to_ipv4h(&myaddr);
-    return ret;
-  }
-
   return -1;
 }
 
diff --git a/src/common/compat.h b/src/common/compat.h
index b658ed5..8a7f976 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -397,7 +397,7 @@ typedef int socklen_t;
 
 int tor_close_socket(int s);
 int tor_open_socket(int domain, int type, int protocol);
-int tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len);
+int tor_accept_socket(int sockfd, struct sockaddr_storage *addr, socklen_t *len);
 int get_n_open_sockets(void);
 
 #define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags)
@@ -465,10 +465,11 @@ struct sockaddr_in6 {
 };
 #endif
 
-int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
+/* Need for tor_addr_t till we kill off these 'compatibility' functions */
+#include "address.h"
+
 const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
-int tor_inet_pton(int af, const char *src, void *dst);
-int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
+int tor_inet_pton(int af, const char *src, tor_addr_t *dst);
 void set_socket_nonblocking(int socket);
 int tor_socketpair(int family, int type, int protocol, int fd[2]);
 int network_init(void);
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 70f8b4a..540bf4c 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1710,7 +1710,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
           else
             tor_addr_from_ipv4n(&destaddr, get_uint32(data+4));
 
-          tor_addr_to_str(tmpbuf, &destaddr, sizeof(tmpbuf), 1);
+          tor_addr_to_str(&destaddr, tmpbuf, sizeof(tmpbuf), 1);
 
           if (strlen(tmpbuf)+1 > MAX_SOCKS_ADDR_LEN) {
             log_warn(LD_APP,
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 17e7c14..aecd5d0 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -2600,7 +2600,7 @@ node_handles_some_port(const node_t *node, smartlist_t *needed_ports)
     port = *(uint16_t *)smartlist_get(needed_ports, i);
     tor_assert(port);
     if (node)
-      r = compare_addr_to_node_policy(0, port, node);
+      r = compare_tor_addr_to_node_policy(NULL, port, node);
     else
       continue;
     if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
@@ -3290,11 +3290,9 @@ extend_info_alloc(const char *nickname, const char *digest,
 extend_info_t *
 extend_info_from_router(const routerinfo_t *r)
 {
-  tor_addr_t addr;
   tor_assert(r);
-  tor_addr_from_ipv4h(&addr, r->addr);
   return extend_info_alloc(r->nickname, r->cache_info.identity_digest,
-                           r->onion_pkey, &addr, r->or_port);
+                           r->onion_pkey, &r->addr, r->or_port);
 }
 
 /** Allocate and return a new extend_info that can be used to build a ircuit
@@ -3308,12 +3306,10 @@ extend_info_from_node(const node_t *node)
   if (node->ri) {
     return extend_info_from_router(node->ri);
   } else if (node->rs && node->md) {
-    tor_addr_t addr;
-    tor_addr_from_ipv4h(&addr, node->rs->addr);
     return extend_info_alloc(node->rs->nickname,
                              node->identity,
                              node->md->onion_pkey,
-                             &addr,
+                             &node->rs->addr,
                              node->rs->or_port);
   } else {
     return NULL;
@@ -4513,7 +4509,7 @@ clear_bridge_list(void)
  * (either by comparing keys if possible, else by comparing addr/port).
  * Else return NULL. */
 static bridge_info_t *
-get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port,
+get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr, uint16_t port,
                                           const char *digest)
 {
   if (!bridge_list)
@@ -4521,7 +4517,7 @@ get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port,
   SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
     {
       if (tor_digest_is_zero(bridge->identity) &&
-          !tor_addr_compare(&bridge->addr, addr, CMP_EXACT) &&
+          !tor_addr_eq(&bridge->addr, addr) &&
           bridge->port == port)
         return bridge;
       if (tor_memeq(bridge->identity, digest, DIGEST_LEN))
@@ -4536,9 +4532,7 @@ get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port,
 static bridge_info_t *
 get_configured_bridge_by_routerinfo(const routerinfo_t *ri)
 {
-  tor_addr_t addr;
-  tor_addr_from_ipv4h(&addr, ri->addr);
-  return get_configured_bridge_by_addr_port_digest(&addr,
+  return get_configured_bridge_by_addr_port_digest(&ri->addr,
                               ri->or_port, ri->cache_info.identity_digest);
 }
 
@@ -4737,19 +4731,16 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
    *   do that safely if we know that no function that connects to an OR
    *   does so through an address from any source other than node_get_addr().
    */
-  tor_addr_t addr;
-
   if (node->ri) {
     routerinfo_t *ri = node->ri;
-    tor_addr_from_ipv4h(&addr, ri->addr);
 
-    if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+    if (!tor_addr_eq(&bridge->addr, &ri->addr) &&
         bridge->port == ri->or_port) {
       /* they match, so no need to do anything */
     } else {
-      ri->addr = tor_addr_to_ipv4h(&bridge->addr);
+      tor_addr_copy(&ri->addr, &bridge->addr);
       tor_free(ri->address);
-      ri->address = tor_dup_ip(ri->addr);
+      ri->address = tor_dup_ip(&ri->addr);
       ri->or_port = bridge->port;
       log_info(LD_DIR,
                "Adjusted bridge routerinfo for '%s' to match configured "
@@ -4759,13 +4750,11 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
   }
   if (node->rs) {
     routerstatus_t *rs = node->rs;
-    tor_addr_from_ipv4h(&addr, rs->addr);
-
-    if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+    if (!tor_addr_eq(&bridge->addr, &rs->addr) &&
         bridge->port == rs->or_port) {
       /* they match, so no need to do anything */
     } else {
-      rs->addr = tor_addr_to_ipv4h(&bridge->addr);
+      tor_addr_copy(&rs->addr, &bridge->addr);
       rs->or_port = bridge->port;
       log_info(LD_DIR,
                "Adjusted bridge routerstatus for '%s' to match "
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 6e98e53..1b5e394 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -519,7 +519,7 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
           ok = connection_ap_can_use_exit(conn, exitnode);
         } else {
           addr_policy_result_t r;
-          r = compare_addr_to_node_policy(0, port, exitnode);
+          r = compare_tor_addr_to_node_policy(NULL, port, exitnode);
           ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED;
         }
         if (ok) {
@@ -1271,11 +1271,14 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
   /* Do we need to check exit policy? */
   if (check_exit_policy) {
     if (!conn->chosen_exit_name) {
-      struct in_addr in;
-      uint32_t addr = 0;
-      if (tor_inet_aton(conn->socks_request->address, &in))
-        addr = ntohl(in.s_addr);
-      if (router_exit_policy_all_nodes_reject(addr,
+      tor_addr_t addr;
+      if (!tor_inet_pton(AF_UNSPEC, conn->socks_request->address, &addr)) {
+        log_notice(LD_APP,
+                   "Could not parse address %s. Rejecting.",
+                   safe_str_client(conn->socks_request->address));
+        return -1;
+      }
+      if (router_exit_policy_all_nodes_reject(&addr,
                                               conn->socks_request->port,
                                               need_uptime)) {
         log_notice(LD_APP,
diff --git a/src/or/config.c b/src/or/config.c
index 1a877b8..feaa84e 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -2406,7 +2406,7 @@ list_torrc_options(void)
 }
 
 /** Last value actually set by resolve_my_address. */
-static uint32_t last_resolved_addr = 0;
+static tor_addr_t last_resolved_addr;
 /**
  * Based on <b>options-\>Address</b>, guess our public IP address and put it
  * (in host order) into *<b>addr_out</b>. If <b>hostname_out</b> is provided,
@@ -2416,10 +2416,9 @@ static uint32_t last_resolved_addr = 0;
  */
 int
 resolve_my_address(int warn_severity, or_options_t *options,
-                   uint32_t *addr_out, char **hostname_out)
+                   tor_addr_t *addr_out, char **hostname_out)
 {
-  struct in_addr in;
-  uint32_t addr; /* host order */
+  tor_addr_t addr;
   char hostname[256];
   int explicit_ip=1;
   int explicit_hostname=1;
@@ -2446,11 +2445,10 @@ resolve_my_address(int warn_severity, or_options_t *options,
 
   /* now we know hostname. resolve it and keep only the IP address */
 
-  if (tor_inet_aton(hostname, &in) == 0) {
+  if (tor_inet_pton(AF_UNSPEC, hostname, &addr) == 0) {
     /* then we have to resolve it */
     explicit_ip = 0;
-    if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */
-      uint32_t interface_ip; /* host order */
+    if (tor_addr_lookup(hostname, AF_UNSPEC, &addr)) { /* failed to resolve */
 
       if (explicit_hostname) {
         log_fn(warn_severity, LD_CONFIG,
@@ -2460,49 +2458,45 @@ resolve_my_address(int warn_severity, or_options_t *options,
       log_fn(notice_severity, LD_CONFIG,
              "Could not resolve guessed local hostname '%s'. "
              "Trying something else.", hostname);
-      if (get_interface_address(warn_severity, &interface_ip)) {
+      if (get_interface_address6(warn_severity, AF_UNSPEC, &addr)) {
         log_fn(warn_severity, LD_CONFIG,
                "Could not get local interface IP address. Failing.");
         return -1;
       }
       from_interface = 1;
-      addr = interface_ip;
       log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
-             "local interface. Using that.", fmt_addr32(addr));
+             "local interface. Using that.", fmt_addr(&addr));
       strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
     } else { /* resolved hostname into addr */
       if (!explicit_hostname &&
-          is_internal_IP(addr, 0)) {
-        uint32_t interface_ip;
+          tor_addr_is_internal(&addr, 0)) {
 
         log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
                "resolves to a private IP address (%s). Trying something "
-               "else.", hostname, fmt_addr32(addr));
+               "else.", hostname, fmt_addr(&addr));
 
-        if (get_interface_address(warn_severity, &interface_ip)) {
+        if (get_interface_address6(warn_severity, AF_UNSPEC, &addr)) {
           log_fn(warn_severity, LD_CONFIG,
                  "Could not get local interface IP address. Too bad.");
-        } else if (is_internal_IP(interface_ip, 0)) {
+        } else if (tor_addr_is_internal(&addr, 0)) {
           log_fn(notice_severity, LD_CONFIG,
                  "Interface IP address '%s' is a private address too. "
-                 "Ignoring.", fmt_addr32(interface_ip));
+                 "Ignoring.", fmt_addr(&addr));
         } else {
           from_interface = 1;
-          addr = interface_ip;
           log_fn(notice_severity, LD_CONFIG,
                  "Learned IP address '%s' for local interface."
-                 " Using that.", fmt_addr32(addr));
+                 " Using that.", fmt_addr(&addr));
           strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
         }
       }
     }
   } else {
-    addr = ntohl(in.s_addr); /* set addr so that addr_string is not
-                              * illformed */
+    tor_addr_from_null(&addr); /* set addr so that addr_string is not illformed */
   }
 
-  addr_string = tor_dup_ip(addr);
-  if (is_internal_IP(addr, 0)) {
+  addr_string = tor_dup_ip(&addr);
+  if (tor_addr_is_internal(&addr, 0)) {
     /* make sure we're ok with publishing an internal IP */
     if (!options->DirServers && !options->AlternateDirAuthority) {
       /* if they are using the default dirservers, disallow internal IPs
@@ -2525,19 +2519,17 @@ resolve_my_address(int warn_severity, or_options_t *options,
     }
   }
 
-  log_debug(LD_CONFIG, "Resolved Address to '%s'.", fmt_addr32(addr));
-  *addr_out = addr;
-  if (last_resolved_addr && last_resolved_addr != *addr_out) {
+  log_debug(LD_CONFIG, "Resolved Address to '%s'.", fmt_addr(&addr));
+  tor_addr_copy(addr_out,&addr);
+  if (!tor_addr_is_null(&addr) && !tor_addr_eq(&last_resolved_addr, addr_out)) {
+    const char *method;
+    const char *h = hostname;
     /* Leave this as a notice, regardless of the requested severity,
      * at least until dynamic IP address support becomes bulletproof. */
     log_notice(LD_NET,
                "Your IP address seems to have changed to %s. Updating.",
                addr_string);
     ip_address_changed(0);
-  }
-  if (last_resolved_addr != *addr_out) {
-    const char *method;
-    const char *h = hostname;
     if (explicit_ip) {
       method = "CONFIGURED";
       h = NULL;
@@ -2568,24 +2560,31 @@ is_local_addr(const tor_addr_t *addr)
 {
   if (tor_addr_is_internal(addr, 0))
     return 1;
-  /* Check whether ip is on the same /24 as we are. */
+  /* Check whether ip is on the same /24 (IPv4) or /48 (IPv6) as we are. */
   if (get_options()->EnforceDistinctSubnets == 0)
     return 0;
   if (tor_addr_family(addr) == AF_INET) {
-    /*XXXX023 IP6 what corresponds to an /24? */
     uint32_t ip = tor_addr_to_ipv4h(addr);
+    uint32_t lip = tor_addr_to_ipv4h(&last_resolved_addr);
 
     /* It's possible that this next check will hit before the first time
      * resolve_my_address actually succeeds.  (For clients, it is likely that
      * resolve_my_address will never be called at all).  In those cases,
      * last_resolved_addr will be 0, and so checking to see whether ip is on
      * the same /24 as last_resolved_addr will be the same as checking whether
-     * it was on net 0, which is already done by is_internal_IP.
+     * it was on net 0, which is already done by tor_addr_is_internal.
      */
-    if ((last_resolved_addr & (uint32_t)0xffffff00ul)
-        == (ip & (uint32_t)0xffffff00ul))
+    if ((lip & (uint32_t)0xffffff00ul) == (ip & (uint32_t)0xffffff00ul))
       return 1;
   }
+  else if (tor_addr_family(addr) == AF_INET6) {
+    /* XXX: The problem with last_resolved_addr is:
+     * - it is IPv4 only (and in an int, not even a tor_addr)
+     * - We can't have multiple of them:
+     *   - would need at least IPv4 + IPv6 in minimum case
+     *   - a host might have multiple IPv4 and IPv6 addresses...
+     */
+  }
   return 0;
 }
 
@@ -2730,6 +2729,8 @@ config_init(config_format_t *fmt, void *options)
   config_var_t *var;
   CHECK(fmt, options);
 
+  tor_addr_from_loopback(&last_resolved_addr, AF_INET);
+
   for (i=0; fmt->vars[i].name; ++i) {
     var = &fmt->vars[i];
     if (!var->initvalue)
@@ -2998,10 +2999,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
     for (line = opt; line; line = line->next) {
       char *address = NULL;
       uint16_t port;
-      uint32_t addr;
+      tor_addr_t addr;
       if (parse_addr_port(LOG_WARN, line->value, &address, &addr, &port)<0)
         continue; /* We'll warn about this later. */
-      if (!is_internal_IP(addr, 1) &&
+      if (!tor_addr_is_internal(&addr, 1) &&
           (!old_options || !config_lines_eq(old, opt))) {
         log_warn(LD_CONFIG,
              "You specified a public address '%s' for a %s. Other "
@@ -3043,7 +3044,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
 
   if (authdir_mode(options)) {
     /* confirm that our address isn't broken, so we can complain now */
-    uint32_t tmp;
+    tor_addr_t tmp;
     if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0)
       REJECT("Failed to resolve/guess local address. See logs for details.");
   }
diff --git a/src/or/config.h b/src/or/config.h
index 49f7e25..a1f517d 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -27,7 +27,7 @@ void config_free_lines(config_line_t *front);
 setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
                                   int clear_first, char **msg);
 int resolve_my_address(int warn_severity, or_options_t *options,
-                       uint32_t *addr, char **hostname_out);
+                       tor_addr_t *addr, char **hostname_out);
 int is_local_addr(const tor_addr_t *addr) ATTR_PURE;
 void options_init(or_options_t *options);
 char *options_dump(or_options_t *options, int minimal);
diff --git a/src/or/connection.c b/src/or/connection.c
index 099482b..ae398bc 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -68,9 +68,9 @@ static int connection_read_https_proxy_response(connection_t *conn);
 static void connection_send_socks5_connect(connection_t *conn);
 
 /** The last IPv4 address that our network interface seemed to have been
- * binding to, in host order.  We use this to detect when our IP changes. */
-static uint32_t last_interface_ip = 0;
-/** A list of uint32_ts for addresses we've used in outgoing connections.
+ * binding to, in host order.  We use this to detect when our IPv4 address changes. */
+static tor_addr_t last_interface_ip;
+/** A list of tor_addr_ts for addresses we've used in outgoing connections.
  * Used to detect IP address changes. */
 static smartlist_t *outgoing_addrs = NULL;
 
@@ -801,11 +801,11 @@ connection_expire_held_open(void)
  *
  * The listenaddr struct has to be freed by the caller.
  */
-static struct sockaddr_in *
+static struct sockaddr_storage *
 create_inet_sockaddr(const char *listenaddress, int listenport,
                      char **readable_address, socklen_t *socklen_out) {
-  struct sockaddr_in *listenaddr = NULL;
-  uint32_t addr;
+  struct sockaddr_storage *listenaddr = NULL;
+  tor_addr_t addr;
   uint16_t usePort = 0;
 
   if (parse_addr_port(LOG_WARN,
@@ -819,12 +819,9 @@ create_inet_sockaddr(const char *listenaddress, int listenport,
       usePort = listenport;
   }
 
-  listenaddr = tor_malloc_zero(sizeof(struct sockaddr_in));
-  listenaddr->sin_addr.s_addr = htonl(addr);
-  listenaddr->sin_family = AF_INET;
-  listenaddr->sin_port = htons((uint16_t) usePort);
-
-  *socklen_out = sizeof(struct sockaddr_in);
+  listenaddr = tor_malloc_zero(sizeof(*listenaddr));
+  tor_addr_to_sockaddr(&addr, usePort, listenaddr, sizeof(*listenaddr));
+  *socklen_out = sizeof(*listenaddr);
 
   return listenaddr;
 
@@ -917,7 +914,7 @@ connection_create_listener(const struct sockaddr *listensockaddr,
     return NULL;
   }
 
-  if (listensockaddr->sa_family == AF_INET) {
+  if (listensockaddr->sa_family == AF_INET || listensockaddr->sa_family == AF_INET6) {
     tor_addr_t addr;
     int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
 #ifndef MS_WINDOWS
@@ -931,7 +928,7 @@ connection_create_listener(const struct sockaddr *listensockaddr,
     log_notice(LD_NET, "Opening %s on %s:%d",
                conn_type_to_string(type), fmt_addr(&addr), usePort);
 
-    s = tor_open_socket(PF_INET,
+    s = tor_open_socket(tor_addr_protocol(&addr),
                         is_tcp ? SOCK_STREAM : SOCK_DGRAM,
                         is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
     if (s < 0) {
@@ -1125,16 +1122,12 @@ connection_handle_listener_read(connection_t *conn, int new_type)
   int news; /* the new socket */
   connection_t *newconn;
   /* information about the remote peer when connecting to other routers */
-  char addrbuf[256];
-  struct sockaddr *remote = (struct sockaddr*)addrbuf;
+  struct sockaddr_storage remote;
   /* length of the remote address. Must be whatever accept() needs. */
-  socklen_t remotelen = (socklen_t)sizeof(addrbuf);
+  socklen_t remotelen = (socklen_t)sizeof(remote);
   or_options_t *options = get_options();
 
-  tor_assert((size_t)remotelen >= sizeof(struct sockaddr_in));
-  memset(addrbuf, 0, sizeof(addrbuf));
-
-  news = tor_accept_socket(conn->s,remote,&remotelen);
+  news = tor_accept_socket(conn->s,&remote,&remotelen);
   if (news < 0) { /* accept() error */
     int e = tor_socket_errno(conn->s);
     if (ERRNO_IS_ACCEPT_EAGAIN(e)) {
@@ -1158,7 +1151,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
   if (options->ConstrainedSockets)
     set_constrained_socket_buffers(news, (int)options->ConstrainedSockSize);
 
-  if (check_sockaddr_family_match(remote->sa_family, conn) < 0) {
+  if (check_sockaddr_family_match(remote.ss_family, conn) < 0) {
     tor_close_socket(news);
     return 0;
   }
@@ -1166,17 +1159,17 @@ connection_handle_listener_read(connection_t *conn, int new_type)
   if (conn->socket_family == AF_INET || conn->socket_family == AF_INET6) {
     tor_addr_t addr;
     uint16_t port;
-    if (check_sockaddr(remote, remotelen, LOG_INFO)<0) {
+    if (check_sockaddr((struct sockaddr *)&remote, remotelen, LOG_INFO)<0) {
       log_info(LD_NET,
                "accept() returned a strange address; trying getsockname().");
-      remotelen=sizeof(addrbuf);
-      memset(addrbuf, 0, sizeof(addrbuf));
-      if (getsockname(news, remote, &remotelen)<0) {
+      remotelen=sizeof(remote);
+      memset(&remote, 0, sizeof(remote));
+      if (getsockname(news, (struct sockaddr *)&remote, &remotelen)<0) {
         int e = tor_socket_errno(news);
         log_warn(LD_NET, "getsockname() for new connection failed: %s",
                  tor_socket_strerror(e));
       } else {
-        if (check_sockaddr((struct sockaddr*)addrbuf, remotelen,
+        if (check_sockaddr((struct sockaddr*)&remote, remotelen,
                               LOG_WARN) < 0) {
           log_warn(LD_NET,"Something's wrong with this conn. Closing it.");
           tor_close_socket(news);
@@ -1185,12 +1178,12 @@ connection_handle_listener_read(connection_t *conn, int new_type)
       }
     }
 
-    if (check_sockaddr_family_match(remote->sa_family, conn) < 0) {
+    if (check_sockaddr_family_match(remote.ss_family, conn) < 0) {
       tor_close_socket(news);
       return 0;
     }
 
-    tor_addr_from_sockaddr(&addr, remote, &port);
+    tor_addr_from_sockaddr(&addr, (struct sockaddr *)&remote, &port);
 
     /* process entrance policies here, before we even create the connection */
     if (new_type == CONN_TYPE_AP) {
@@ -1304,23 +1297,16 @@ connection_connect(connection_t *conn, const char *address,
                    const tor_addr_t *addr, uint16_t port, int *socket_error)
 {
   int s, inprogress = 0;
-  char addrbuf[256];
-  struct sockaddr *dest_addr;
+  struct sockaddr_storage dest_addr;
   int dest_addr_len;
   or_options_t *options = get_options();
-  int protocol_family;
 
   if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
     warn_too_many_conns();
     return -1;
   }
 
-  if (tor_addr_family(addr) == AF_INET6)
-    protocol_family = PF_INET6;
-  else
-    protocol_family = PF_INET;
-
-  s = tor_open_socket(protocol_family,SOCK_STREAM,IPPROTO_TCP);
+  s = tor_open_socket(tor_addr_protocol(addr),SOCK_STREAM,IPPROTO_TCP);
   if (s < 0) {
     *socket_error = tor_socket_errno(-1);
     log_warn(LD_NET,"Error creating network socket: %s",
@@ -1329,17 +1315,15 @@ connection_connect(connection_t *conn, const char *address,
   }
 
   if (options->OutboundBindAddress && !tor_addr_is_loopback(addr)) {
-    struct sockaddr_in ext_addr;
-
-    memset(&ext_addr, 0, sizeof(ext_addr));
-    ext_addr.sin_family = AF_INET;
-    ext_addr.sin_port = 0;
-    if (!tor_inet_aton(options->OutboundBindAddress, &ext_addr.sin_addr)) {
+    tor_addr_t ext_addr;
+    if (tor_addr_from_str(&ext_addr, options->OutboundBindAddress) < 0) {
       log_warn(LD_CONFIG,"Outbound bind address '%s' didn't parse. Ignoring.",
                options->OutboundBindAddress);
     } else {
-      if (bind(s, (struct sockaddr*)&ext_addr,
-               (socklen_t)sizeof(ext_addr)) < 0) {
+      int socklen;
+      struct sockaddr_storage ss;
+      socklen = tor_addr_to_sockaddr(&ext_addr, 0, &ss, sizeof(ss));
+      if (bind(s, (struct sockaddr*)&ss, socklen) < 0) {
         *socket_error = tor_socket_errno(s);
         log_warn(LD_NET,"Error binding network socket: %s",
                  tor_socket_strerror(*socket_error));
@@ -1354,15 +1338,14 @@ connection_connect(connection_t *conn, const char *address,
   if (options->ConstrainedSockets)
     set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize);
 
-  memset(addrbuf,0,sizeof(addrbuf));
-  dest_addr = (struct sockaddr*) addrbuf;
-  dest_addr_len = tor_addr_to_sockaddr(addr, port, dest_addr, sizeof(addrbuf));
+  memset(&dest_addr,0,sizeof(dest_addr));
+  dest_addr_len = tor_addr_to_sockaddr(addr, port, &dest_addr, sizeof(dest_addr));
   tor_assert(dest_addr_len > 0);
 
   log_debug(LD_NET, "Connecting to %s:%u.",
             escaped_safe_str_client(address), port);
 
-  if (connect(s, dest_addr, (socklen_t)dest_addr_len) < 0) {
+  if (connect(s, (struct sockaddr*)&dest_addr, (socklen_t)dest_addr_len) < 0) {
     int e = tor_socket_errno(s);
     if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
       /* yuck. kill it. */
@@ -1891,8 +1874,10 @@ retry_listeners(int type, config_line_t *cfg,
         struct sockaddr *listensockaddr;
         socklen_t listensocklen = 0;
 
+        /* XXX-IPv6: could gust use sockaddr_storage as everything fits in it */
         switch (socket_family) {
           case AF_INET:
+          case AF_INET6:
             listensockaddr = (struct sockaddr *)
                              create_inet_sockaddr(cfg_line->value,
                                                   port_option,
@@ -3598,13 +3583,13 @@ alloc_http_authenticator(const char *authenticator)
 static void
 client_check_address_changed(int sock)
 {
-  uint32_t iface_ip, ip_out; /* host order */
-  struct sockaddr_in out_addr;
-  socklen_t out_addr_len = (socklen_t) sizeof(out_addr);
-  uint32_t *ip; /* host order */
+  tor_addr_t iface_ip, ip_out;
+  struct sockaddr_storage out_addr;
+  socklen_t out_addr_len = (socklen_t)sizeof(out_addr);
+  tor_addr_t *ip;
 
-  if (!last_interface_ip)
-    get_interface_address(LOG_INFO, &last_interface_ip);
+  if (tor_addr_is_null(&last_interface_ip))
+    get_interface_address6(LOG_INFO, AF_UNSPEC, &last_interface_ip);
   if (!outgoing_addrs)
     outgoing_addrs = smartlist_create();
 
@@ -3616,27 +3601,27 @@ client_check_address_changed(int sock)
   }
 
   /* If we've used this address previously, we're okay. */
-  ip_out = ntohl(out_addr.sin_addr.s_addr);
-  SMARTLIST_FOREACH(outgoing_addrs, uint32_t*, ip_ptr,
-                    if (*ip_ptr == ip_out) return;
+  tor_addr_from_sockaddr(&ip_out, (const struct sockaddr *)&out_addr, NULL);
+  SMARTLIST_FOREACH(outgoing_addrs, tor_addr_t *, ip_ptr,
+                    if (tor_addr_eq(ip_ptr, &ip_out)) return;
                     );
 
   /* Uh-oh.  We haven't connected from this address before. Has the interface
    * address changed? */
-  if (get_interface_address(LOG_INFO, &iface_ip)<0)
+  if (get_interface_address6(LOG_INFO, AF_UNSPEC, &iface_ip)<0)
     return;
-  ip = tor_malloc(sizeof(uint32_t));
+  ip = tor_malloc(sizeof(*ip));
   *ip = ip_out;
 
-  if (iface_ip == last_interface_ip) {
+  if (tor_addr_eq(&iface_ip, &last_interface_ip)) {
     /* Nope, it hasn't changed.  Add this address to the list. */
     smartlist_add(outgoing_addrs, ip);
   } else {
     /* The interface changed.  We're a client, so we need to regenerate our
      * keys.  First, reset the state. */
     log(LOG_NOTICE, LD_NET, "Our IP address has changed.  Rotating keys...");
-    last_interface_ip = iface_ip;
-    SMARTLIST_FOREACH(outgoing_addrs, void*, ip_ptr, tor_free(ip_ptr));
+    tor_addr_copy(&last_interface_ip, &iface_ip);
+    SMARTLIST_FOREACH(outgoing_addrs, void *, ip_ptr, tor_free(ip_ptr));
     smartlist_clear(outgoing_addrs);
     smartlist_add(outgoing_addrs, ip);
     /* Okay, now change our keys. */
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 186137b..5448330 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -701,6 +701,7 @@ typedef struct {
 /** Entry for mapping addresses to which virtual address we mapped them to. */
 typedef struct {
   char *ipv4_address;
+  char *ipv6_address;
   char *hostname_address;
 } virtaddress_entry_t;
 
@@ -749,6 +750,7 @@ addressmap_virtaddress_ent_free(void *_ent)
 
   ent = _ent;
   tor_free(ent->ipv4_address);
+  tor_free(ent->ipv6_address);
   tor_free(ent->hostname_address);
   tor_free(ent);
 }
@@ -765,9 +767,11 @@ addressmap_virtaddress_remove(const char *address, addressmap_entry_t *ent)
     if (ve) {
       if (!strcmp(address, ve->ipv4_address))
         tor_free(ve->ipv4_address);
+      if (!strcmp(address, ve->ipv6_address))
+        tor_free(ve->ipv6_address);
       if (!strcmp(address, ve->hostname_address))
         tor_free(ve->hostname_address);
-      if (!ve->ipv4_address && !ve->hostname_address) {
+      if (!ve->ipv4_address && !ve->ipv6_address && !ve->hostname_address) {
         tor_free(ve);
         strmap_remove(virtaddress_reversemap, ent->new_address);
       }
@@ -1132,19 +1136,18 @@ client_dns_set_addressmap_impl(const char *address, const char *name,
  * <b>ttl</b>seconds; otherwise, we use the default.
  */
 void
-client_dns_set_addressmap(const char *address, uint32_t val,
+client_dns_set_addressmap(const char *address, tor_addr_t *val,
                           const char *exitname,
                           int ttl)
 {
-  struct in_addr in;
+  tor_addr_t a;
   char valbuf[INET_NTOA_BUF_LEN];
 
   tor_assert(address);
 
-  if (tor_inet_aton(address, &in))
+  if (tor_inet_pton(AF_UNSPEC, address, &a))
     return; /* If address was an IP address already, don't add a mapping. */
-  in.s_addr = htonl(val);
-  tor_inet_ntoa(&in,valbuf,sizeof(valbuf));
+  tor_addr_to_str(val,valbuf,sizeof(valbuf),0);
 
   client_dns_set_addressmap_impl(address, valbuf, exitname, ttl);
 }
@@ -1194,7 +1197,7 @@ int
 parse_virtual_addr_network(const char *val, int validate_only,
                            char **msg)
 {
-  uint32_t addr;
+  tor_addr_t addr, nxt;
   uint16_t port_min, port_max;
   maskbits_t bits;
 
@@ -1217,11 +1220,12 @@ parse_virtual_addr_network(const char *val, int validate_only,
   if (validate_only)
     return 0;
 
-  virtual_addr_network = (uint32_t)( addr & (0xfffffffful << (32-bits)) );
+  virtual_addr_network = (uint32_t)( tor_addr_to_ipv4h(&addr) & (0xfffffffful << (32-bits)) );
   virtual_addr_netmask_bits = bits;
 
-  if (addr_mask_cmp_bits(next_virtual_addr, addr, bits))
-    next_virtual_addr = addr;
+  tor_addr_from_ipv4n(&addr, htonl(next_virtual_addr));
+  if (tor_addr_mask_cmp_bits(&nxt, &addr, bits))
+    next_virtual_addr = tor_addr_to_ipv4h(&addr);
 
   return 0;
 }
@@ -1233,14 +1237,13 @@ parse_virtual_addr_network(const char *val, int validate_only,
 static int
 address_is_in_virtual_range(const char *address)
 {
-  struct in_addr in;
+  tor_addr_t a, b;
   tor_assert(address);
   if (!strcasecmpend(address, ".virtual")) {
     return 1;
-  } else if (tor_inet_aton(address, &in)) {
-    uint32_t addr = ntohl(in.s_addr);
-    if (!addr_mask_cmp_bits(addr, virtual_addr_network,
-                            virtual_addr_netmask_bits))
+  } else if (tor_inet_pton(AF_UNSPEC, address, &a)) {
+    tor_addr_from_ipv4n(&b, virtual_addr_network);
+    if (!tor_addr_mask_cmp_bits(&a, &b, virtual_addr_netmask_bits))
       return 1;
   }
   return 0;
@@ -1248,18 +1251,21 @@ address_is_in_virtual_range(const char *address)
 
 /** Increment the value of next_virtual_addr; reset it to the start of the
  * virtual address range if it wraps around.
+ * XXX-IPv6: IPv4-only
  */
 static INLINE void
 increment_virtual_addr(void)
 {
+  tor_addr_t nxt, vnet;
   ++next_virtual_addr;
-  if (addr_mask_cmp_bits(next_virtual_addr, virtual_addr_network,
-                         virtual_addr_netmask_bits))
+  tor_addr_from_ipv4n(&nxt, htonl(next_virtual_addr));
+  tor_addr_from_ipv4n(&vnet, htonl(virtual_addr_network));
+  if (tor_addr_mask_cmp_bits(&nxt, &vnet, virtual_addr_netmask_bits))
     next_virtual_addr = virtual_addr_network;
 }
 
 /** Return a newly allocated string holding an address of <b>type</b>
- * (one of RESOLVED_TYPE_{IPV4|HOSTNAME}) that has not yet been mapped,
+ * (one of RESOLVED_TYPE_{IPV4|HOSTNAME|IPV6}) that has not yet been mapped,
  * and that is very unlikely to be the address of any real host.
  *
  * May return NULL if we have run out of virtual addresses.
@@ -1309,6 +1315,10 @@ addressmap_get_virtual_address(int type)
       }
     }
     return tor_strdup(buf);
+  } else if (type == RESOLVED_TYPE_IPV6) {
+    /* XXX-IPv6: implement this */
+    log_warn(LD_CONFIG, "IPv6 code missing in this spot");
+    return NULL;
   } else {
     log_warn(LD_BUG, "Called with unsupported address type (%d)", type);
     return NULL;
@@ -1341,8 +1351,9 @@ addressmap_register_virtual_address(int type, char *new_address)
     vent_needs_to_be_added = 1;
   }
 
-  addrp = (type == RESOLVED_TYPE_IPV4) ?
-    &vent->ipv4_address : &vent->hostname_address;
+  addrp = (type == RESOLVED_TYPE_IPV4 ? &vent->ipv4_address :
+           type == RESOLVED_TYPE_IPV6 ? &vent->ipv6_address :
+                                        &vent->hostname_address);
   if (*addrp) {
     addressmap_entry_t *ent = strmap_get(addressmap, *addrp);
     if (ent && ent->new_address &&
@@ -1382,8 +1393,9 @@ addressmap_register_virtual_address(int type, char *new_address)
     vent = strmap_get(virtaddress_reversemap, new_address);
     tor_assert(vent);
     tor_assert(!strcasecmp(*addrp,
-                           (type == RESOLVED_TYPE_IPV4) ?
-                           vent->ipv4_address : vent->hostname_address));
+                           (type == RESOLVED_TYPE_IPV4 ? vent->ipv4_address
+                            type == RESOLVED_TYPE_IPv6 ? vent->ipv6_address :
+                                                         vent->hostname_address));
     log_info(LD_APP, "Map from %s to %s okay.",
              safe_str_client(*addrp),
              safe_str_client(new_address));
@@ -1544,7 +1556,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
   socks_request_t *socks = conn->socks_request;
   hostname_type_t addresstype;
   or_options_t *options = get_options();
-  struct in_addr addr_tmp;
+  tor_addr_t addr_tmp;
   /* We set this to true if this is an address we should automatically
    * remap to a local address in VirtualAddrNetwork */
   int automap = 0;
@@ -1562,14 +1574,14 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
             socks->port);
 
   if (socks->command == SOCKS_COMMAND_RESOLVE &&
-      !tor_inet_aton(socks->address, &addr_tmp) &&
+      !tor_inet_pton(AF_UNSPEC, socks->address, &addr_tmp) &&
       options->AutomapHostsOnResolve && options->AutomapHostsSuffixes) {
     SMARTLIST_FOREACH(options->AutomapHostsSuffixes, const char *, cp,
                       if (!strcasecmpend(socks->address, cp)) {
                         automap = 1;
                         break;
                       });
-    if (automap) {
+    if (automap) { /* XXX-IPv6: Need to handle IPv6 here too? */
       const char *new_addr;
       new_addr = addressmap_register_virtual_address(
                               RESOLVED_TYPE_IPV4, tor_strdup(socks->address));
@@ -1730,20 +1742,20 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
     }
 
     if (socks->command == SOCKS_COMMAND_RESOLVE) {
-      uint32_t answer;
-      struct in_addr in;
+      tor_addr_t addr;
       /* Reply to resolves immediately if we can. */
-      if (tor_inet_aton(socks->address, &in)) { /* see if it's an IP already */
-        /* leave it in network order */
-        answer = in.s_addr;
+      if (tor_inet_pton(AF_UNSPEC, socks->address, &addr)) { /* see if it's an IP already */
         /* remember _what_ is supposed to have been resolved. */
         strlcpy(socks->address, orig_address, sizeof(socks->address));
-        connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4,
-                                               (uint8_t*)&answer,
-                                               -1,map_expires);
+        /* We do a tor_addr_raw() here but convert it back to a tor_addr in the function... */
+        connection_ap_handshake_socks_resolved(conn,
+               tor_addr_family(&addr) == AF_INET ? RESOLVED_TYPE_IPV4 : RESOLVED_TYPE_IPV6,
+               tor_addr_family(&addr) == AF_INET ? 4 : 16,
+               tor_addr_raw(&addr),
+               -1,map_expires);
         connection_mark_unattached_ap(conn,
-                                END_STREAM_REASON_DONE |
-                                END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
+               END_STREAM_REASON_DONE |
+               END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
         return 0;
       }
       tor_assert(!automap);
@@ -1945,7 +1957,7 @@ connection_ap_get_original_destination(edge_connection_t *conn,
   }
 
   tor_addr_from_sockaddr(&addr, (struct sockaddr*)&orig_dst, &req->port);
-  tor_addr_to_str(req->address, &addr, sizeof(req->address), 0);
+  tor_addr_to_str(&addr, req->address, sizeof(req->address), 0);
 
   return 0;
 #elif defined(TRANS_PF)
@@ -2006,7 +2018,7 @@ connection_ap_get_original_destination(edge_connection_t *conn,
     return -1;
   }
 
-  tor_addr_to_str(req->address, &addr, sizeof(req->address), 0);
+  tor_addr_to_str(&addr, req->address, sizeof(req->address), 0);
   req->port = ntohs(pnl.rdport);
 
   return 0;
@@ -2455,10 +2467,13 @@ tell_controller_about_resolved_result(edge_connection_t *conn,
 {
 
   if (ttl >= 0 && (answer_type == RESOLVED_TYPE_IPV4 ||
+                   answer_type == RESOLVED_TYPE_IPV6 ||
                    answer_type == RESOLVED_TYPE_HOSTNAME)) {
     return; /* we already told the controller. */
   } else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) {
-    char *cp = tor_dup_ip(get_uint32(answer));
+    tor_addr_t addr;
+    char *cp = NULL;
+    tor_addr_from_ipv4n(&addr, get_uint32(answer));
     control_event_address_mapped(conn->socks_request->address,
                                  cp, expires, NULL);
     tor_free(cp);
@@ -2467,6 +2482,14 @@ tell_controller_about_resolved_result(edge_connection_t *conn,
     control_event_address_mapped(conn->socks_request->address,
                                  cp, expires, NULL);
     tor_free(cp);
+  } else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len >= 16) {
+    tor_addr_t addr;
+    char *cp = NULL;
+    tor_addr_from_ipv6_bytes(&addr, answer);
+    cp = tor_dup_ip(&addr);
+    control_event_address_mapped(conn->socks_request->address,
+                                 cp, expires, NULL);
+    tor_free(cp);
   } else {
     control_event_address_mapped(conn->socks_request->address,
                                  "<error>",
@@ -2497,16 +2520,21 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
 
   if (ttl >= 0) {
     if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
-      uint32_t a = ntohl(get_uint32(answer));
-      if (a)
-        client_dns_set_addressmap(conn->socks_request->address, a,
-                                  conn->chosen_exit_name, ttl);
+      tor_addr_t a;
+      tor_addr_from_ipv4n(&a, ntohl(get_uint32(answer)));
+      client_dns_set_addressmap(conn->socks_request->address, &a,
+                                conn->chosen_exit_name, ttl);
     } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
       char *cp = tor_strndup((char*)answer, answer_len);
       client_dns_set_reverse_addressmap(conn->socks_request->address,
                                         cp,
                                         conn->chosen_exit_name, ttl);
       tor_free(cp);
+    } else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) {
+      tor_addr_t a;
+      tor_addr_from_ipv4n(&a, ntohl(get_uint32(answer)));
+      client_dns_set_addressmap(conn->socks_request->address, &a,
+                                conn->chosen_exit_name, ttl);
     }
   }
 
@@ -3083,12 +3111,11 @@ connection_ap_can_use_exit(edge_connection_t *conn, const node_t *exit)
 
   if (conn->socks_request->command == SOCKS_COMMAND_CONNECT &&
       !conn->use_begindir) {
-    struct in_addr in;
-    uint32_t addr = 0;
+    tor_addr_t addr;
     addr_policy_result_t r;
-    if (tor_inet_aton(conn->socks_request->address, &in))
-      addr = ntohl(in.s_addr);
-    r = compare_addr_to_node_policy(addr, conn->socks_request->port, exit);
+    if (!tor_inet_pton(AF_UNSPEC, conn->socks_request->address, &addr))
+      return 0; /* Failed to fixup address */
+    r = compare_tor_addr_to_node_policy(&addr, conn->socks_request->port, exit);
     if (r == ADDR_POLICY_REJECTED)
       return 0; /* We know the address, and the exit policy rejects it. */
     if (r == ADDR_POLICY_PROBABLY_REJECTED && !conn->chosen_exit_name)
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index 562db5b..8a4c9bc 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -77,7 +77,7 @@ int parse_virtual_addr_network(const char *val, int validate_only,
                                char **msg);
 int client_dns_incr_failures(const char *address);
 void client_dns_clear_failures(const char *address);
-void client_dns_set_addressmap(const char *address, uint32_t val,
+void client_dns_set_addressmap(const char *address, tor_addr_t *val,
                                const char *exitname, int ttl);
 const char *addressmap_register_virtual_address(int type, char *new_address);
 void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 73aad7e..9397d92 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -462,10 +462,8 @@ connection_or_init_conn_from_address(or_connection_t *conn,
   tor_addr_copy(&conn->_base.addr, addr);
   tor_addr_copy(&conn->real_addr, addr);
   if (r) {
-    tor_addr_t node_addr;
-    node_get_addr(r, &node_addr);
     /* XXXX proposal 118 will make this more complex. */
-    if (tor_addr_eq(&conn->_base.addr, &node_addr))
+    if (tor_addr_eq(&conn->_base.addr, node_get_addr(r)))
       conn->is_canonical = 1;
     if (!started_here) {
       /* Override the addr/port, so our log messages will make sense.
@@ -478,12 +476,12 @@ connection_or_init_conn_from_address(or_connection_t *conn,
        * right IP address and port 56244, that wouldn't be as helpful. now we
        * log the "right" port too, so we know if it's moria1 or moria2.
        */
-      tor_addr_copy(&conn->_base.addr, &node_addr);
+      tor_addr_copy(&conn->_base.addr, node_get_addr(r));
       conn->_base.port = node_get_orport(r);
     }
     conn->nickname = tor_strdup(node_get_nickname(r));
     tor_free(conn->_base.address);
-    conn->_base.address = tor_dup_addr(&node_addr);
+    conn->_base.address = tor_dup_addr(node_get_addr(r));
   } else {
     const char *n;
     /* If we're an authoritative directory server, we may know a
@@ -592,7 +590,7 @@ connection_or_get_for_extend(const char *digest,
     if (conn->_base.state != OR_CONN_STATE_OPEN) {
       /* If the address matches, don't launch a new connection for this
        * circuit. */
-      if (!tor_addr_compare(&conn->real_addr, target_addr, CMP_EXACT))
+      if (!tor_addr_eq(&conn->real_addr, target_addr))
         ++n_inprogress_goodaddr;
       continue;
     }
@@ -609,7 +607,7 @@ connection_or_get_for_extend(const char *digest,
      * have an out-of-date descriptor, and we will get no NETINFO cell to
      * tell us about the right address.) */
     if (!conn->is_canonical && conn->link_proto >= 2 &&
-        tor_addr_compare(&conn->real_addr, target_addr, CMP_EXACT)) {
+        tor_addr_eq(&conn->real_addr, target_addr)) {
       ++n_noncanonical;
       continue;
     }
@@ -761,8 +759,7 @@ connection_or_group_set_badness(or_connection_t *head, int force)
                  (int)(now - or_conn->_base.timestamp_created),
                  best->_base.s, (int)(now - best->_base.timestamp_created));
         or_conn->is_bad_for_new_circs = 1;
-      } else if (!tor_addr_compare(&or_conn->real_addr,
-                                   &best->real_addr, CMP_EXACT)) {
+      } else if (!tor_addr_eq(&or_conn->real_addr, &best->real_addr)) {
         log_info(LD_OR,
                  "Marking OR conn to %s:%d as unsuitable for new circuits: "
                  "(fd %d, %d secs old).  We have a better one with the "
@@ -1352,9 +1349,7 @@ connection_or_set_state_open(or_connection_t *conn)
     /* only report it to the geoip module if it's not a known router */
     if (!router_get_by_id_digest(conn->identity_digest)) {
       if (tor_addr_family(&TO_CONN(conn)->addr) == AF_INET) {
-        /*XXXX IP6 support ipv6 geoip.*/
-        uint32_t a = tor_addr_to_ipv4h(&TO_CONN(conn)->addr);
-        geoip_note_client_seen(GEOIP_CLIENT_CONNECT, a, now);
+        geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(conn)->addr, now);
       }
     }
   }
@@ -1561,7 +1556,7 @@ connection_or_send_netinfo(or_connection_t *conn)
     tor_addr_t my_addr;
     *out++ = 1; /* only one address is supported. */
 
-    tor_addr_from_ipv4h(&my_addr, me->addr);
+    tor_addr_copy(&my_addr, &me->addr);
     len = append_address_to_payload(out, &my_addr);
     if (len < 0)
       return -1;
diff --git a/src/or/control.c b/src/or/control.c
index e0e8f7e..b867fbc 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1393,12 +1393,12 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
   } else if (!strcmp(question, "features/names")) {
     *answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
   } else if (!strcmp(question, "address")) {
-    uint32_t addr;
+    tor_addr_t addr;
     if (router_pick_published_address(get_options(), &addr) < 0) {
       *errmsg = "Address unknown";
       return -1;
     }
-    *answer = tor_dup_ip(addr);
+    *answer = tor_dup_ip(&addr);
   } else if (!strcmp(question, "traffic/read")) {
     tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_read()));
   } else if (!strcmp(question, "traffic/written")) {
@@ -1561,9 +1561,11 @@ getinfo_helper_listeners(control_connection_t *control_conn,
     if (getsockname(conn->s, (struct sockaddr *)&ss, &ss_len) < 0) {
       tor_asprintf(&addr, "%s:%d", conn->address, (int)conn->port);
     } else {
-      char *tmp = tor_sockaddr_to_str((struct sockaddr *)&ss);
+      tor_addr_t a;
+      char tmp[128];
+      tor_addr_from_sockaddr(&a, (struct sockaddr *)&ss, NULL);
+      tor_addr_to_str(&a, tmp, sizeof(tmp),1);
       addr = esc_for_log(tmp);
-      tor_free(tmp);
     }
     if (addr)
       smartlist_add(res, addr);
@@ -3163,7 +3165,6 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
 {
   const char *status;
   char extended_buf[96];
-  int providing_reason=0;
   if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
     return 0;
   tor_assert(circ);
@@ -3187,7 +3188,6 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
     const char *reason_str = circuit_end_reason_to_control_string(reason_code);
     char *reason = NULL;
     size_t n=strlen(extended_buf);
-    providing_reason=1;
     if (!reason_str) {
       reason = tor_malloc(16);
       tor_snprintf(reason, 16, "UNKNOWN_%d", reason_code);
diff --git a/src/or/directory.c b/src/or/directory.c
index c0378a4..bb45f2f 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -296,7 +296,6 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
   SMARTLIST_FOREACH_BEGIN(dirservers, trusted_dir_server_t *, ds) {
       routerstatus_t *rs = &(ds->fake_status);
       size_t upload_len = payload_len;
-      tor_addr_t ds_addr;
 
       if ((type & ds->type) == 0)
         continue;
@@ -320,9 +319,8 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
         log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
                  (int) extrainfo_len);
       }
-      tor_addr_from_ipv4h(&ds_addr, ds->addr);
       post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) ||
-        !fascist_firewall_allows_address_dir(&ds_addr, ds->dir_port);
+        !fascist_firewall_allows_address_dir(&ds->addr, ds->dir_port);
       directory_initiate_command_routerstatus(rs, dir_purpose,
                                               router_purpose,
                                               post_via_tor,
@@ -422,10 +420,8 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
       const node_t *node = choose_random_entry(NULL);
       if (node && node->ri) {
         /* every bridge has a routerinfo. */
-        tor_addr_t addr;
         routerinfo_t *ri = node->ri;
-        node_get_addr(node, &addr);
-        directory_initiate_command(ri->address, &addr,
+        directory_initiate_command(ri->address, node_get_addr(node),
                                    ri->or_port, 0,
                                    0, /* don't use conditional consensus url */
                                    1, ri->cache_info.identity_digest,
@@ -546,9 +542,7 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
   or_options_t *options = get_options();
   const node_t *node;
   char address_buf[INET_NTOA_BUF_LEN+1];
-  struct in_addr in;
   const char *address;
-  tor_addr_t addr;
   node = node_get_by_id(status->identity_digest);
 
   if (!node && anonymized_connection) {
@@ -559,11 +553,9 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
     node_get_address_string(node, address_buf, sizeof(address_buf));
     address = address_buf;
   } else {
-    in.s_addr = htonl(status->addr);
-    tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
+    tor_addr_to_str(&status->addr, address_buf, sizeof(address_buf), 1);
     address = address_buf;
   }
-  tor_addr_from_ipv4h(&addr, status->addr);
 
   if (options->ExcludeNodes && options->StrictNodes &&
       routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
@@ -575,7 +567,7 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
     return;
   }
 
-  directory_initiate_command_rend(address, &addr,
+  directory_initiate_command_rend(address, &status->addr,
                              status->or_port, status->dir_port,
                              status->version_supports_conditional_consensus,
                              status->version_supports_begindir,
@@ -628,7 +620,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn)
     const routerinfo_t *me = router_get_my_routerinfo();
     if (me &&
         router_digest_is_me(conn->identity_digest) &&
-        tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/
+        tor_addr_eq(&conn->_base.addr, &me->addr) && /*XXXX prop 118*/
         me->dir_port == conn->_base.port)
       return 1;
   }
@@ -1361,8 +1353,8 @@ http_set_address_origin(const char *headers, connection_t *conn)
   if (!fwd)
     fwd = http_get_header(headers, "X-Forwarded-For: ");
   if (fwd) {
-    struct in_addr in;
-    if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
+    tor_addr_t addr;
+    if (!tor_inet_pton(AF_UNSPEC, fwd, &addr) || tor_addr_is_internal(&addr, 0)) {
       log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
                 escaped(fwd));
       tor_free(fwd);
@@ -2799,9 +2791,9 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
     }
 
     {
-      struct in_addr in;
-      if (tor_inet_aton((TO_CONN(conn))->address, &in)) {
-        geoip_note_client_seen(act, ntohl(in.s_addr), time(NULL));
+      tor_addr_t addr;
+      if (tor_inet_pton(AF_UNSPEC, (TO_CONN(conn))->address, &addr)) {
+        geoip_note_client_seen(act, &addr, time(NULL));
         geoip_note_ns_response(act, GEOIP_SUCCESS);
         /* Note that a request for a network status has started, so that we
          * can measure the download time later on. */
@@ -3238,7 +3230,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
   }while(0);
 
   if (!strcmp(url,"/tor/mallinfo.txt") &&
-      (tor_addr_eq_ipv4h(&conn->_base.addr, 0x7f000001ul))) {
+      (tor_addr_is_loopback(&conn->_base.addr))) {
     char *result;
     size_t len;
     struct mallinfo mi;
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index aa2e74b..a8bb780 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -71,7 +71,7 @@ static int add_fingerprint_to_dir(const char *nickname, const char *fp,
 static uint32_t
 dirserv_get_status_impl(const char *fp, const char *nickname,
                         const char *address,
-                        uint32_t addr, uint16_t or_port,
+                        const tor_addr_t *addr, uint16_t or_port,
                         const char *platform, const char *contact,
                         const char **msg, int should_log);
 static void clear_cached_dir(cached_dir_t *d);
@@ -319,7 +319,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg)
 
   return dirserv_get_status_impl(d, router->nickname,
                                  router->address,
-                                 router->addr, router->or_port,
+                                 &router->addr, router->or_port,
                                  router->platform, router->contact_info,
                                  msg, 1);
 }
@@ -333,7 +333,7 @@ dirserv_would_reject_router(const routerstatus_t *rs)
 
   res = dirserv_get_status_impl(rs->identity_digest, rs->nickname,
                                 "", /* address is only used in logs */
-                                rs->addr, rs->or_port,
+                                &rs->addr, rs->or_port,
                                 NULL, NULL,
                                 NULL, 0);
 
@@ -372,7 +372,7 @@ dirserv_get_name_status(const char *id_digest, const char *nickname)
 static uint32_t
 dirserv_get_status_impl(const char *id_digest, const char *nickname,
                         const char *address,
-                        uint32_t addr, uint16_t or_port,
+                        const tor_addr_t *addr, uint16_t or_port,
                         const char *platform, const char *contact,
                         const char **msg, int should_log)
 {
@@ -514,15 +514,15 @@ dirserv_free_fingerprint_list(void)
 static int
 dirserv_router_has_valid_address(routerinfo_t *ri)
 {
-  struct in_addr iaddr;
+  tor_addr_t iaddr;
   if (get_options()->DirAllowPrivateAddresses)
     return 0; /* whatever it is, we're fine with it */
-  if (!tor_inet_aton(ri->address, &iaddr)) {
+  if (!tor_inet_pton(AF_UNSPEC, ri->address, &iaddr)) {
     log_info(LD_DIRSERV,"Router '%s' published non-IP address '%s'. Refusing.",
              ri->nickname, ri->address);
     return -1;
   }
-  if (is_internal_IP(ntohl(iaddr.s_addr), 0)) {
+  if (tor_addr_is_internal(&iaddr,0)) {
     log_info(LD_DIRSERV,
              "Router '%s' published internal IP address '%s'. Refusing.",
              ri->nickname, ri->address);
@@ -1196,7 +1196,7 @@ int
 directory_fetches_from_authorities(or_options_t *options)
 {
   const routerinfo_t *me;
-  uint32_t addr;
+  tor_addr_t addr;
   int refuseunknown;
   if (options->FetchDirInfoEarly)
     return 1;
@@ -2044,7 +2044,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
                    (format==NS_V3_CONSENSUS_MICRODESC)?"":digest64,
                    (format==NS_V3_CONSENSUS_MICRODESC)?"":" ",
                    published,
-                   fmt_addr32(rs->addr),
+                   fmt_addr(&rs->addr),
                    (int)rs->or_port,
                    (int)rs->dir_port);
   if (r<0) {
@@ -2188,17 +2188,15 @@ static int
 _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
 {
   routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
-  int first_is_auth, second_is_auth;
+  int first_is_auth, second_is_auth, n;
   uint32_t bw_first, bw_second;
   const node_t *node_first, *node_second;
   int first_is_running, second_is_running;
 
   /* we return -1 if first should appear before second... that is,
    * if first is a better router. */
-  if (first->addr < second->addr)
-    return -1;
-  else if (first->addr > second->addr)
-    return 1;
+  n = tor_addr_cmp(&first->addr, &second->addr);
+  if (n != 0) return n;
 
   /* Potentially, this next bit could cause k n lg n memcmp calls.  But in
    * reality, we will almost never get here, since addresses will usually be
@@ -2248,7 +2246,7 @@ get_possible_sybil_list(const smartlist_t *routers)
   or_options_t *options = get_options();
   digestmap_t *omit_as_sybil;
   smartlist_t *routers_by_ip = smartlist_create();
-  uint32_t last_addr;
+  tor_addr_t last_addr;
   int addr_count;
   /* Allow at most this number of Tor servers on a single IP address, ... */
   int max_with_same_addr = options->AuthDirMaxServersPerAddr;
@@ -2263,15 +2261,15 @@ get_possible_sybil_list(const smartlist_t *routers)
   smartlist_sort(routers_by_ip, _compare_routerinfo_by_ip_and_bw);
   omit_as_sybil = digestmap_new();
 
-  last_addr = 0;
+  tor_addr_from_null(&last_addr);
   addr_count = 0;
   SMARTLIST_FOREACH(routers_by_ip, routerinfo_t *, ri,
     {
-      if (last_addr != ri->addr) {
-        last_addr = ri->addr;
+      if (!tor_addr_eq(&last_addr, &ri->addr)) {
+        tor_addr_copy(&last_addr, &ri->addr);
         addr_count = 1;
       } else if (++addr_count > max_with_same_addr) {
-        if (!router_addr_is_trusted_dir(ri->addr) ||
+        if (!router_addr_is_trusted_dir(&ri->addr) ||
             addr_count > max_with_same_addr_on_authority)
           digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri);
       }
@@ -2547,7 +2545,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
 {
   or_options_t *options = get_options();
   networkstatus_t *v3_out = NULL;
-  uint32_t addr;
+  tor_addr_t addr;
   char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
   const char *contact;
   smartlist_t *routers, *routerstatuses;
@@ -2574,7 +2572,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
   }
   if (!strchr(hostname, '.')) {
     tor_free(hostname);
-    hostname = tor_dup_ip(addr);
+    hostname = tor_dup_ip(&addr);
   }
   if (crypto_pk_get_digest(private_key, signing_key_digest)<0) {
     log_err(LD_BUG, "Error computing signing key digest");
@@ -2764,7 +2762,7 @@ generate_v2_networkstatus_opinion(void)
   char fingerprint[FINGERPRINT_LEN+1];
   char published[ISO_TIME_LEN+1];
   char digest[DIGEST_LEN];
-  uint32_t addr;
+  tor_addr_t addr;
   crypto_pk_env_t *private_key;
   routerlist_t *rl = router_get_routerlist();
   time_t now = time(NULL);
@@ -2829,7 +2827,7 @@ generate_v2_networkstatus_opinion(void)
                "dir-options%s%s%s%s\n"
                "%s" /* client version line, server version line. */
                "dir-signing-key\n%s",
-               hostname, fmt_addr32(addr),
+               hostname, fmt_addr(&addr),
                (int)router_get_advertised_dir_port(options),
                fingerprint,
                contact,
@@ -3237,14 +3235,12 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri,
 void
 dirserv_single_reachability_test(time_t now, routerinfo_t *router)
 {
-  tor_addr_t router_addr;
   log_debug(LD_OR,"Testing reachability of %s at %s:%u.",
             router->nickname, router->address, router->or_port);
   /* Remember when we started trying to determine reachability */
   if (!router->testing_since)
     router->testing_since = now;
-  tor_addr_from_ipv4h(&router_addr, router->addr);
-  connection_or_connect(&router_addr, router->or_port,
+  connection_or_connect(&router->addr, router->or_port,
                         router->cache_info.identity_digest);
 }
 
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 6fe29f2..8308d95 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -84,7 +84,6 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
   char *outp, *endp;
   char fingerprint[FINGERPRINT_LEN+1];
   char digest[DIGEST_LEN];
-  uint32_t addr;
   routerlist_t *rl = router_get_routerlist();
   char *version_lines = NULL;
   int r;
@@ -95,8 +94,6 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
 
   voter = smartlist_get(v3_ns->voters, 0);
 
-  addr = voter->addr;
-
   base16_encode(fingerprint, sizeof(fingerprint),
                 v3_ns->cert->cache_info.identity_digest, DIGEST_LEN);
   client_versions = v3_ns->client_versions;
@@ -182,7 +179,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
                  flags,
                  params,
                  voter->nickname, fingerprint, voter->address,
-                 fmt_addr32(addr), voter->dir_port, voter->or_port,
+                 fmt_addr(&voter->addr), voter->dir_port, voter->or_port,
                  voter->contact);
 
     if (r < 0) {
@@ -401,7 +398,7 @@ compare_vote_rs(const vote_routerstatus_t *a, const vote_routerstatus_t *b)
     return r;
   if ((r = strcmp(b->status.nickname, a->status.nickname)))
     return r;
-  if ((r = (((int)b->status.addr) - ((int)a->status.addr))))
+  if ((r = tor_addr_cmp(&b->status.addr, &a->status.addr)))
     return r;
   if ((r = (((int)b->status.or_port) - ((int)a->status.or_port))))
     return r;
@@ -1542,7 +1539,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
       tor_asprintf(&buf,
                    "dir-source %s%s %s %s %s %d %d\n",
                    voter->nickname, e->is_legacy ? "-legacy" : "",
-                   fingerprint, voter->address, fmt_addr32(voter->addr),
+                   fingerprint, voter->address, fmt_addr(&voter->addr),
                    voter->dir_port,
                    voter->or_port);
       smartlist_add(chunks, buf);
diff --git a/src/or/dns.c b/src/or/dns.c
index c8e1012..557368f 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -1204,8 +1204,7 @@ configure_nameservers(int force)
     } else {
       int socklen;
       struct sockaddr_storage ss;
-      socklen = tor_addr_to_sockaddr(&addr, 0,
-                                     (struct sockaddr *)&ss, sizeof(ss));
+      socklen = tor_addr_to_sockaddr(&addr, 0, &ss, sizeof(ss));
       if (socklen <= 0) {
         log_warn(LD_BUG, "Couldn't convert outbound bind address to sockaddr."
                  " Ignoring.");
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
index fb05e48..2060a06 100644
--- a/src/or/eventdns.c
+++ b/src/or/eventdns.c
@@ -359,7 +359,6 @@ error_is_eagain(int err)
 {
 	return err == EAGAIN || err == WSAEWOULDBLOCK;
 }
-#define inet_aton(c, addr) tor_inet_aton((c), (addr))
 #define CLOSE_SOCKET(x) closesocket(x)
 #else
 #define last_error(sock) (errno)
@@ -2288,7 +2287,7 @@ _evdns_nameserver_add_impl(const struct sockaddr *address,
 
 	evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
 
-	ns->socket = tor_open_socket(PF_INET, SOCK_DGRAM, 0);
+	ns->socket = tor_open_socket(address->sa_family == AF_INET ? PF_INET : PF_INET6, SOCK_DGRAM, 0);
 	if (ns->socket < 0) { err = 1; goto out1; }
 #ifdef WIN32
 	{
@@ -2299,6 +2298,8 @@ _evdns_nameserver_add_impl(const struct sockaddr *address,
 	fcntl(ns->socket, F_SETFL, O_NONBLOCK);
 #endif
 
+	/* XXX Check that global_bind_address matches socket family before comparing */
+
 	if (global_bind_addr_is_set &&
 	    !sockaddr_is_loopback((struct sockaddr*)&global_bind_address)) {
 		if (bind(ns->socket, (struct sockaddr *)&global_bind_address,
@@ -2352,7 +2353,7 @@ out1:
 	return err;
 }
 
-/* exported function */
+/* exported function */ /* XXX-IPv6: Unused in Tor */
 int
 evdns_nameserver_add(uint32_t address) {
 	struct sockaddr_in sin;
@@ -2372,7 +2373,9 @@ evdns_nameserver_ip_add(const char *ip_as_string) {
 	int port;
 	char buf[128];
 	const char *cp, *addr_part, *port_part;
-	int is_ipv6;
+        tor_addr_t addr;
+        struct sockaddr_storage sa;
+        socklen_t sa_len;
 	/* recognized formats are:
 	 * [ipv6]:port
 	 * ipv6
@@ -2402,13 +2405,10 @@ evdns_nameserver_ip_add(const char *ip_as_string) {
 			port_part = cp+2;
 		else
 			port_part = NULL;
-		is_ipv6 = 1;
 	} else if (cp && strchr(cp+1, ':')) {
-		is_ipv6 = 1;
 		addr_part = ip_as_string;
 		port_part = NULL;
 	} else if (cp) {
-		is_ipv6 = 0;
 		if (cp - ip_as_string > (int)sizeof(buf)-1) {
 			log(EVDNS_LOG_DEBUG, "Nameserver does not fit in buffer.");
 			return 4;
@@ -2420,7 +2420,6 @@ evdns_nameserver_ip_add(const char *ip_as_string) {
 	} else {
 		addr_part = ip_as_string;
 		port_part = NULL;
-		is_ipv6 = 0;
 	}
 
 	if (port_part == NULL) {
@@ -2434,37 +2433,14 @@ evdns_nameserver_ip_add(const char *ip_as_string) {
 		}
 	}
 
-	/* Tor-only.  needs a more general fix. */
+	/* Tor-only.  needs a more general fix (XXX-IPv6: Like rewriting the whole evdns part? :) */
 	assert(addr_part);
-	if (is_ipv6) {
-		struct sockaddr_in6 sin6;
-		memset(&sin6, 0, sizeof(sin6));
-#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
-		sin6.sin6_len = sizeof(sin6);
-#endif
-		sin6.sin6_family = AF_INET6;
-		sin6.sin6_port = htons(port);
-		if (1 != tor_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr)) {
-			log(EVDNS_LOG_DEBUG, "inet_pton(%s) failed", addr_part);
-			return 4;
-		}
-		return _evdns_nameserver_add_impl((struct sockaddr*)&sin6,
-										  sizeof(sin6));
-	} else {
-		struct sockaddr_in sin;
-		memset(&sin, 0, sizeof(sin));
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
-		sin.sin_len = sizeof(sin);
-#endif
-		sin.sin_family = AF_INET;
-		sin.sin_port = htons(port);
-		if (!inet_aton(addr_part, &sin.sin_addr)) {
-			log(EVDNS_LOG_DEBUG, "inet_pton(%s) failed", addr_part);
-			return 4;
-		}
-		return _evdns_nameserver_add_impl((struct sockaddr*)&sin,
-										  sizeof(sin));
+        if (1 != tor_inet_pton(AF_UNSPEC, addr_part, &addr)) {
+		log(EVDNS_LOG_DEBUG, "tor_inet_pton(%s) failed", addr_part);
+		return 4;
 	}
+        sa_len = tor_addr_to_sockaddr(&addr, 0, &sa, sizeof(sa));
+	return _evdns_nameserver_add_impl((struct sockaddr*)&sa, sa_len);
 }
 
 int
@@ -3470,13 +3446,14 @@ main(int c, char **v) {
 	}
 	for (; idx < c; ++idx) {
 		if (reverse) {
-			struct in_addr addr;
-			if (!inet_aton(v[idx], &addr)) {
+                        tor_addr_t addr;
+			if (!inet_pton(AF_UNSPEC, v[idx], &addr)) {
 				fprintf(stderr, "Skipping non-IP %s\n", v[idx]);
 				continue;
 			}
 			fprintf(stderr, "resolving %s...\n",v[idx]);
-			evdns_resolve_reverse(&addr, 0, main_callback, v[idx]);
+			if (tor_addr_family(&addr) == AF_INET) evdns_resolve_reverse(&addr.in_addr, 0, main_callback, v[idx]);
+			else evdns_resolve_reverse6(&addr.in6_addr, 0, main_callback, v[idx]);
 		} else {
 			fprintf(stderr, "resolving (fwd) %s...\n",v[idx]);
 			evdns_resolve_ipv4(v[idx], 0, main_callback, v[idx]);
diff --git a/src/or/geoip.c b/src/or/geoip.c
index 71ed3be..834ea72 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -23,8 +23,8 @@ static void init_geoip_countries(void);
 
 /** An entry from the GeoIP file: maps an IP range to a country. */
 typedef struct geoip_entry_t {
-  uint32_t ip_low; /**< The lowest IP in the range, in host order */
-  uint32_t ip_high; /**< The highest IP in the range, in host order */
+  tor_addr_t ip_low; /**< The lowest IP in the range, in host order */
+  tor_addr_t ip_high; /**< The highest IP in the range, in host order */
   intptr_t country; /**< An index into geoip_countries */
 } geoip_entry_t;
 
@@ -68,13 +68,14 @@ geoip_get_country(const char *country)
  * <b>high</b>, inclusive, to the 2-letter country code <b>country</b>.
  */
 static void
-geoip_add_entry(uint32_t low, uint32_t high, const char *country)
+geoip_add_entry(tor_addr_t *low, tor_addr_t *high, const char *country)
 {
   intptr_t idx;
   geoip_entry_t *ent;
   void *_idxplus1;
 
-  if (high < low)
+  tor_assert(tor_addr_cmp(low, high) <= 1);
+  if (tor_addr_cmp(low, high) > 1)
     return;
 
   _idxplus1 = strmap_get_lc(country_idxplus1_by_lc_code, country);
@@ -94,18 +95,21 @@ geoip_add_entry(uint32_t low, uint32_t high, const char *country)
     tor_assert(!strcasecmp(c->countrycode, country));
   }
   ent = tor_malloc_zero(sizeof(geoip_entry_t));
-  ent->ip_low = low;
-  ent->ip_high = high;
+  memcpy(&ent->ip_low, &low,  sizeof(*low));
+  memcpy(&ent->ip_high,&high, sizeof(*high));
   ent->country = idx;
   smartlist_add(geoip_entries, ent);
 }
 
+/* XXX-IPv6: Only loads IPv4 file, we don't have IPv6 entries yet anyway */
+/* XXX-IPv6: These files should be prefix based (eg 192.0.2.0/24 and 2001:db8::/32) */
 /** Add an entry to the GeoIP table, parsing it from <b>line</b>.  The
  * format is as for geoip_load_file(). */
 /*private*/ int
 geoip_parse_entry(const char *line)
 {
-  unsigned int low, high;
+  tor_addr_t lo, hi;
+  uint32_t l,h;
   char b[3];
   if (!geoip_countries)
     init_geoip_countries();
@@ -116,11 +120,15 @@ geoip_parse_entry(const char *line)
     ++line;
   if (*line == '#')
     return 0;
-  if (sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) {
-    geoip_add_entry(low, high, b);
+  if (sscanf(line,"%u,%u,%2s", &l, &h, b) == 3) {
+    tor_addr_from_ipv4h(&lo, l);
+    tor_addr_from_ipv4h(&hi, h);
+    geoip_add_entry(&lo, &hi, b);
     return 0;
-  } else if (sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) {
-    geoip_add_entry(low, high, b);
+  } else if (sscanf(line,"\"%u\",\"%u\",\"%2s\",", &l, &h, b) == 3) {
+    tor_addr_from_ipv4h(&lo, l);
+    tor_addr_from_ipv4h(&hi, h);
+    geoip_add_entry(&lo, &hi, b);
     return 0;
   } else {
     log_warn(LD_GENERAL, "Unable to parse line from GEOIP file: %s",
@@ -135,28 +143,19 @@ static int
 _geoip_compare_entries(const void **_a, const void **_b)
 {
   const geoip_entry_t *a = *_a, *b = *_b;
-  if (a->ip_low < b->ip_low)
-    return -1;
-  else if (a->ip_low > b->ip_low)
-    return 1;
-  else
-    return 0;
+  return tor_addr_cmp(&a->ip_low, &b->ip_low);
 }
 
-/** bsearch helper: return -1, 1, or 0 based on comparison of an IP (a pointer
- * to a uint32_t in host order) to a geoip_entry_t */
+/** bsearch helper: return -1, 1, or 0 based on comparison of an
+ * IP (a pointer * to a tor_addr_t) to a geoip_entry_t */
 static int
 _geoip_compare_key_to_entry(const void *_key, const void **_member)
 {
-  /* No alignment issue here, since _key really is a pointer to uint32_t */
-  const uint32_t addr = *(uint32_t *)_key;
+  /* No alignment issue here, since _key really is a pointer to tor_addr_t */
+  const tor_addr_t *addr = (tor_addr_t *)_key;
   const geoip_entry_t *entry = *_member;
-  if (addr < entry->ip_low)
-    return -1;
-  else if (addr > entry->ip_high)
-    return 1;
-  else
-    return 0;
+
+  return tor_addr_cmp(addr, &entry->ip_low);
 }
 
 /** Return 1 if we should collect geoip stats on bridge users, and
@@ -252,12 +251,16 @@ geoip_load_file(const char *filename, or_options_t *options)
  * geoip_get_country_name().
  */
 int
-geoip_get_country_by_ip(uint32_t ipaddr)
+geoip_get_country_by_ip(const tor_addr_t *ipaddr)
 {
   geoip_entry_t *ent;
   if (!geoip_entries)
     return -1;
-  ent = smartlist_bsearch(geoip_entries, &ipaddr, _geoip_compare_key_to_entry);
+  /* XXX-IPv6: dirty, should maybe just make tor_addr_t just hold an address
+   * as that is the information we need in there, not in_addr
+   * then it satisfies the minimum memory usage which geoip needs
+   */
+  ent = smartlist_bsearch(geoip_entries, tor_addr_raw(ipaddr), _geoip_compare_key_to_entry);
   return ent ? (int)ent->country : 0;
 }
 
@@ -303,7 +306,7 @@ geoip_db_digest(void)
  * countries have them blocked. */
 typedef struct clientmap_entry_t {
   HT_ENTRY(clientmap_entry_t) node;
-  uint32_t ipaddr;
+  tor_addr_t ipaddr;
   /** Time when we last saw this IP address, in MINUTES since the epoch.
    *
    * (This will run out of space around 4011 CE.  If Tor is still in use around
@@ -325,13 +328,14 @@ static HT_HEAD(clientmap, clientmap_entry_t) client_history =
 static INLINE unsigned
 clientmap_entry_hash(const clientmap_entry_t *a)
 {
-  return ht_improve_hash((unsigned) a->ipaddr);
+  /* XXX-IPv6: need to see how to properly handle this */
+  return ht_improve_hash((unsigned) tor_addr_to_ipv4h(&a->ipaddr));
 }
 /** Hashtable helper: compare two clientmap_entry_t values for equality. */
 static INLINE int
 clientmap_entries_eq(const clientmap_entry_t *a, const clientmap_entry_t *b)
 {
-  return a->ipaddr == b->ipaddr && a->action == b->action;
+  return tor_addr_eq(&a->ipaddr,&b->ipaddr) && a->action == b->action;
 }
 
 HT_PROTOTYPE(clientmap, clientmap_entry_t, node, clientmap_entry_hash,
@@ -422,7 +426,7 @@ geoip_get_mean_shares(time_t now, double *v2_share_out,
  * configured accordingly. */
 void
 geoip_note_client_seen(geoip_client_action_t action,
-                       uint32_t addr, time_t now)
+                       tor_addr_t *addr, time_t now)
 {
   or_options_t *options = get_options();
   clientmap_entry_t lookup, *ent;
@@ -437,12 +441,12 @@ geoip_note_client_seen(geoip_client_action_t action,
       return;
   }
 
-  lookup.ipaddr = addr;
+  tor_addr_copy(&lookup.ipaddr, addr);
   lookup.action = (int)action;
   ent = HT_FIND(clientmap, &client_history, &lookup);
   if (! ent) {
     ent = tor_malloc_zero(sizeof(clientmap_entry_t));
-    ent->ipaddr = addr;
+    tor_addr_copy(&ent->ipaddr, addr);
     ent->action = (int)action;
     HT_INSERT(clientmap, &client_history, ent);
   }
@@ -823,7 +827,7 @@ geoip_get_client_history(geoip_client_action_t action)
     int country;
     if ((*ent)->action != (int)action)
       continue;
-    country = geoip_get_country_by_ip((*ent)->ipaddr);
+    country = geoip_get_country_by_ip(&(*ent)->ipaddr);
     if (country < 0)
       country = 0; /** unresolved requests are stored at index 0. */
     tor_assert(0 <= country && country < n_countries);
@@ -1364,12 +1368,10 @@ getinfo_helper_geoip(control_connection_t *control_conn,
   }
   if (!strcmpstart(question, "ip-to-country/")) {
     int c;
-    uint32_t ip;
-    struct in_addr in;
+    tor_addr_t a;
     question += strlen("ip-to-country/");
-    if (tor_inet_aton(question, &in) != 0) {
-      ip = ntohl(in.s_addr);
-      c = geoip_get_country_by_ip(ip);
+    if (tor_inet_pton(AF_UNSPEC, question, &a) != 0) {
+      c = geoip_get_country_by_ip(&a);
       *answer = tor_strdup(geoip_get_country_name(c));
     }
   }
diff --git a/src/or/geoip.h b/src/or/geoip.h
index 02228ea..50351a8 100644
--- a/src/or/geoip.h
+++ b/src/or/geoip.h
@@ -17,7 +17,7 @@ int geoip_parse_entry(const char *line);
 #endif
 int should_record_bridge_info(or_options_t *options);
 int geoip_load_file(const char *filename, or_options_t *options);
-int geoip_get_country_by_ip(uint32_t ipaddr);
+int geoip_get_country_by_ip(const tor_addr_t *ipaddr);
 int geoip_get_n_countries(void);
 const char *geoip_get_country_name(country_t num);
 int geoip_is_loaded(void);
@@ -25,7 +25,7 @@ const char *geoip_db_digest(void);
 country_t geoip_get_country(const char *countrycode);
 
 void geoip_note_client_seen(geoip_client_action_t action,
-                            uint32_t addr, time_t now);
+                            tor_addr_t *addr, time_t now);
 void geoip_remove_old_clients(time_t cutoff);
 
 void geoip_note_ns_response(geoip_client_action_t action,
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 837c8c2..6a215bd 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1131,15 +1131,13 @@ update_v2_networkstatus_cache_downloads(time_t now)
     SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds)
       {
          char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */
-         tor_addr_t addr;
          if (!(ds->type & V2_DIRINFO))
            continue;
          if (router_digest_is_me(ds->digest))
            continue;
-         tor_addr_from_ipv4h(&addr, ds->addr);
          /* Is this quite sensible with IPv6 or multiple addresses? */
          if (connection_get_by_type_addr_port_purpose(
-                CONN_TYPE_DIR, &addr, ds->dir_port,
+                CONN_TYPE_DIR, &ds->addr, ds->dir_port,
                 DIR_PURPOSE_FETCH_V2_NETWORKSTATUS)) {
            /* XXX the above dir_port won't be accurate if we're
             * doing a tunneled conn. In that case it should be or_port.
@@ -1471,7 +1469,7 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
 
   return strcmp(a->nickname, b->nickname) ||
          fast_memneq(a->descriptor_digest, b->descriptor_digest, DIGEST_LEN) ||
-         a->addr != b->addr ||
+         tor_addr_eq(&a->addr, &b->addr) ||
          a->or_port != b->or_port ||
          a->dir_port != b->dir_port ||
          a->is_authority != b->is_authority ||
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 0856b31..b9c8ee3 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -621,31 +621,17 @@ node_exit_policy_rejects_all(const node_t *node)
     return 1;
 }
 
-/** Copy the address for <b>node</b> into *<b>addr_out</b>. */
-int
-node_get_addr(const node_t *node, tor_addr_t *addr_out)
-{
-  if (node->ri) {
-    tor_addr_from_ipv4h(addr_out, node->ri->addr);
-    return 0;
-  } else if (node->rs) {
-    tor_addr_from_ipv4h(addr_out, node->rs->addr);
-    return 0;
-  }
-  return -1;
-}
-
-/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
+/** Return the tor_addr_t for <b>node</b>, or 0 if it doesn't
  * seem to have one.  */
-uint32_t
-node_get_addr_ipv4h(const node_t *node)
+const tor_addr_t *
+node_get_addr(const node_t *node)
 {
   if (node->ri) {
-    return node->ri->addr;
+    return &node->ri->addr;
   } else if (node->rs) {
-    return node->rs->addr;
+    return &node->rs->addr;
   }
-  return 0;
+  return NULL;
 }
 
 /** Copy a string representation of the IP address for <b>node</b> into the
@@ -657,9 +643,7 @@ node_get_address_string(const node_t *node, char *buf, size_t len)
   if (node->ri) {
     strlcpy(buf, node->ri->address, len);
   } else if (node->rs) {
-    tor_addr_t addr;
-    tor_addr_from_ipv4h(&addr, node->rs->addr);
-    tor_addr_to_str(buf, &addr, len, 0);
+    tor_addr_to_str(&node->rs->addr, buf, len, 0);
   } else {
     buf[0] = '\0';
   }
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index 08f11da..2dc9920 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -37,8 +37,7 @@ int node_get_purpose(const node_t *node);
   (node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
 int node_is_me(const node_t *node);
 int node_exit_policy_rejects_all(const node_t *node);
-int node_get_addr(const node_t *node, tor_addr_t *addr_out);
-uint32_t node_get_addr_ipv4h(const node_t *node);
+const tor_addr_t *node_get_addr(const node_t *node);
 int node_allows_single_hop_exits(const node_t *node);
 uint16_t node_get_orport(const node_t *node);
 const char *node_get_nickname(const node_t *node);
diff --git a/src/or/or.h b/src/or/or.h
index 74b0244..f92acde 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1505,7 +1505,7 @@ typedef struct {
   char *address; /**< Location of OR: either a hostname or an IP address. */
   char *nickname; /**< Human-readable OR name. */
 
-  uint32_t addr; /**< IPv4 address of OR, in host order. */
+  tor_addr_t addr; /**< IPv4 address of OR. */
   uint16_t or_port; /**< Port for TLS connections. */
   uint16_t dir_port; /**< Port for HTTP directory connections. */
 
@@ -1599,7 +1599,7 @@ typedef struct routerstatus_t {
   /** Digest of the router's most recent descriptor or microdescriptor.
    * If it's a descriptor, we only use the first DIGEST_LEN bytes. */
   char descriptor_digest[DIGEST256_LEN];
-  uint32_t addr; /**< IPv4 address for this router. */
+  tor_addr_t addr; /**< IPv4 address for this router. */
   uint16_t or_port; /**< OR port for this router. */
   uint16_t dir_port; /**< Directory port for this router. */
   unsigned int is_authority:1; /**< True iff this router is an authority. */
@@ -1820,7 +1820,7 @@ typedef struct networkstatus_v2_t {
   time_t published_on; /**< Declared publication date. */
 
   char *source_address; /**< Canonical directory server hostname. */
-  uint32_t source_addr; /**< Canonical directory server IP. */
+  tor_addr_t source_addr; /**< Canonical directory server IP. */
   uint16_t source_dirport; /**< Canonical directory server dirport. */
 
   unsigned int binds_names:1; /**< True iff this directory server binds
@@ -1895,7 +1895,7 @@ typedef struct networkstatus_voter_info_t {
    * consensuses, we treat legacy keys as additional signers. */
   char legacy_id_digest[DIGEST_LEN];
   char *address; /**< Address of this voter, in string format. */
-  uint32_t addr; /**< Address of this voter, in IPv4, in host order. */
+  tor_addr_t addr; /**< Address of this voter, in IPv4, in host order. */
   uint16_t dir_port; /**< Directory port of this voter */
   uint16_t or_port; /**< OR port of this voter */
   char *contact; /**< Contact information for this voter. */
@@ -2082,7 +2082,7 @@ typedef struct authority_cert_t {
   /** The listed expiration time of this certificate. */
   time_t expires;
   /** This authority's IPv4 address, in host order. */
-  uint32_t addr;
+  tor_addr_t addr;
   /** This authority's directory port. */
   uint16_t dir_port;
   /** True iff this certificate was cross-certified by signing the identity
@@ -3660,7 +3660,7 @@ typedef struct trusted_dir_server_t {
   char *description;
   char *nickname;
   char *address; /**< Hostname. */
-  uint32_t addr; /**< IPv4 address. */
+  tor_addr_t addr; /**< IPv4 address. */
   uint16_t dir_port; /**< Directory port. */
   uint16_t or_port; /**< OR port: Used for tunneling connections. */
   char digest[DIGEST_LEN]; /**< Digest of identity key. */
diff --git a/src/or/policies.c b/src/or/policies.c
index 6738b48..b22164d 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -237,18 +237,6 @@ addr_policy_permits_tor_addr(const tor_addr_t *addr, uint16_t port,
   }
 }
 
-/** Return true iff <b> policy</b> (possibly NULL) will allow a connection to
- * <b>addr</b>:<b>port</b>.  <b>addr</b> is an IPv4 address given in host
- * order. */
-/* XXXX deprecate when possible. */
-static int
-addr_policy_permits_address(uint32_t addr, uint16_t port,
-                            smartlist_t *policy)
-{
-  tor_addr_t a;
-  tor_addr_from_ipv4h(&a, addr);
-  return addr_policy_permits_tor_addr(&a, port, policy);
-}
 
 /** Return true iff we think our firewall will let us make an OR connection to
  * addr:port. */
@@ -265,9 +253,7 @@ int
 fascist_firewall_allows_or(const routerinfo_t *ri)
 {
   /* XXXX proposal 118 */
-  tor_addr_t addr;
-  tor_addr_from_ipv4h(&addr, ri->addr);
-  return fascist_firewall_allows_address_or(&addr, ri->or_port);
+  return fascist_firewall_allows_address_or(&ri->addr, ri->or_port);
 }
 
 /** Return true iff we think our firewall will let us make an OR connection to
@@ -278,9 +264,7 @@ fascist_firewall_allows_node(const node_t *node)
   if (node->ri) {
     return fascist_firewall_allows_or(node->ri);
   } else if (node->rs) {
-    tor_addr_t addr;
-    tor_addr_from_ipv4h(&addr, node->rs->addr);
-    return fascist_firewall_allows_address_or(&addr, node->rs->or_port);
+    return fascist_firewall_allows_address_or(&node->rs->addr, node->rs->or_port);
   } else {
     return 1;
   }
@@ -317,36 +301,36 @@ socks_policy_permits_address(const tor_addr_t *addr)
  * directory, based on <b>authdir_reject_policy</b>. Else return 0.
  */
 int
-authdir_policy_permits_address(uint32_t addr, uint16_t port)
+authdir_policy_permits_address(const tor_addr_t *addr, uint16_t port)
 {
-  return addr_policy_permits_address(addr, port, authdir_reject_policy);
+  return addr_policy_permits_tor_addr(addr, port, authdir_reject_policy);
 }
 
 /** Return 1 if <b>addr</b>:<b>port</b> is considered valid in our
  * directory, based on <b>authdir_invalid_policy</b>. Else return 0.
  */
 int
-authdir_policy_valid_address(uint32_t addr, uint16_t port)
+authdir_policy_valid_address(const tor_addr_t *addr, uint16_t port)
 {
-  return addr_policy_permits_address(addr, port, authdir_invalid_policy);
+  return addr_policy_permits_tor_addr(addr, port, authdir_invalid_policy);
 }
 
 /** Return 1 if <b>addr</b>:<b>port</b> should be marked as a bad dir,
  * based on <b>authdir_baddir_policy</b>. Else return 0.
  */
 int
-authdir_policy_baddir_address(uint32_t addr, uint16_t port)
+authdir_policy_baddir_address(const tor_addr_t *addr, uint16_t port)
 {
-  return ! addr_policy_permits_address(addr, port, authdir_baddir_policy);
+  return ! addr_policy_permits_tor_addr(addr, port, authdir_baddir_policy);
 }
 
 /** Return 1 if <b>addr</b>:<b>port</b> should be marked as a bad exit,
  * based on <b>authdir_badexit_policy</b>. Else return 0.
  */
 int
-authdir_policy_badexit_address(uint32_t addr, uint16_t port)
+authdir_policy_badexit_address(const tor_addr_t *addr, uint16_t port)
 {
-  return ! addr_policy_permits_address(addr, port, authdir_badexit_policy);
+  return ! addr_policy_permits_tor_addr(addr, port, authdir_badexit_policy);
 }
 
 #define REJECT(arg) \
@@ -474,7 +458,7 @@ cmp_single_addr_policy(addr_policy_t *a, addr_policy_t *b)
     return r;
   if ((r=((int)a->is_private - (int)b->is_private)))
     return r;
-  if ((r=tor_addr_compare(&a->addr, &b->addr, CMP_EXACT)))
+  if ((r=tor_addr_cmp(&a->addr, &b->addr)))
     return r;
   if ((r=((int)a->maskbits - (int)b->maskbits)))
     return r;
@@ -570,18 +554,6 @@ addr_policy_get_canonical_entry(addr_policy_t *e)
   return found->policy;
 }
 
-/** As compare_tor_addr_to_addr_policy, but instead of a tor_addr_t, takes
- * in host order. */
-addr_policy_result_t
-compare_addr_to_addr_policy(uint32_t addr, uint16_t port,
-                            const smartlist_t *policy)
-{
-  /*XXXX deprecate this function when possible. */
-  tor_addr_t a;
-  tor_addr_from_ipv4h(&a, addr);
-  return compare_tor_addr_to_addr_policy(&a, port, policy);
-}
-
 /** Helper for compare_tor_addr_to_addr_policy.  Implements the case where
  * addr and port are both known. */
 static addr_policy_result_t
@@ -701,7 +673,7 @@ compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port,
   if (!policy) {
     /* no policy? accept all. */
     return ADDR_POLICY_ACCEPTED;
-  } else if (tor_addr_is_null(addr)) {
+  } else if (!addr || tor_addr_is_null(addr)) {
     tor_assert(port != 0);
     return compare_unknown_tor_addr_to_addr_policy(port, policy);
   } else if (port == 0) {
@@ -902,7 +874,7 @@ exit_policy_is_general_exit_helper(smartlist_t *policy, int port)
   memset(subnet_status, 0, sizeof(subnet_status));
   SMARTLIST_FOREACH(policy, addr_policy_t *, p, {
     if (tor_addr_family(&p->addr) != AF_INET)
-      continue; /* IPv4 only for now */
+      continue; /* IPv4 only for now (XXX-IPv6 TODO) */
     if (p->prt_min > port || p->prt_max < port)
       continue; /* Doesn't cover our port. */
     mask = 0;
@@ -984,7 +956,7 @@ policy_write_item(char *buf, size_t buflen, addr_policy_t *policy,
   const int is_accept = policy->policy_type == ADDR_POLICY_ACCEPT;
   const int is_ip6 = tor_addr_family(&policy->addr) == AF_INET6;
 
-  tor_addr_to_str(addrbuf, &policy->addr, sizeof(addrbuf), 1);
+  tor_addr_to_str(&policy->addr, addrbuf, sizeof(addrbuf), 1);
 
   /* write accept/reject 1.2.3.4 */
   if (policy->is_private)
@@ -1179,7 +1151,7 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p)
                                   &maskbits, NULL, NULL)<0) {
          tor_assert(0);
        }
-       if (tor_addr_compare(&p->addr, &addr, CMP_EXACT) == 0 &&
+       if (tor_addr_eq(&p->addr, &addr) &&
            p->maskbits == maskbits) {
          is_private = 1;
          break;
@@ -1471,17 +1443,6 @@ short_policy_is_reject_star(const short_policy_t *policy)
  * <b>node</b>.  See compare_tor_addr_to_addr_policy for details on addr/port
  * interpretation. */
 addr_policy_result_t
-compare_addr_to_node_policy(uint32_t addr, uint16_t port, const node_t *node)
-{
-  tor_addr_t a;
-  tor_addr_from_ipv4h(&a, addr);
-  return compare_tor_addr_to_node_policy(&a, port, node);
-}
-
-/** Decides whether addr:port is probably or definitely accepted or rejcted by
- * <b>node</b>.  See compare_tor_addr_to_addr_policy for details on addr/port
- * interpretation. */
-addr_policy_result_t
 compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port,
                                 const node_t *node)
 {
diff --git a/src/or/policies.h b/src/or/policies.h
index ee1162c..d91e1ec 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -24,10 +24,10 @@ int fascist_firewall_allows_node(const node_t *node);
 int fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port);
 int dir_policy_permits_address(const tor_addr_t *addr);
 int socks_policy_permits_address(const tor_addr_t *addr);
-int authdir_policy_permits_address(uint32_t addr, uint16_t port);
-int authdir_policy_valid_address(uint32_t addr, uint16_t port);
-int authdir_policy_baddir_address(uint32_t addr, uint16_t port);
-int authdir_policy_badexit_address(uint32_t addr, uint16_t port);
+int authdir_policy_permits_address(const tor_addr_t *addr, uint16_t port);
+int authdir_policy_valid_address(const tor_addr_t *addr, uint16_t port);
+int authdir_policy_baddir_address(const tor_addr_t *addr, uint16_t port);
+int authdir_policy_badexit_address(const tor_addr_t *addr, uint16_t port);
 
 int validate_addr_policies(or_options_t *options, char **msg);
 void policy_expand_private(smartlist_t **policy);
@@ -37,11 +37,7 @@ addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent);
 int cmp_addr_policies(smartlist_t *a, smartlist_t *b);
 addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr,
                               uint16_t port, const smartlist_t *policy);
-addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr,
-                              uint16_t port, const smartlist_t *policy);
 
-addr_policy_result_t compare_addr_to_node_policy(uint32_t addr,
-                              uint16_t port, const node_t *node);
 addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
                               uint16_t port, const node_t *node);
 
diff --git a/src/or/relay.c b/src/or/relay.c
index cf53116..7c62080 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -704,7 +704,7 @@ connection_ap_process_end_not_open(
     relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
     edge_connection_t *conn, crypt_path_t *layer_hint)
 {
-  struct in_addr in;
+  tor_addr_t addr;
   node_t *exitrouter;
   int reason = *(cell->payload+RELAY_HEADER_SIZE);
   int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
@@ -722,33 +722,34 @@ connection_ap_process_end_not_open(
     switch (reason) {
       case END_STREAM_REASON_EXITPOLICY:
         if (rh->length >= 5) {
-          uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1));
+          uint32_t a = get_uint32(cell->payload+RELAY_HEADER_SIZE+5);
           int ttl;
-          if (!addr) {
+          if (!a) {
             log_info(LD_APP,"Address '%s' resolved to 0.0.0.0. Closing,",
                      safe_str(conn->socks_request->address));
             connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
             return 0;
           }
+          tor_addr_from_ipv4n(&addr, ntohl(a));
           if (rh->length >= 9)
             ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5));
           else
             ttl = -1;
 
           if (get_options()->ClientDNSRejectInternalAddresses &&
-              is_internal_IP(addr, 0)) {
+              tor_addr_is_internal(&addr, 0)) {
             log_info(LD_APP,"Address '%s' resolved to internal. Closing,",
                      safe_str(conn->socks_request->address));
             connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
             return 0;
           }
-          client_dns_set_addressmap(conn->socks_request->address, addr,
+          client_dns_set_addressmap(conn->socks_request->address, &addr,
                                     conn->chosen_exit_name, ttl);
         }
         /* check if he *ought* to have allowed it */
         if (exitrouter &&
             (rh->length < 5 ||
-             (tor_inet_aton(conn->socks_request->address, &in) &&
+             (tor_inet_pton(AF_UNSPEC, conn->socks_request->address, &addr) &&
               !conn->chosen_exit_name))) {
           log_info(LD_APP,
                  "Exitrouter '%s' seems to be more restrictive than its exit "
@@ -848,13 +849,10 @@ connection_ap_process_end_not_open(
  * dotted-quad representation of <b>new_addr</b> (given in host order),
  * and send an appropriate REMAP event. */
 static void
-remap_event_helper(edge_connection_t *conn, uint32_t new_addr)
+remap_event_helper(edge_connection_t *conn, tor_addr_t *new_addr)
 {
-  struct in_addr in;
-
-  in.s_addr = htonl(new_addr);
-  tor_inet_ntoa(&in, conn->socks_request->address,
-                sizeof(conn->socks_request->address));
+  tor_addr_to_str(new_addr, conn->socks_request->address,
+                sizeof(conn->socks_request->address),1);
   control_event_stream_status(conn, STREAM_EVENT_REMAP,
                               REMAP_STREAM_SOURCE_EXIT);
 }
@@ -871,6 +869,7 @@ connection_edge_process_relay_cell_not_open(
     relay_header_t *rh, cell_t *cell, circuit_t *circ,
     edge_connection_t *conn, crypt_path_t *layer_hint)
 {
+  tor_addr_t addr;
   if (rh->command == RELAY_COMMAND_END) {
     if (CIRCUIT_IS_ORIGIN(circ) && conn->_base.type == CONN_TYPE_AP) {
       return connection_ap_process_end_not_open(rh, cell,
@@ -898,12 +897,13 @@ connection_edge_process_relay_cell_not_open(
     log_info(LD_APP,"'connected' received after %d seconds.",
              (int)(time(NULL) - conn->_base.timestamp_lastread));
     if (rh->length >= 4) {
-      uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
+      uint32_t a = get_uint32(cell->payload+RELAY_HEADER_SIZE);
       int ttl;
-      if (!addr || (get_options()->ClientDNSRejectInternalAddresses &&
-                    is_internal_IP(addr, 0))) {
+      tor_addr_from_ipv4n(&addr, a);
+      if (!a || (get_options()->ClientDNSRejectInternalAddresses &&
+                    tor_addr_is_internal(&addr, 0))) {
         log_info(LD_APP, "...but it claims the IP address was %s. Closing.",
-                 fmt_addr32(addr));
+                 fmt_addr(&addr));
         connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
         connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
         return 0;
@@ -912,10 +912,10 @@ connection_edge_process_relay_cell_not_open(
         ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4));
       else
         ttl = -1;
-      client_dns_set_addressmap(conn->socks_request->address, addr,
+      client_dns_set_addressmap(conn->socks_request->address, &addr,
                                 conn->chosen_exit_name, ttl);
 
-      remap_event_helper(conn, addr);
+      remap_event_helper(conn, &addr);
     }
     circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
     /* don't send a socks reply to transparent conns */
@@ -976,12 +976,16 @@ connection_edge_process_relay_cell_not_open(
                                   2+answer_len));
     else
       ttl = -1;
-    if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
-      uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
+    if (answer_type == RESOLVED_TYPE_IPV4 || answer_type == RESOLVED_TYPE_IPV6) {
+      if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
+        tor_addr_from_ipv4n(&addr, get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
+      } else {
+        tor_addr_from_ipv6_bytes(&addr, (char *)cell->payload+RELAY_HEADER_SIZE+2);
+      }
       if (get_options()->ClientDNSRejectInternalAddresses &&
-          is_internal_IP(addr, 0)) {
+          tor_addr_is_internal(&addr, 0)) {
         log_info(LD_APP,"Got a resolve with answer %s. Rejecting.",
-                 fmt_addr32(addr));
+                 fmt_addr(&addr));
         connection_ap_handshake_socks_resolved(conn,
                                                RESOLVED_TYPE_ERROR_TRANSIENT,
                                                0, NULL, 0, TIME_MAX);
@@ -996,8 +1000,12 @@ connection_edge_process_relay_cell_not_open(
                    ttl,
                    -1);
     if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
-      uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
-      remap_event_helper(conn, addr);
+      tor_addr_from_ipv4n(&addr, get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
+      remap_event_helper(conn, &addr);
+    }
+    else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) {
+      tor_addr_from_ipv6_bytes(&addr, (char *)cell->payload+RELAY_HEADER_SIZE+2);
+      remap_event_helper(conn, &addr);
     }
     connection_mark_unattached_ap(conn,
                               END_STREAM_REASON_DONE |
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 3d5c80c..425b725 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -1623,7 +1623,7 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
                                               strlen(desc->desc_str), 0);
       base32_encode(desc_id_base32, sizeof(desc_id_base32),
                     desc->desc_id, DIGEST_LEN);
-      hs_dir_ip = tor_dup_ip(hs_dir->addr);
+      hs_dir_ip = tor_dup_ip(&hs_dir->addr);
       log_info(LD_REND, "Sending publish request for v2 descriptor for "
                         "service '%s' with descriptor ID '%s' with validity "
                         "of %d seconds to hidden service directory '%s' on "
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 1ab4171..8cd35e8 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -311,7 +311,7 @@ rep_hist_note_router_reachable(const char *id, const tor_addr_t *at_addr,
   tor_assert((!at_addr && !at_port) || (at_addr && at_port));
 
   addr_changed = at_addr &&
-    tor_addr_compare(at_addr, &hist->last_reached_addr, CMP_EXACT) != 0;
+    !tor_addr_eq(at_addr, &hist->last_reached_addr);
   port_changed = at_port && at_port != hist->last_reached_port;
 
   if (!started_tracking_stability)
diff --git a/src/or/router.c b/src/or/router.c
index e2791c1..0ef2d1c 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -852,7 +852,6 @@ consider_testing_reachability(int test_or, int test_dir)
 {
   const routerinfo_t *me = router_get_my_routerinfo();
   int orport_reachable = check_whether_orport_reachable();
-  tor_addr_t addr;
   or_options_t *options = get_options();
   if (!me)
     return;
@@ -887,13 +886,12 @@ consider_testing_reachability(int test_or, int test_dir)
     extend_info_free(ei);
   }
 
-  tor_addr_from_ipv4h(&addr, me->addr);
   if (test_dir && !check_whether_dirport_reachable() &&
       !connection_get_by_type_addr_port_purpose(
-                CONN_TYPE_DIR, &addr, me->dir_port,
+                CONN_TYPE_DIR, &me->addr, me->dir_port,
                 DIR_PURPOSE_FETCH_SERVERDESC)) {
     /* ask myself, via tor, for my server descriptor. */
-    directory_initiate_command(me->address, &addr,
+    directory_initiate_command(me->address, &me->addr,
                                me->or_port, me->dir_port,
                                0, /* does not matter */
                                0, me->cache_info.identity_digest,
@@ -1378,14 +1376,14 @@ router_get_my_extrainfo(void)
  * declaration verbatim rather than as digests. */
 static smartlist_t *warned_nonexistent_family = NULL;
 
-static int router_guess_address_from_dir_headers(uint32_t *guess);
+static int router_guess_address_from_dir_headers(tor_addr_t *guess);
 
 /** Make a current best guess at our address, either because
  * it's configured in torrc, or because we've learned it from
  * dirserver headers. Place the answer in *<b>addr</b> and return
  * 0 on success, else return -1 if we have no guess. */
 int
-router_pick_published_address(or_options_t *options, uint32_t *addr)
+router_pick_published_address(or_options_t *options, tor_addr_t *addr)
 {
   if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) {
     log_info(LD_CONFIG, "Could not determine our address locally. "
@@ -1396,7 +1394,7 @@ router_pick_published_address(or_options_t *options, uint32_t *addr)
       return -1;
     }
   }
-  log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr));
+  log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr(addr));
   return 0;
 }
 
@@ -1409,7 +1407,7 @@ router_rebuild_descriptor(int force)
 {
   routerinfo_t *ri;
   extrainfo_t *ei;
-  uint32_t addr;
+  tor_addr_t addr;
   char platform[256];
   int hibernating = we_are_hibernating();
   or_options_t *options = get_options();
@@ -1427,9 +1425,9 @@ router_rebuild_descriptor(int force)
 
   ri = tor_malloc_zero(sizeof(routerinfo_t));
   ri->cache_info.routerlist_index = -1;
-  ri->address = tor_dup_ip(addr);
+  ri->address = tor_dup_ip(&addr);
   ri->nickname = tor_strdup(options->Nickname);
-  ri->addr = addr;
+  tor_addr_copy(&ri->addr, &addr);
   ri->or_port = router_get_advertised_or_port(options);
   ri->dir_port = router_get_advertised_dir_port(options);
   ri->cache_info.published_on = time(NULL);
@@ -1638,21 +1636,16 @@ check_descriptor_bandwidth_changed(time_t now)
 /** Note at log level severity that our best guess of address has changed from
  * <b>prev</b> to <b>cur</b>. */
 static void
-log_addr_has_changed(int severity, uint32_t prev, uint32_t cur,
+log_addr_has_changed(int severity, tor_addr_t *prev, tor_addr_t *cur,
                      const char *source)
 {
   char addrbuf_prev[INET_NTOA_BUF_LEN];
   char addrbuf_cur[INET_NTOA_BUF_LEN];
-  struct in_addr in_prev;
-  struct in_addr in_cur;
-
-  in_prev.s_addr = htonl(prev);
-  tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev));
 
-  in_cur.s_addr = htonl(cur);
-  tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur));
+  tor_addr_to_str(prev, addrbuf_prev, sizeof(addrbuf_prev), 1);
+  tor_addr_to_str(cur, addrbuf_cur, sizeof(addrbuf_cur), 1);
 
-  if (prev)
+  if (tor_addr_is_null(prev))
     log_fn(severity, LD_GENERAL,
            "Our IP Address has changed from %s to %s; "
            "rebuilding descriptor (source: %s).",
@@ -1669,28 +1662,28 @@ log_addr_has_changed(int severity, uint32_t prev, uint32_t cur,
 void
 check_descriptor_ipaddress_changed(time_t now)
 {
-  uint32_t prev, cur;
+  tor_addr_t prev, cur;
   or_options_t *options = get_options();
   (void) now;
 
   if (!desc_routerinfo)
     return;
 
-  prev = desc_routerinfo->addr;
+  tor_addr_copy(&prev, &desc_routerinfo->addr);
   if (resolve_my_address(LOG_INFO, options, &cur, NULL) < 0) {
     log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
     return;
   }
 
-  if (prev != cur) {
-    log_addr_has_changed(LOG_NOTICE, prev, cur, "resolve");
+  if (!tor_addr_eq(&prev, &cur)) {
+    log_addr_has_changed(LOG_NOTICE, &prev, &cur, "resolve");
     ip_address_changed(0);
   }
 }
 
 /** The most recently guessed value of our IP address, based on directory
  * headers. */
-static uint32_t last_guessed_ip = 0;
+static tor_addr_t last_guessed_ip;
 
 /** A directory server <b>d_conn</b> told us our IP address is
  * <b>suggestion</b>.
@@ -1700,38 +1693,36 @@ void
 router_new_address_suggestion(const char *suggestion,
                               const dir_connection_t *d_conn)
 {
-  uint32_t addr, cur = 0;
-  struct in_addr in;
+  tor_addr_t addr, cur;
   or_options_t *options = get_options();
 
   /* first, learn what the IP address actually is */
-  if (!tor_inet_aton(suggestion, &in)) {
+  if (!tor_inet_pton(AF_UNSPEC, suggestion, &addr)) {
     log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
               escaped(suggestion));
     return;
   }
-  addr = ntohl(in.s_addr);
 
   log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion);
 
   if (!server_mode(options)) {
-    last_guessed_ip = addr; /* store it in case we need it later */
+    tor_addr_copy(&last_guessed_ip, &addr); /* store it in case we need it later */
     return;
   }
 
   if (resolve_my_address(LOG_INFO, options, &cur, NULL) >= 0) {
     /* We're all set -- we already know our address. Great. */
-    last_guessed_ip = cur; /* store it in case we need it later */
+    tor_addr_copy(&last_guessed_ip, &cur); /* store it in case we need it later */
     return;
   }
-  if (is_internal_IP(addr, 0)) {
+  if (tor_addr_is_internal(&addr, 0)) {
     /* Don't believe anybody who says our IP is, say, 127.0.0.1. */
     return;
   }
-  if (tor_addr_eq_ipv4h(&d_conn->_base.addr, addr)) {
+  if (tor_addr_eq(&d_conn->_base.addr, &addr)) {
     /* Don't believe anybody who says our IP is their IP. */
     log_debug(LD_DIR, "A directory server told us our IP address is %s, "
-              "but he's just reporting his own IP address. Ignoring.",
+              "but it is just reporting their own IP address. Ignoring.",
               suggestion);
     return;
   }
@@ -1739,14 +1730,13 @@ router_new_address_suggestion(const char *suggestion,
   /* Okay.  We can't resolve our own address, and X-Your-Address-Is is giving
    * us an answer different from what we had the last time we managed to
    * resolve it. */
-  if (last_guessed_ip != addr) {
+  if (!tor_addr_eq(&last_guessed_ip, &addr)) {
     control_event_server_status(LOG_NOTICE,
                                 "EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV",
                                 suggestion);
-    log_addr_has_changed(LOG_NOTICE, last_guessed_ip, addr,
-                         d_conn->_base.address);
+    log_addr_has_changed(LOG_NOTICE, &last_guessed_ip, &addr, d_conn->_base.address);
     ip_address_changed(0);
-    last_guessed_ip = addr; /* router_rebuild_descriptor() will fetch it */
+    tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor() will fetch it */
   }
 }
 
@@ -1755,10 +1745,10 @@ router_new_address_suggestion(const char *suggestion,
  * about our address based on directory headers, answer it and return
  * 0; else return -1. */
 static int
-router_guess_address_from_dir_headers(uint32_t *guess)
+router_guess_address_from_dir_headers(tor_addr_t *guess)
 {
-  if (last_guessed_ip) {
-    *guess = last_guessed_ip;
+  if (tor_addr_is_null(&last_guessed_ip)) {
+    tor_addr_copy(guess, &last_guessed_ip);
     return 0;
   }
   return -1;
diff --git a/src/or/router.h b/src/or/router.h
index d126ac9..922407e 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -76,7 +76,7 @@ int router_digest_is_me(const char *digest);
 int router_extrainfo_digest_is_me(const char *digest);
 int router_is_me(const routerinfo_t *router);
 int router_fingerprint_is_me(const char *fp);
-int router_pick_published_address(or_options_t *options, uint32_t *addr);
+int router_pick_published_address(or_options_t *options, tor_addr_t *addr);
 int router_rebuild_descriptor(int force);
 int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
                                  crypto_pk_env_t *ident_key);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 8d25eaa..e5f43bb 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -246,10 +246,10 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store,
     if (ds && cert->cache_info.published_on > ds->addr_current_at) {
       /* Check to see whether we should update our view of the authority's
        * address. */
-      if (cert->addr && cert->dir_port &&
-          (ds->addr != cert->addr ||
+      if (tor_addr_is_null(&cert->addr) && cert->dir_port &&
+          (tor_addr_eq(&ds->addr, &cert->addr) ||
            ds->dir_port != cert->dir_port)) {
-        char *a = tor_dup_ip(cert->addr);
+        char *a = tor_dup_ip(&cert->addr);
         log_notice(LD_DIR, "Updating address for directory authority %s "
                    "from %s:%d to %s:%d based on certificate.",
                    ds->nickname, ds->address, (int)ds->dir_port,
@@ -1105,7 +1105,6 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
   SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
     int is_trusted;
     int is_overloaded;
-    tor_addr_t addr;
     const routerstatus_t *status = node->rs;
     const country_t country = node->country;
     if (!status)
@@ -1140,18 +1139,21 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
     }
 
     /* XXXX IP6 proposal 118 */
-    tor_addr_from_ipv4h(&addr, node->rs->addr);
 
+    /* XXX-IPv6: we might want to check that the address is IPv4 and reject others
+     *           that the internal datastructures support it does not mean that the
+     *           protocol wants to carry it here
+     */
     is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
 
     if (prefer_tunnel &&
         status->version_supports_begindir &&
         (!fascistfirewall ||
-         fascist_firewall_allows_address_or(&addr, status->or_port)))
+         fascist_firewall_allows_address_or(&node->rs->addr, status->or_port)))
       smartlist_add(is_trusted ? trusted_tunnel :
                     is_overloaded ? overloaded_tunnel : tunnel, (void*)node);
     else if (!fascistfirewall ||
-             fascist_firewall_allows_address_dir(&addr, status->dir_port))
+             fascist_firewall_allows_address_dir(&node->rs->addr, status->dir_port))
       smartlist_add(is_trusted ? trusted_direct :
                     is_overloaded ? overloaded_direct : direct, (void*)node);
   } SMARTLIST_FOREACH_END(node);
@@ -1244,14 +1246,13 @@ router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags,
         continue;
       }
 
-      /* XXXX IP6 proposal 118 */
-      tor_addr_from_ipv4h(&addr, d->addr);
+      /* XXXX IP6 proposal 118 (XXX-IPv6: need to check if this should be IPv4-only) */
 
       if (no_serverdesc_fetching) {
         if (connection_get_by_type_addr_port_purpose(
-            CONN_TYPE_DIR, &addr, d->dir_port, DIR_PURPOSE_FETCH_SERVERDESC)
+            CONN_TYPE_DIR, &d->addr, d->dir_port, DIR_PURPOSE_FETCH_SERVERDESC)
          || connection_get_by_type_addr_port_purpose(
-             CONN_TYPE_DIR, &addr, d->dir_port, DIR_PURPOSE_FETCH_EXTRAINFO)) {
+             CONN_TYPE_DIR, &d->addr, d->dir_port, DIR_PURPOSE_FETCH_EXTRAINFO)) {
           //log_debug(LD_DIR, "We have an existing connection to fetch "
           //           "descriptor from %s; delaying",d->description);
           ++n_busy;
@@ -1336,7 +1337,7 @@ mark_all_trusteddirservers_up(void)
 int
 routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2)
 {
-  return r1->addr == r2->addr && r1->or_port == r2->or_port;
+  return tor_addr_eq(&r1->addr, &r2->addr) && r1->or_port == r2->or_port;
 }
 
 /** Reset all internal variables used to count failed downloads of network
@@ -1354,6 +1355,7 @@ addrs_in_same_network_family(const tor_addr_t *a1,
                              const tor_addr_t *a2)
 {
   /* XXXX MOVE ? */
+  /* XXX_IPv6: Only compare a /16, should use different length for IPv6 */
   return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC);
 }
 
@@ -1375,13 +1377,8 @@ nodelist_add_node_family(smartlist_t *sl, const node_t *node)
 
   /* First, add any nodes with similar network addresses. */
   if (options->EnforceDistinctSubnets) {
-    tor_addr_t node_addr;
-    node_get_addr(node, &node_addr);
-
     SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) {
-      tor_addr_t a;
-      node_get_addr(node2, &a);
-      if (addrs_in_same_network_family(&a, &node_addr))
+      if (addrs_in_same_network_family(node_get_addr(node2), node_get_addr(node)))
         smartlist_add(sl, (void*)node2);
     } SMARTLIST_FOREACH_END(node2);
   }
@@ -1460,10 +1457,7 @@ nodes_in_same_family(const node_t *node1, const node_t *node2)
 
   /* Are they in the same family because of their addresses? */
   if (options->EnforceDistinctSubnets) {
-    tor_addr_t a1, a2;
-    node_get_addr(node1, &a1);
-    node_get_addr(node2, &a2);
-    if (addrs_in_same_network_family(&a1, &a2))
+    if (addrs_in_same_network_family(node_get_addr(node1), node_get_addr(node2)))
       return 1;
   }
 
@@ -1562,21 +1556,16 @@ routerlist_find_my_routerinfo(void)
 const node_t *
 router_find_exact_exit_enclave(const char *address, uint16_t port)
 {/*XXXX MOVE*/
-  uint32_t addr;
-  struct in_addr in;
-  tor_addr_t a;
+  tor_addr_t addr;
   or_options_t *options = get_options();
 
-  if (!tor_inet_aton(address, &in))
+  if (!tor_inet_pton(AF_UNSPEC, address, &addr))
     return NULL; /* it's not an IP already */
-  addr = ntohl(in.s_addr);
-
-  tor_addr_from_ipv4h(&a, addr);
 
   SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, {
-    if (node_get_addr_ipv4h(node) == addr &&
+    if (tor_addr_eq(node_get_addr(node), &addr) &&
         node->is_running &&
-        compare_tor_addr_to_node_policy(&a, port, node) ==
+        compare_tor_addr_to_node_policy(&addr, port, node) ==
           ADDR_POLICY_ACCEPTED &&
         !routerset_contains_node(options->_ExcludeExitNodesUnion, node))
       return node;
@@ -2468,12 +2457,12 @@ router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
 /** Return true iff <b>addr</b> is the address of one of our trusted
  * directory authorities. */
 int
-router_addr_is_trusted_dir(uint32_t addr)
+router_addr_is_trusted_dir(tor_addr_t *addr)
 {
   if (!trusted_dir_servers)
     return 0;
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ent,
-    if (ent->addr == addr)
+    if (tor_addr_eq(&ent->addr, addr))
       return 1;
     );
   return 0;
@@ -4017,7 +4006,7 @@ routerlist_retry_directory_downloads(time_t now)
 /** Return 1 if all running sufficiently-stable routers we can use will reject
  * addr:port, return 0 if any might accept it. */
 int
-router_exit_policy_all_nodes_reject(uint32_t addr, uint16_t port,
+router_exit_policy_all_nodes_reject(tor_addr_t *addr, uint16_t port,
                                     int need_uptime)
 { /* XXXX MOVE */
   addr_policy_result_t r;
@@ -4026,7 +4015,7 @@ router_exit_policy_all_nodes_reject(uint32_t addr, uint16_t port,
     if (node->is_running &&
         !node_is_unreliable(node, need_uptime, 0, 0)) {
 
-      r = compare_addr_to_node_policy(addr, port, node);
+      r = compare_tor_addr_to_node_policy(addr, port, node);
 
       if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
         return 0; /* this one could be ok. good enough. */
@@ -4054,21 +4043,21 @@ add_trusted_dir_server(const char *nickname, const char *address,
                        dirinfo_type_t type)
 {
   trusted_dir_server_t *ent;
-  uint32_t a;
+  tor_addr_t addr;
   char *hostname = NULL;
   size_t dlen;
   if (!trusted_dir_servers)
     trusted_dir_servers = smartlist_create();
 
   if (!address) { /* The address is us; we should guess. */
-    if (resolve_my_address(LOG_WARN, get_options(), &a, &hostname) < 0) {
+    if (resolve_my_address(LOG_WARN, get_options(), &addr, &hostname) < 0) {
       log_warn(LD_CONFIG,
                "Couldn't find a suitable address when adding ourself as a "
                "trusted directory server.");
       return NULL;
     }
   } else {
-    if (tor_lookup_hostname(address, &a)) {
+    if (tor_addr_lookup(address, AF_UNSPEC, &addr)) {
       log_warn(LD_CONFIG,
                "Unable to lookup address for directory server at '%s'",
                address);
@@ -4080,7 +4069,7 @@ add_trusted_dir_server(const char *nickname, const char *address,
   ent = tor_malloc_zero(sizeof(trusted_dir_server_t));
   ent->nickname = nickname ? tor_strdup(nickname) : NULL;
   ent->address = hostname;
-  ent->addr = a;
+  tor_addr_copy(&ent->addr, &addr);
   ent->dir_port = dir_port;
   ent->or_port = or_port;
   ent->is_running = 1;
@@ -5572,7 +5561,7 @@ routerset_contains(const routerset_t *set, const tor_addr_t *addr,
     return 3;
   if (set->countries) {
     if (country < 0 && addr)
-      country = geoip_get_country_by_ip(tor_addr_to_ipv4h(addr));
+      country = geoip_get_country_by_ip(addr);
 
     if (country >= 0 && country < set->n_countries &&
         bitarray_is_set(set->countries, country))
@@ -5599,10 +5588,8 @@ int
 routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
                           country_t country)
 {
-  tor_addr_t addr;
-  tor_addr_from_ipv4h(&addr, ri->addr);
   return routerset_contains(set,
-                            &addr,
+                            &ri->addr,
                             ri->or_port,
                             ri->nickname,
                             ri->cache_info.identity_digest,
@@ -5616,10 +5603,8 @@ routerset_contains_routerstatus(const routerset_t *set,
                                 const routerstatus_t *rs,
                                 country_t country)
 {
-  tor_addr_t addr;
-  tor_addr_from_ipv4h(&addr, rs->addr);
   return routerset_contains(set,
-                            &addr,
+                            &rs->addr,
                             rs->or_port,
                             rs->nickname,
                             rs->identity_digest,
@@ -5786,9 +5771,9 @@ void
 node_set_country(node_t *node)
 {
   if (node->rs)
-    node->country = geoip_get_country_by_ip(node->rs->addr);
+    node->country = geoip_get_country_by_ip(&node->rs->addr);
   else if (node->ri)
-    node->country = geoip_get_country_by_ip(node->ri->addr);
+    node->country = geoip_get_country_by_ip(&node->ri->addr);
   else
     node->country = -1;
 }
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index a613c34..4ac9421 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -61,7 +61,7 @@ int router_digest_is_trusted_dir_type(const char *digest,
 #define router_digest_is_trusted_dir(d) \
   router_digest_is_trusted_dir_type((d), NO_DIRINFO)
 
-int router_addr_is_trusted_dir(uint32_t addr);
+int router_addr_is_trusted_dir(tor_addr_t *addr);
 int hexdigest_to_digest(const char *hexdigest, char *digest);
 const routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
 const routerinfo_t *router_get_by_id_digest(const char *digest);
@@ -129,7 +129,7 @@ void router_load_extrainfo_from_string(const char *s, const char *eos,
                                        int descriptor_digests);
 
 void routerlist_retry_directory_downloads(time_t now);
-int router_exit_policy_all_nodes_reject(uint32_t addr, uint16_t port,
+int router_exit_policy_all_nodes_reject(tor_addr_t *addr, uint16_t port,
                                         int need_uptime);
 
 int router_exit_policy_rejects_all(const routerinfo_t *router);
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 3f5aad8..62dc682 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -1278,7 +1278,6 @@ router_parse_entry_from_string(const char *s, const char *end,
   char digest[128];
   smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
   directory_token_t *tok;
-  struct in_addr in;
   const char *start_of_annotations, *cp, *s_dup = s;
   size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
   int ok = 1;
@@ -1387,11 +1386,10 @@ router_parse_entry_from_string(const char *s, const char *end,
     goto err;
   }
   router->address = tor_strdup(tok->args[1]);
-  if (!tor_inet_aton(router->address, &in)) {
+  if (!tor_inet_pton(AF_UNSPEC, router->address, &router->addr)) {
     log_warn(LD_DIR,"Router address is not an IP address.");
     goto err;
   }
-  router->addr = ntohl(in.s_addr);
 
   router->or_port =
     (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
@@ -1803,18 +1801,16 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
 
   tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
   if (tok) {
-    struct in_addr in;
     char *address = NULL;
     tor_assert(tok->n_args);
     /* XXX023 use tor_addr_port_parse() below instead. -RD */
     if (parse_addr_port(LOG_WARN, tok->args[0], &address, NULL,
                         &cert->dir_port)<0 ||
-        tor_inet_aton(address, &in) == 0) {
+        tor_inet_pton(AF_UNSPEC, address, &cert->addr) == 0) {
       log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
       tor_free(address);
       goto err;
     }
-    cert->addr = ntohl(in.s_addr);
     tor_free(address);
   }
 
@@ -1951,7 +1947,6 @@ routerstatus_parse_entry_from_string(memarea_t *area,
   routerstatus_t *rs = NULL;
   directory_token_t *tok;
   char timebuf[ISO_TIME_LEN+1];
-  struct in_addr in;
   int offset = 0;
   tor_assert(tokens);
   tor_assert(bool_eq(vote, vote_rs));
@@ -2018,12 +2013,11 @@ routerstatus_parse_entry_from_string(memarea_t *area,
     goto err;
   }
 
-  if (tor_inet_aton(tok->args[5+offset], &in) == 0) {
+  if (tor_inet_pton(AF_UNSPEC, tok->args[5+offset], &rs->addr) == 0) {
     log_warn(LD_DIR, "Error parsing router address in network-status %s",
              escaped(tok->args[5+offset]));
     goto err;
   }
-  rs->addr = ntohl(in.s_addr);
 
   rs->or_port = (uint16_t) tor_parse_long(tok->args[6+offset],
                                          10,0,65535,NULL,NULL);
@@ -2230,7 +2224,6 @@ networkstatus_v2_parse_from_string(const char *s)
   networkstatus_v2_t *ns = NULL;
   char ns_digest[DIGEST_LEN];
   char tmp_digest[DIGEST_LEN];
-  struct in_addr in;
   directory_token_t *tok;
   int i;
   memarea_t *area = NULL;
@@ -2260,12 +2253,11 @@ networkstatus_v2_parse_from_string(const char *s)
   tok = find_by_keyword(tokens, K_DIR_SOURCE);
   tor_assert(tok->n_args >= 3);
   ns->source_address = tor_strdup(tok->args[0]);
-  if (tor_inet_aton(tok->args[1], &in) == 0) {
+  if (tor_inet_pton(AF_UNSPEC, tok->args[1], &ns->source_addr) == 0) {
     log_warn(LD_DIR, "Error parsing network-status source address %s",
              escaped(tok->args[1]));
     goto err;
   }
-  ns->source_addr = ntohl(in.s_addr);
   ns->source_dirport =
     (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
   if (ns->source_dirport == 0) {
@@ -2791,7 +2783,6 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
   const char *cert, *end_of_header, *end_of_footer, *s_dup = s;
   directory_token_t *tok;
   int ok;
-  struct in_addr in;
   int i, inorder, n_signatures = 0;
   memarea_t *area = NULL, *rs_area = NULL;
   consensus_flavor_t flav = FLAV_NS;
@@ -3006,12 +2997,11 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
         goto err;
       }
       voter->address = tor_strdup(tok->args[2]);
-      if (!tor_inet_aton(tok->args[3], &in)) {
+      if (!tor_inet_pton(AF_UNSPEC, tok->args[3], &voter->addr)) {
         log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
                  escaped(tok->args[3]));
         goto err;
       }
-      voter->addr = ntohl(in.s_addr);
       voter->dir_port = (uint16_t)
         tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
       if (!ok)
diff --git a/src/test/test.c b/src/test/test.c
index e2f8b11..76704de 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -625,19 +625,22 @@ test_policies(void)
   test_assert(p != NULL);
   test_eq(ADDR_POLICY_REJECT, p->policy_type);
   tor_addr_from_ipv4h(&tar, 0xc0a80000u);
-  test_eq(0, tor_addr_compare(&p->addr, &tar, CMP_EXACT));
+  test_assert(tor_addr_eq(&p->addr, &tar));
   test_eq(16, p->maskbits);
   test_eq(1, p->prt_min);
   test_eq(65535, p->prt_max);
 
   smartlist_add(policy, p);
 
+  tor_addr_from_ipv4h(&tar, 0x01020304u);
   test_assert(ADDR_POLICY_ACCEPTED ==
-          compare_addr_to_addr_policy(0x01020304u, 2, policy));
+          compare_tor_addr_to_addr_policy(&tar, 2, policy));
+  tor_addr_from_ipv4h(&tar, 0);
   test_assert(ADDR_POLICY_PROBABLY_ACCEPTED ==
-          compare_addr_to_addr_policy(0, 2, policy));
+          compare_tor_addr_to_addr_policy(&tar, 2, policy));
+  tor_addr_from_ipv4h(&tar, 0xc0a80102);
   test_assert(ADDR_POLICY_REJECTED ==
-          compare_addr_to_addr_policy(0xc0a80102, 2, policy));
+          compare_tor_addr_to_addr_policy(&tar, 2, policy));
 
   test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, NULL, 1));
   test_assert(policy2);
@@ -1047,12 +1050,13 @@ static void
 test_geoip(void)
 {
   int i, j;
+  tor_addr_t addr;
   time_t now = time(NULL);
   char *s = NULL;
 
   /* Populate the DB a bit.  Add these in order, since we can't do the final
    * 'sort' step.  These aren't very good IP addresses, but they're perfectly
-   * fine uint32_t values. */
+   * fine 32-bit values. */
   test_eq(0, geoip_parse_entry("10,50,AB"));
   test_eq(0, geoip_parse_entry("52,90,XY"));
   test_eq(0, geoip_parse_entry("95,100,AB"));
@@ -1062,31 +1066,48 @@ test_geoip(void)
 
   /* We should have 4 countries: ??, ab, xy, zz. */
   test_eq(4, geoip_get_n_countries());
+
   /* Make sure that country ID actually works. */
-#define NAMEFOR(x) geoip_get_country_name(geoip_get_country_by_ip(x))
-  test_streq("??", NAMEFOR(3));
-  test_eq(0, geoip_get_country_by_ip(3));
-  test_streq("ab", NAMEFOR(32));
-  test_streq("??", NAMEFOR(5));
-  test_streq("??", NAMEFOR(51));
-  test_streq("xy", NAMEFOR(150));
-  test_streq("xy", NAMEFOR(190));
-  test_streq("??", NAMEFOR(2000));
+#define SETIP(x) tor_addr_from_ipv4n(&addr, x)
+#define NAMEFOR() geoip_get_country_name(geoip_get_country_by_ip(&addr))
+  SETIP(3);
+  test_streq("??", NAMEFOR());
+  test_eq(0, geoip_get_country_by_ip(&addr));
+  SETIP(32);
+  test_streq("ab", NAMEFOR());
+  SETIP(5);
+  test_streq("??", NAMEFOR());
+  SETIP(51);
+  test_streq("??", NAMEFOR());
+  SETIP(150);
+  test_streq("xy", NAMEFOR());
+  SETIP(190);
+  test_streq("xy", NAMEFOR());
+  SETIP(2000);
+  test_streq("??", NAMEFOR());
+#undef SETIP
 #undef NAMEFOR
 
   get_options()->BridgeRelay = 1;
   get_options()->BridgeRecordUsageByCountry = 1;
   /* Put 9 observations in AB... */
-  for (i=32; i < 40; ++i)
-    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-7200);
-  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 225, now-7200);
+  for (i=32; i < 40; ++i) {
+    tor_addr_from_ipv4n(&addr, i);
+    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now-7200);
+  }
+  tor_addr_from_ipv4n(&addr, 225);
+  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now-7200);
   /* and 3 observations in XY, several times. */
   for (j=0; j < 10; ++j)
-    for (i=52; i < 55; ++i)
-      geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-3600);
+    for (i=52; i < 55; ++i) {
+      tor_addr_from_ipv4n(&addr, i);
+      geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now-3600);
+    }
   /* and 17 observations in ZZ... */
-  for (i=110; i < 127; ++i)
-    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now);
+  for (i=110; i < 127; ++i) {
+    tor_addr_from_ipv4n(&addr, i);
+    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now);
+  }
   s = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
   test_assert(s);
   test_streq("zz=24,ab=16,xy=8", s);
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 6db4ee2..2a02df1 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -10,20 +10,21 @@
 static void
 test_addr_basic(void)
 {
-  uint32_t u32;
+  tor_addr_t addr;
+  tor_addr_t addr2;
   uint16_t u16;
   char *cp;
 
   /* Test parse_addr_port */
-  cp = NULL; u32 = 3; u16 = 3;
-  test_assert(!parse_addr_port(LOG_WARN, "1.2.3.4", &cp, &u32, &u16));
+  cp = NULL; u16 = 3;
+  test_assert(!parse_addr_port(LOG_WARN, "1.2.3.4", &cp, &addr, &u16));
   test_streq(cp, "1.2.3.4");
-  test_eq(u32, 0x01020304u);
+  test_eq(tor_addr_to_ipv4h(&addr), 0x01020304u);
   test_eq(u16, 0);
   tor_free(cp);
-  test_assert(!parse_addr_port(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16));
+  test_assert(!parse_addr_port(LOG_WARN, "4.3.2.1:99", &cp, &addr, &u16));
   test_streq(cp, "4.3.2.1");
-  test_eq(u32, 0x04030201u);
+  test_eq(tor_addr_to_ipv4h(&addr), 0x04030201u);
   test_eq(u16, 99);
   tor_free(cp);
   test_assert(!parse_addr_port(LOG_WARN, "nonexistent.address:4040",
@@ -31,28 +32,33 @@ test_addr_basic(void)
   test_streq(cp, "nonexistent.address");
   test_eq(u16, 4040);
   tor_free(cp);
-  test_assert(!parse_addr_port(LOG_WARN, "localhost:9999", &cp, &u32, &u16));
+  test_assert(!parse_addr_port(LOG_WARN, "localhost:9999", &cp, &addr, &u16));
   test_streq(cp, "localhost");
-  test_eq(u32, 0x7f000001u);
+  test_eq(tor_addr_to_ipv4h(&addr), 0x7f000001u);
   test_eq(u16, 9999);
   tor_free(cp);
-  u32 = 3;
-  test_assert(!parse_addr_port(LOG_WARN, "localhost", NULL, &u32, &u16));
+  test_assert(!parse_addr_port(LOG_WARN, "localhost", NULL, &addr, &u16));
   test_eq(cp, NULL);
-  test_eq(u32, 0x7f000001u);
+  tor_addr_from_ipv4h(&addr2, 0x7f000001u);
+  test_assert(tor_addr_eq(&addr, &addr2));
   test_eq(u16, 0);
   tor_free(cp);
-  test_eq(0, addr_mask_get_bits(0x0u));
-  test_eq(32, addr_mask_get_bits(0xFFFFFFFFu));
-  test_eq(16, addr_mask_get_bits(0xFFFF0000u));
-  test_eq(31, addr_mask_get_bits(0xFFFFFFFEu));
-  test_eq(1, addr_mask_get_bits(0x80000000u));
+  tor_addr_from_ipv4h(&addr, 0x0u);
+  test_eq(0, tor_addr_mask_get_bits(&addr));
+  tor_addr_from_ipv4h(&addr, 0xFFFFFFFFu);
+  test_eq(32, tor_addr_mask_get_bits(&addr));
+  tor_addr_from_ipv4h(&addr, 0xFFFF0000u);
+  test_eq(16, tor_addr_mask_get_bits(&addr));
+  tor_addr_from_ipv4h(&addr, 0xFFFFFFFEu);
+  test_eq(31, tor_addr_mask_get_bits(&addr));
+  tor_addr_from_ipv4h(&addr, 0x80000000u);
+  test_eq(1, tor_addr_mask_get_bits(&addr));
 
   /* Test inet_ntop */
   {
     char tmpbuf[TOR_ADDR_BUF_LEN];
     const char *ip = "176.192.208.224";
-    struct in_addr in;
+    struct tor_addr_t in;
     tor_inet_pton(AF_INET, ip, &in);
     tor_inet_ntop(AF_INET, &in, tmpbuf, sizeof(tmpbuf));
     test_streq(tmpbuf, ip);
@@ -104,7 +110,7 @@ test_addr_basic(void)
 /** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that
  * passes tor_addr_is_internal() with <b>for_listening</b>. */
 #define test_internal_ip(a,for_listening) STMT_BEGIN           \
-    test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \
+    test_eq(tor_inet_pton(AF_INET6, a, &t1), 1); \
     t1.family = AF_INET6;                                      \
     if (!tor_addr_is_internal(&t1, for_listening))             \
       test_fail_msg( a "was not internal.");                   \
@@ -113,7 +119,7 @@ test_addr_basic(void)
 /** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that
  * does not pass tor_addr_is_internal() with <b>for_listening</b>. */
 #define test_external_ip(a,for_listening) STMT_BEGIN           \
-    test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \
+    test_eq(tor_inet_pton(AF_INET6, a, &t1), 1); \
     t1.family = AF_INET6;                                      \
     if (tor_addr_is_internal(&t1, for_listening))              \
       test_fail_msg(a  "was not external.");                   \
@@ -123,8 +129,8 @@ test_addr_basic(void)
  * tor_inet_pton(), give addresses that compare in the order defined by
  * <b>op</b> with tor_addr_compare(). */
 #define test_addr_compare(a, op, b) STMT_BEGIN                    \
-    test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1);    \
-    test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1);    \
+    test_eq(tor_inet_pton(AF_INET6, a, &t1), 1);    \
+    test_eq(tor_inet_pton(AF_INET6, b, &t2), 1);    \
     t1.family = t2.family = AF_INET6;                             \
     r = tor_addr_compare(&t1,&t2,CMP_SEMANTIC);                   \
     if (!(r op 0))                                                \
@@ -135,8 +141,8 @@ test_addr_basic(void)
  * tor_inet_pton(), give addresses that compare in the order defined by
  * <b>op</b> with tor_addr_compare_masked() with <b>m</b> masked. */
 #define test_addr_compare_masked(a, op, b, m) STMT_BEGIN          \
-    test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1);    \
-    test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1);    \
+    test_eq(tor_inet_pton(AF_INET6, a, &t1), 1);    \
+    test_eq(tor_inet_pton(AF_INET6, b, &t2), 1);    \
     t1.family = t2.family = AF_INET6;                             \
     r = tor_addr_compare_masked(&t1,&t2,m,CMP_SEMANTIC);          \
     if (!(r op 0))                                                \
@@ -150,7 +156,7 @@ test_addr_basic(void)
 #define test_addr_mask_ports_parse(xx, f, ip1, ip2, ip3, ip4, mm, pt1, pt2) \
   STMT_BEGIN                                                                \
     test_eq(tor_addr_parse_mask_ports(xx, &t1, &mask, &port1, &port2), f);  \
-    p1=tor_inet_ntop(AF_INET6, &t1.addr.in6_addr, bug, sizeof(bug));        \
+    p1=tor_inet_ntop(AF_INET6, &t1, bug, sizeof(bug));        \
     test_eq(htonl(ip1), tor_addr_to_in6_addr32(&t1)[0]);            \
     test_eq(htonl(ip2), tor_addr_to_in6_addr32(&t1)[1]);            \
     test_eq(htonl(ip3), tor_addr_to_in6_addr32(&t1)[2]);            \
@@ -165,7 +171,7 @@ static void
 test_addr_ip6_helpers(void)
 {
   char buf[TOR_ADDR_BUF_LEN], bug[TOR_ADDR_BUF_LEN];
-  struct in6_addr a1, a2;
+  tor_addr_t a1, a2;
   tor_addr_t t1, t2;
   int r, i;
   uint16_t port1, port2;
@@ -189,8 +195,7 @@ test_addr_ip6_helpers(void)
 
   memset(&sa_storage, 0, sizeof(sa_storage));
   test_eq(sizeof(struct sockaddr_in),
-          tor_addr_to_sockaddr(&t1, 1234, (struct sockaddr *)&sa_storage,
-                               sizeof(sa_storage)));
+          tor_addr_to_sockaddr(&t1, 1234, &sa_storage, sizeof(sa_storage)));
   test_eq(1234, ntohs(sin->sin_port));
   test_eq(0x7f7f0102, ntohl(sin->sin_addr.s_addr));
 
@@ -201,13 +206,12 @@ test_addr_ip6_helpers(void)
   sin6->sin6_addr.s6_addr[0] = 128;
   tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, NULL);
   test_eq(tor_addr_family(&t1), AF_INET6);
-  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
+  p1 = tor_addr_to_str(&t1, buf, sizeof(buf), 0);
   test_streq(p1, "8000::");
 
   memset(&sa_storage, 0, sizeof(sa_storage));
   test_eq(sizeof(struct sockaddr_in6),
-          tor_addr_to_sockaddr(&t1, 9999, (struct sockaddr *)&sa_storage,
-                               sizeof(sa_storage)));
+          tor_addr_to_sockaddr(&t1, 9999, &sa_storage, sizeof(sa_storage)));
   test_eq(AF_INET6, sin6->sin6_family);
   test_eq(9999, ntohs(sin6->sin6_port));
   test_eq(0x80000000, ntohl(S6_ADDR32(sin6->sin6_addr)[0]));
@@ -229,7 +233,7 @@ test_addr_ip6_helpers(void)
   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]); }
+  for (i=0;i<16;++i) { test_eq(i+1, (int)a1.addr.in6_addr.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");
@@ -340,7 +344,8 @@ test_addr_ip6_helpers(void)
   test_internal_ip("::ffff:169.254.0.0", 0);
   test_internal_ip("::ffff:169.254.255.255", 0);
   test_external_ip("::ffff:169.255.0.0", 0);
-  test_assert(is_internal_IP(0x7f000001, 0));
+  tor_addr_from_ipv4n(&t1, htonl(0x7f000001));
+  test_assert(tor_addr_is_internal(&t1, 0));
 
   /* tor_addr_compare(tor_addr_t x2) */
   test_addr_compare("ffff::", ==, "ffff::0");
@@ -363,10 +368,10 @@ test_addr_ip6_helpers(void)
 
   /* Test decorated addr_to_string. */
   test_eq(AF_INET6, tor_addr_from_str(&t1, "[123:45:6789::5005:11]"));
-  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
+  p1 = tor_addr_to_str(&t1, buf, sizeof(buf), 1);
   test_streq(p1, "[123:45:6789::5005:11]");
   test_eq(AF_INET, tor_addr_from_str(&t1, "18.0.0.1"));
-  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
+  p1 = tor_addr_to_str(&t1, buf, sizeof(buf), 1);
   test_streq(p1, "18.0.0.1");
 
   /* Test tor_addr_parse_reverse_lookup_name */
@@ -378,13 +383,13 @@ test_addr_ip6_helpers(void)
                                          AF_UNSPEC, 1);
   test_eq(1, i);
   test_eq(tor_addr_family(&t1), AF_INET);
-  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
+  p1 = tor_addr_to_str(&t1, buf, sizeof(buf), 1);
   test_streq(p1, "192.168.0.1");
   i = tor_addr_parse_reverse_lookup_name(&t1, "192.168.0.99", AF_UNSPEC, 0);
   test_eq(0, i);
   i = tor_addr_parse_reverse_lookup_name(&t1, "192.168.0.99", AF_UNSPEC, 1);
   test_eq(1, i);
-  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
+  p1 = tor_addr_to_str(&t1, buf, sizeof(buf), 1);
   test_streq(p1, "192.168.0.99");
   memset(&t1, 0, sizeof(t1));
   i = tor_addr_parse_reverse_lookup_name(&t1,
@@ -393,7 +398,7 @@ test_addr_ip6_helpers(void)
                                          "ip6.ARPA",
                                          AF_UNSPEC, 0);
   test_eq(1, i);
-  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
+  p1 = tor_addr_to_str(&t1, buf, sizeof(buf), 1);
   test_streq(p1, "[9dee:effe:ebe1:beef:fedc:ba98:7654:3210]");
   /* Failing cases. */
   i = tor_addr_parse_reverse_lookup_name(&t1,
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 4b86be4..e525c78 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -88,7 +88,7 @@ test_dir_formats(void)
   get_platform_str(platform, sizeof(platform));
   r1 = tor_malloc_zero(sizeof(routerinfo_t));
   r1->address = tor_strdup("18.244.0.1");
-  r1->addr = 0xc0a80001u; /* 192.168.0.1 */
+  tor_addr_from_ipv4h(&r1->addr, 0xc0a80001u); /* 192.168.0.1 */
   r1->cache_info.published_on = 0;
   r1->or_port = 9000;
   r1->dir_port = 9003;
@@ -113,7 +113,7 @@ test_dir_formats(void)
   ex2->prt_min = ex2->prt_max = 24;
   r2 = tor_malloc_zero(sizeof(routerinfo_t));
   r2->address = tor_strdup("1.1.1.1");
-  r2->addr = 0x0a030201u; /* 10.3.2.1 */
+  tor_addr_from_ipv4h(&r2->addr, 0x0a030201u); /* 10.3.2.1 */
   r2->platform = tor_strdup(platform);
   r2->cache_info.published_on = 5;
   r2->or_port = 9005;
@@ -656,7 +656,7 @@ test_same_voter(networkstatus_voter_info_t *v1,
   test_streq(v1->nickname, v2->nickname);
   test_memeq(v1->identity_digest, v2->identity_digest, DIGEST_LEN);
   test_streq(v1->address, v2->address);
-  test_eq(v1->addr, v2->addr);
+  test_assert(tor_addr_eq(&v1->addr, &v2->addr));
   test_eq(v1->dir_port, v2->dir_port);
   test_eq(v1->or_port, v2->or_port);
   test_streq(v1->contact, v2->contact);
@@ -725,6 +725,7 @@ test_dir_v3_networkstatus(void)
   routerstatus_t *rs;
   char *v1_text=NULL, *v2_text=NULL, *v3_text=NULL, *consensus_text=NULL, *cp;
   smartlist_t *votes = smartlist_create();
+  tor_addr_t addrt;
 
   /* For generating the two other consensuses. */
   char *detached_text1=NULL, *detached_text2=NULL;
@@ -780,7 +781,7 @@ test_dir_v3_networkstatus(void)
   voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
   voter->nickname = tor_strdup("Voter1");
   voter->address = tor_strdup("1.2.3.4");
-  voter->addr = 0x01020304;
+  tor_addr_from_ipv4h(&voter->addr,0x01020304);
   voter->dir_port = 80;
   voter->or_port = 9000;
   voter->contact = tor_strdup("voter@example.com");
@@ -799,7 +800,7 @@ test_dir_v3_networkstatus(void)
   strlcpy(rs->nickname, "router2", sizeof(rs->nickname));
   memset(rs->identity_digest, 3, DIGEST_LEN);
   memset(rs->descriptor_digest, 78, DIGEST_LEN);
-  rs->addr = 0x99008801;
+  tor_addr_from_ipv4h(&rs->addr,0x99008801);
   rs->or_port = 443;
   rs->dir_port = 8000;
   /* all flags but running cleared */
@@ -815,7 +816,7 @@ test_dir_v3_networkstatus(void)
   strlcpy(rs->nickname, "router1", sizeof(rs->nickname));
   memset(rs->identity_digest, 5, DIGEST_LEN);
   memset(rs->descriptor_digest, 77, DIGEST_LEN);
-  rs->addr = 0x99009901;
+  tor_addr_from_ipv4h(&rs->addr, 0x99009901);
   rs->or_port = 443;
   rs->dir_port = 0;
   rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
@@ -831,7 +832,7 @@ test_dir_v3_networkstatus(void)
   strlcpy(rs->nickname, "router3", sizeof(rs->nickname));
   memset(rs->identity_digest, 33, DIGEST_LEN);
   memset(rs->descriptor_digest, 79, DIGEST_LEN);
-  rs->addr = 0xAA009901;
+  tor_addr_from_ipv4h(&rs->addr,0xAA009901);
   rs->or_port = 400;
   rs->dir_port = 9999;
   rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
@@ -848,7 +849,7 @@ test_dir_v3_networkstatus(void)
   strlcpy(rs->nickname, "router4", sizeof(rs->nickname));
   memset(rs->identity_digest, 34, DIGEST_LEN);
   memset(rs->descriptor_digest, 47, DIGEST_LEN);
-  rs->addr = 0xC0000203;
+  tor_addr_from_ipv4h(&rs->addr,0xC0000203);
   rs->or_port = 500;
   rs->dir_port = 1999;
   /* Running flag (and others) cleared */
@@ -875,7 +876,8 @@ test_dir_v3_networkstatus(void)
   voter = smartlist_get(v1->voters, 0);
   test_streq(voter->nickname, "Voter1");
   test_streq(voter->address, "1.2.3.4");
-  test_eq(voter->addr, 0x01020304);
+  tor_addr_from_ipv4h(&addrt, 0x01020304);
+  test_assert(tor_addr_eq(&voter->addr, &addrt));
   test_eq(voter->dir_port, 80);
   test_eq(voter->or_port, 9000);
   test_streq(voter->contact, "voter@example.com");
@@ -895,7 +897,8 @@ test_dir_v3_networkstatus(void)
              "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3",
              DIGEST_LEN);
   test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
-  test_eq(rs->addr, 0x99008801);
+  tor_addr_from_ipv4h(&addrt, 0x99008801);
+  test_assert(tor_addr_eq(&rs->addr, &addrt));
   test_eq(rs->or_port, 443);
   test_eq(rs->dir_port, 8000);
   test_eq(vrs->flags, U64_LITERAL(16)); // no flags except "running"
@@ -909,7 +912,8 @@ test_dir_v3_networkstatus(void)
              "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5",
              DIGEST_LEN);
   test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
-  test_eq(rs->addr, 0x99009901);
+  tor_addr_from_ipv4h(&addrt, 0x99009901);
+  test_assert(tor_addr_eq(&rs->addr, &addrt));
   test_eq(rs->or_port, 443);
   test_eq(rs->dir_port, 0);
   test_eq(vrs->flags, U64_LITERAL(254)); // all flags except "authority."
@@ -942,7 +946,7 @@ test_dir_v3_networkstatus(void)
   tor_free(voter->address);
   voter->nickname = tor_strdup("Voter2");
   voter->address = tor_strdup("2.3.4.5");
-  voter->addr = 0x02030405;
+  tor_addr_from_ipv4h(&voter->addr,0x02030405);
   crypto_pk_get_digest(cert2->identity_key, voter->identity_digest);
   smartlist_add(vote->known_flags, tor_strdup("MadeOfCheese"));
   smartlist_add(vote->known_flags, tor_strdup("MadeOfTin"));
@@ -984,7 +988,7 @@ test_dir_v3_networkstatus(void)
   tor_free(voter->address);
   voter->nickname = tor_strdup("Voter3");
   voter->address = tor_strdup("3.4.5.6");
-  voter->addr = 0x03040506;
+  tor_addr_from_ipv4h(&voter->addr,0x03040506);
   crypto_pk_get_digest(cert3->identity_key, voter->identity_digest);
   /* This one has a legacy id. */
   memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN);
@@ -1091,7 +1095,8 @@ test_dir_v3_networkstatus(void)
   test_streq(rs->nickname, "router1");
   test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
   test_eq(rs->published_on, now-1000);
-  test_eq(rs->addr, 0x99009901);
+  tor_addr_from_ipv4h(&addrt, 0x99009901);
+  test_assert(tor_addr_eq(&rs->addr,&addrt));
   test_eq(rs->or_port, 443);
   test_eq(rs->dir_port, 0);
   test_assert(!rs->is_authority);
diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c
index a04edda..98345d7 100644
--- a/src/tools/tor-gencert.c
+++ b/src/tools/tor-gencert.c
@@ -161,18 +161,16 @@ parse_commandline(int argc, char **argv)
     } else if (!strcmp(argv[i], "-v")) {
       verbose = 1;
     } else if (!strcmp(argv[i], "-a")) {
-      uint32_t addr;
+      tor_addr_t addr;
       uint16_t port;
       char b[INET_NTOA_BUF_LEN];
-      struct in_addr in;
       if (i+1>=argc) {
         fprintf(stderr, "No argument to -a\n");
         return 1;
       }
       if (parse_addr_port(LOG_ERR, argv[++i], NULL, &addr, &port)<0)
         return 1;
-      in.s_addr = htonl(addr);
-      tor_inet_ntoa(&in, b, sizeof(b));
+      tor_addr_to_str(&addr,b,sizeof(b),1);
       address = tor_malloc(INET_NTOA_BUF_LEN+32);
       tor_snprintf(address, INET_NTOA_BUF_LEN+32, "%s:%d", b, (int)port);
     } else if (!strcmp(argv[i], "--create-identity-key")) {
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 12349d9..b1a74ed 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -74,14 +74,14 @@ build_socks_resolve_request(char **out,
     memcpy((*out)+8+strlen(username)+1, hostname, strlen(hostname)+1);
   } else if (version == 5) {
     int is_ip_address;
-    struct in_addr in;
+    tor_addr_t addr;
     size_t addrlen;
-    is_ip_address = tor_inet_aton(hostname, &in);
+    is_ip_address = tor_inet_pton(AF_UNSPEC, hostname, &addr);
     if (!is_ip_address && reverse) {
       log_err(LD_GENERAL, "Tried to do a reverse lookup on a non-IP!");
       return -1;
     }
-    addrlen = reverse ? 4 : 1 + strlen(hostname);
+    addrlen = reverse ? (tor_addr_family(&addr) == AF_INET ? 4 : 16) : 1 + strlen(hostname);
     len = 6 + addrlen;
     *out = tor_malloc(len);
     (*out)[0] = 5; /* SOCKS version 5 */
@@ -89,7 +89,7 @@ build_socks_resolve_request(char **out,
     (*out)[2] = 0; /* reserved. */
     (*out)[3] = reverse ? 1 : 3;
     if (reverse) {
-      set_uint32((*out)+4, in.s_addr);
+      memcpy((*out)+4, tor_addr_raw(&addr), addrlen);
     } else {
       (*out)[4] = (char)(uint8_t)(addrlen - 1);
       memcpy((*out)+5, hostname, addrlen - 1);
@@ -109,7 +109,7 @@ build_socks_resolve_request(char **out,
 static int
 parse_socks4a_resolve_response(const char *hostname,
                                const char *response, size_t len,
-                               uint32_t *addr_out)
+                               tor_addr_t *addr_out)
 {
   uint8_t status;
   tor_assert(response);
@@ -140,7 +140,8 @@ parse_socks4a_resolve_response(const char *hostname,
     return -1;
   }
 
-  *addr_out = ntohl(get_uint32(response+4));
+  /* Note that there is no IPv6 support in SOCKS4(a) */
+  tor_addr_from_ipv4n(addr_out, get_uint32(response+4));
   return 0;
 }
 
@@ -177,12 +178,12 @@ socks5_reason_to_string(char reason)
  * address (in host order) into *<b>result_addr</b>.
  */
 static int
-do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
+do_resolve(const char *hostname, tor_addr_t *sockshost, uint16_t socksport,
            int reverse, int version,
-           uint32_t *result_addr, char **result_hostname)
+           tor_addr_t *result_addr, char **result_hostname)
 {
   int s;
-  struct sockaddr_in socksaddr;
+  struct sockaddr_storage socksaddr;
   char *req = NULL;
   ssize_t len = 0;
 
@@ -190,19 +191,17 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
   tor_assert(result_addr);
   tor_assert(version == 4 || version == 5);
 
-  *result_addr = 0;
+  memset(result_addr, 0, sizeof(*result_addr));
   *result_hostname = NULL;
 
-  s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
+  s = tor_open_socket(tor_addr_protocol(sockshost),SOCK_STREAM,IPPROTO_TCP);
   if (s<0) {
     log_sock_error("creating_socket", -1);
     return -1;
   }
 
-  memset(&socksaddr, 0, sizeof(socksaddr));
-  socksaddr.sin_family = AF_INET;
-  socksaddr.sin_port = htons(socksport);
-  socksaddr.sin_addr.s_addr = htonl(sockshost);
+  tor_addr_to_sockaddr(sockshost, socksport, &socksaddr, sizeof(socksaddr));
+
   if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) {
     log_sock_error("connecting to SOCKS host", s);
     return -1;
@@ -281,14 +280,15 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
     if (reply_buf[3] == 1) {
       /* IPv4 address */
       if (read_all(s, reply_buf, 4, 1) != 4) {
-        log_err(LD_NET, "Error reading address in socks5 response.");
+        log_err(LD_NET, "Error reading IPv4 address in socks5 response.");
         return -1;
       }
-      *result_addr = ntohl(get_uint32(reply_buf));
+      tor_addr_from_ipv4n(result_addr, get_uint32(reply_buf));
     } else if (reply_buf[3] == 3) {
+      /* Domain name */
       size_t result_len;
       if (read_all(s, reply_buf, 1, 1) != 1) {
-        log_err(LD_NET, "Error reading address_length in socks5 response.");
+        log_err(LD_NET, "Error reading hostname address_length in socks5 response.");
         return -1;
       }
       result_len = *(uint8_t*)(reply_buf);
@@ -298,6 +298,13 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
         return -1;
       }
       (*result_hostname)[result_len] = '\0';
+    } else if (reply_buf[3] == 4) {
+      /* IPv6 address */
+      if (read_all(s, reply_buf, 16, 1) != 16) {
+        log_err(LD_NET, "Error reading IPv6 address in socks5 response.");
+        return -1;
+      }
+      tor_addr_from_ipv6_bytes(result_addr, reply_buf);
     }
   }
 
@@ -308,7 +315,7 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
 static void
 usage(void)
 {
-  puts("Syntax: tor-resolve [-4] [-v] [-x] [-F] [-p port] "
+  puts("Syntax: tor-resolve [-4] [-5] [-v] [-x] [-F] [-p port] "
        "hostname [sockshost:socksport]");
   exit(1);
 }
@@ -317,13 +324,11 @@ usage(void)
 int
 main(int argc, char **argv)
 {
-  uint32_t sockshost;
+  tor_addr_t sockshost, result;
   uint16_t socksport = 0, port_option = 0;
   int isSocks4 = 0, isVerbose = 0, isReverse = 0, force = 0;
   char **arg;
   int n_args;
-  struct in_addr a;
-  uint32_t result = 0;
   char *result_hostname = NULL;
   char buf[INET_NTOA_BUF_LEN];
   log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
@@ -385,8 +390,8 @@ main(int argc, char **argv)
   add_stream_log(s, "<stderr>", fileno(stderr));
 
   if (n_args == 1) {
-    log_debug(LD_CONFIG, "defaulting to localhost");
-    sockshost = 0x7f000001u; /* localhost */
+    log_debug(LD_CONFIG, "defaulting to IPv4 localhost");
+    tor_addr_from_loopback(&sockshost, AF_INET);
     if (port_option) {
       log_debug(LD_CONFIG, "Using port %d", (int)port_option);
       socksport = port_option;
@@ -417,7 +422,7 @@ main(int argc, char **argv)
     return 1;
   }
 
-  if (do_resolve(arg[0], sockshost, socksport, isReverse,
+  if (do_resolve(arg[0], &sockshost, socksport, isReverse,
                  isSocks4 ? 4 : 5, &result,
                  &result_hostname))
     return 1;
@@ -425,8 +430,7 @@ main(int argc, char **argv)
   if (result_hostname) {
     printf("%s\n", result_hostname);
   } else {
-    a.s_addr = htonl(result);
-    tor_inet_ntoa(&a, buf, sizeof(buf));
+    tor_addr_to_str(&result, buf, sizeof(buf),1);
     printf("%s\n", buf);
   }
   return 0;
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 5483b6d..22f9272 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -42,9 +42,6 @@
 /* Define to 1 if you have the <grp.h> header file. */
 #undef HAVE_GRP_H
 
-/* Define to 1 if you have the `inet_aton' function. */
-#undef HAVE_INET_ATON
-
 /* Define to 1 if you have the <inttypes.h> header file. */
 /* #define HAVE_INTTYPES_H */
 
