diff options
author | Nick Mathewson <nickm@torproject.org> | 2008-07-24 13:44:04 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2008-07-24 13:44:04 +0000 |
commit | 3ce6e2fba290eb5d3a4d0a3ca2f61658245b52b6 (patch) | |
tree | 08c562380df129cb4c8c896eecba0f3d8013d262 /src/common | |
parent | ed781e69716248111ef1a2ddc1b9add671bd8d16 (diff) | |
download | tor-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.c | 16 | ||||
-rw-r--r-- | src/common/compat.h | 14 | ||||
-rw-r--r-- | src/common/util.c | 91 | ||||
-rw-r--r-- | src/common/util.h | 10 |
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); |