summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2008-07-24 13:44:04 +0000
committerNick Mathewson <nickm@torproject.org>2008-07-24 13:44:04 +0000
commit3ce6e2fba290eb5d3a4d0a3ca2f61658245b52b6 (patch)
tree08c562380df129cb4c8c896eecba0f3d8013d262 /src/common
parented781e69716248111ef1a2ddc1b9add671bd8d16 (diff)
downloadtor-3ce6e2fba290eb5d3a4d0a3ca2f61658245b52b6.tar.gz
tor-3ce6e2fba290eb5d3a4d0a3ca2f61658245b52b6.zip
r17346@aud-055: nickm | 2008-07-24 15:37:19 +0200
Make generic address manipulation functions work better. Switch address policy code to use tor_addr_t, so it can handle IPv6. That is a good place to start. svn:r16178
Diffstat (limited to 'src/common')
-rw-r--r--src/common/compat.c16
-rw-r--r--src/common/compat.h14
-rw-r--r--src/common/util.c91
-rw-r--r--src/common/util.h10
4 files changed, 112 insertions, 19 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index 7a6859af34..eb4afa1a64 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -960,6 +960,22 @@ tor_addr_to_sockaddr(const tor_addr_t *a,
}
}
+/** DOCDOC */
+void
+tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa)
+{
+ memset(&a, 0, sizeof(tor_addr_t));
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+ a->family = AF_INET;
+ a->addr.in_addr.s_addr = sin->sin_addr.s_addr;
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ a->family = AF_INET6;
+ memcpy(&a->addr.in6_addr, &sin6->sin6_addr, sizeof(struct in6_addr));
+ }
+}
+
/** 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.)
diff --git a/src/common/compat.h b/src/common/compat.h
index 7ad964c75d..596a7058fe 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -361,17 +361,18 @@ typedef struct tor_addr_t
/* DOCDOC*/
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_ipv4n(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 const struct in_addr *tor_addr_to_in(const tor_addr_t *a);
static INLINE const struct in6_addr *tor_addr_to_in6(const tor_addr_t *a);
socklen_t tor_addr_to_sockaddr(const tor_addr_t *a, uint16_t port,
struct sockaddr *sa_out);
+void tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa);
static INLINE const struct in6_addr *
tor_addr_to_in6(const tor_addr_t *a)
{
- return &a->addr.in6_addr;
+ return a->family == AF_INET6 ? &a->addr.in6_addr : NULL;
}
#define tor_addr_to_in6_addr16(x) S6_ADDR16(*tor_addr_to_in6(x))
@@ -380,7 +381,7 @@ tor_addr_to_in6(const tor_addr_t *a)
static INLINE uint32_t
tor_addr_to_ipv4n(const tor_addr_t *a)
{
- return a->addr.in_addr.s_addr;
+ return a->family == AF_INET ? a->addr.in_addr.s_addr : 0;
}
static INLINE uint32_t
tor_addr_to_ipv4h(const tor_addr_t *a)
@@ -388,7 +389,7 @@ tor_addr_to_ipv4h(const tor_addr_t *a)
return ntohl(tor_addr_to_ipv4n(a));
}
static INLINE uint32_t
-tor_addr_to_mapped_ipv4n(const tor_addr_t *a)
+tor_addr_to_mapped_ipv4h(const tor_addr_t *a)
{
return ntohl(tor_addr_to_in6_addr32(a)[3]);
}
@@ -400,11 +401,12 @@ tor_addr_family(const tor_addr_t *a)
static INLINE const struct in_addr *
tor_addr_to_in(const tor_addr_t *a)
{
- return &a->addr.in_addr;
+ return a->family == AF_INET ? &a->addr.in_addr : NULL;
}
#define INET_NTOA_BUF_LEN 16 /* 255.255.255.255 */
-#define TOR_ADDR_BUF_LEN 46 /* ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255 */
+#define TOR_ADDR_BUF_LEN 48 /* [ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]
+ */
int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
diff --git a/src/common/util.c b/src/common/util.c
index 47d6aecd8c..42c96beafe 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -2230,17 +2230,27 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening)
/** Convert a tor_addr_t <b>addr</b> into a string, and store it in
* <b>dest</b> of size <b>len</b>. Returns a pointer to dest on success,
- * or NULL on failure.
+ * or NULL on failure. If <b>decorate</b>, surround IPv6 addresses with
+ * brackets.
*/
const char *
-tor_addr_to_str(char *dest, const tor_addr_t *addr, int len)
+tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, int decorate)
{
const char *ptr;
tor_assert(addr && dest);
switch (tor_addr_family(addr)) {
case AF_INET:
- ptr = tor_inet_ntop(AF_INET, &addr->addr.in_addr, dest, len);
+ if (len<3)
+ return NULL;
+ if (decorate)
+ ptr = tor_inet_ntop(AF_INET, &addr->addr.in_addr, dest+1, len-2);
+ else
+ ptr = tor_inet_ntop(AF_INET, &addr->addr.in_addr, dest, len);
+ if (ptr && decorate) {
+ *dest = '[';
+ memcpy(dest+strlen(dest), "]", 2);
+ }
break;
case AF_INET6:
ptr = tor_inet_ntop(AF_INET6, &addr->addr.in6_addr, dest, len);
@@ -2739,6 +2749,29 @@ tor_addr_is_null(const tor_addr_t *addr)
//return 1;
}
+/** Return true iff <b>addr</b> is a loopback address */
+int
+tor_addr_is_loopback(const tor_addr_t *addr)
+{
+ tor_assert(addr);
+ switch (tor_addr_family(addr)) {
+ case AF_INET6: {
+ /* ::1 */
+ uint32_t *a32 = tor_addr_to_in6_addr32(addr);
+ return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) && (a32[3] == 1);
+ }
+ case AF_INET:
+ /* 127.0.0.1 */
+ return (tor_addr_to_ipv4h(addr) & 0xff000000) == 0x7f000000;
+ case AF_UNSPEC:
+ return 0;
+ default:
+ tor_fragile_assert();
+ return 0;
+ }
+}
+
+
/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
* write it as a string into the <b>buf_len</b>-byte buffer in
* <b>buf</b>.
@@ -2756,12 +2789,11 @@ tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
/** Take a 32-bit host-order ipv4 address <b>v4addr</b> and store it in the
* tor_addr *<b>dest</b>.
- *
- * XXXX_IP6 Temporary, for use while 32-bit int addresses are still being
- * passed around.
*/
+/* XXXX_IP6 Temporary, for use while 32-bit int addresses are still being
+ * passed around. */
void
-tor_addr_from_ipv4(tor_addr_t *dest, uint32_t v4addr)
+tor_addr_from_ipv4h(tor_addr_t *dest, uint32_t v4addr)
{
tor_assert(dest);
memset(dest, 0, sizeof(dest));
@@ -2816,12 +2848,22 @@ tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
v_family[0] = tor_addr_family(addr1);
v_family[1] = tor_addr_family(addr2);
+ if (v_family[0] == AF_UNSPEC) {
+ if (v_family[1] == AF_UNSPEC)
+ return 0;
+ else
+ return 1;
+ } else {
+ if (v_family[1] == AF_UNSPEC)
+ return -1;
+ }
+
if (v_family[0] == AF_INET) { /* If this is native IPv4, note the address */
/* Later we risk overwriting a v4-mapped address */
ip4a = tor_addr_to_ipv4h(addr1);
} else if ((v_family[0] == AF_INET6) && tor_addr_is_v4(addr1)) {
v_family[0] = AF_INET;
- ip4a = tor_addr_to_mapped_ipv4n(addr1);
+ ip4a = tor_addr_to_mapped_ipv4h(addr1);
}
if (v_family[1] == AF_INET) { /* If this is native IPv4, note the address */
@@ -2829,7 +2871,7 @@ tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
ip4b = tor_addr_to_ipv4h(addr2);
} else if ((v_family[1] == AF_INET6) && tor_addr_is_v4(addr2)) {
v_family[1] = AF_INET;
- ip4b = tor_addr_to_mapped_ipv4n(addr2);
+ ip4b = tor_addr_to_mapped_ipv4h(addr2);
}
if (v_family[0] > v_family[1]) /* Comparison of virtual families */
@@ -2885,11 +2927,40 @@ tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
}
+
+/** Return a hash code based on the address addr */
+unsigned int
+tor_addr_hash(const tor_addr_t *addr)
+{
+ switch (tor_addr_family(addr)) {
+ case AF_INET:
+ return tor_addr_to_ipv4h(addr);
+ case AF_UNSPEC:
+ return 0x4e4d5342;
+ case AF_INET6: {
+ const uint32_t *u = tor_addr_to_in6_addr32(addr);
+ return u[0] + u[1] + u[2] + u[3];
+ }
+ default:
+ tor_fragile_assert();
+ return 0;
+ }
+}
+
+/** Return a newly allocatd string with a representation of <b>addr</b>. */
+char *
+tor_dup_addr(const tor_addr_t *addr)
+{
+ char buf[TOR_ADDR_BUF_LEN];
+ tor_addr_to_str(buf, addr, sizeof(buf), 0);
+ return tor_strdup(buf);
+}
+
/** Given a host-order <b>addr</b>, call tor_inet_ntop() on it
* and return a strdup of the resulting address.
*/
char *
-tor_dup_addr(uint32_t addr)
+tor_dup_ip(uint32_t addr)
{
char buf[TOR_ADDR_BUF_LEN];
struct in_addr in;
diff --git a/src/common/util.h b/src/common/util.h
index f6d547cd29..c2e1604cbe 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -276,23 +276,27 @@ int parse_addr_and_port_range(const char *s, uint32_t *addr_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_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
-char *tor_dup_addr(uint32_t addr) ATTR_MALLOC;
+char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC;
+char *tor_dup_ip(uint32_t addr) ATTR_MALLOC;
int get_interface_address(int severity, uint32_t *addr);
int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr);
int tor_addr_compare(const tor_addr_t *addr1, const tor_addr_t *addr2);
int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
maskbits_t mask);
+unsigned int tor_addr_hash(const tor_addr_t *addr);
int tor_addr_is_v4(const tor_addr_t *addr);
int tor_addr_is_internal(const tor_addr_t *ip, int for_listening) ATTR_PURE;
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, int len);
+const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, int 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);
-void tor_addr_from_ipv4(tor_addr_t *dest, uint32_t v4addr);
+void tor_addr_from_ipv4h(tor_addr_t *dest, uint32_t v4addr);
int tor_addr_is_null(const tor_addr_t *addr);
+int tor_addr_is_loopback(const tor_addr_t *addr);
/* Process helpers */
void start_daemon(void);