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 | |
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
-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 | ||||
-rw-r--r-- | src/or/connection.c | 2 | ||||
-rw-r--r-- | src/or/connection_or.c | 2 | ||||
-rw-r--r-- | src/or/control.c | 2 | ||||
-rw-r--r-- | src/or/dirserv.c | 2 | ||||
-rw-r--r-- | src/or/dnsserv.c | 2 | ||||
-rw-r--r-- | src/or/or.h | 6 | ||||
-rw-r--r-- | src/or/policies.c | 59 | ||||
-rw-r--r-- | src/or/rendcommon.c | 2 | ||||
-rw-r--r-- | src/or/router.c | 4 | ||||
-rw-r--r-- | src/or/routerlist.c | 2 | ||||
-rw-r--r-- | src/or/routerparse.c | 53 | ||||
-rw-r--r-- | src/or/test.c | 9 |
16 files changed, 200 insertions, 76 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); diff --git a/src/or/connection.c b/src/or/connection.c index 002d10a03e..8c7cca1ba9 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1036,7 +1036,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) /* remember the remote address */ newconn->addr = ntohl(remote.sin_addr.s_addr); newconn->port = ntohs(remote.sin_port); - newconn->address = tor_dup_addr(newconn->addr); + newconn->address = tor_dup_ip(newconn->addr); } else if (conn->socket_family == AF_UNIX) { /* For now only control ports can be unix domain sockets diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 0ed957eb66..1c6c85bd1a 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -434,7 +434,7 @@ connection_or_init_conn_from_address(or_connection_t *conn, conn->identity_digest, DIGEST_LEN); } tor_free(conn->_base.address); - conn->_base.address = tor_dup_addr(addr); + conn->_base.address = tor_dup_ip(addr); } } diff --git a/src/or/control.c b/src/or/control.c index 06902bcd87..aaf4701a15 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1382,7 +1382,7 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, uint32_t addr; if (router_pick_published_address(get_options(), &addr) < 0) return -1; - *answer = tor_dup_addr(addr); + *answer = tor_dup_ip(addr); } else if (!strcmp(question, "dir-usage")) { *answer = directory_dump_request_log(); } else if (!strcmp(question, "fingerprint")) { diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 04544d7f49..df3a913a13 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2165,7 +2165,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, } if (!strchr(hostname, '.')) { tor_free(hostname); - hostname = tor_dup_addr(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"); diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index c88193e15a..18623f6a49 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -118,7 +118,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) TO_CONN(conn)->addr = ntohl(sin->sin_addr.s_addr); TO_CONN(conn)->port = ntohs(sin->sin_port); - TO_CONN(conn)->address = tor_dup_addr(TO_CONN(conn)->addr); + TO_CONN(conn)->address = tor_dup_ip(TO_CONN(conn)->addr); if (q->type == EVDNS_TYPE_A) conn->socks_request->command = SOCKS_COMMAND_RESOLVE; diff --git a/src/or/or.h b/src/or/or.h index 6975b16fd6..342a57022d 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1148,8 +1148,7 @@ typedef struct addr_policy_t { maskbits_t maskbits; /**< Accept/reject all addresses <b>a</b> such that the * first <b>maskbits</b> bits of <b>a</b> match * <b>addr</b>. */ - /* XXXX_IP6 make this ipv6-capable */ - uint32_t addr; /**< Base address to accept or reject. */ + tor_addr_t addr; /**< Base address to accept or reject. */ uint16_t prt_min; /**< Lowest port number to accept/reject. */ uint16_t prt_max; /**< Highest port number to accept/reject. */ } addr_policy_t; @@ -3635,7 +3634,8 @@ int exit_policy_is_general_exit(smartlist_t *policy); int policy_is_reject_star(smartlist_t *policy); int getinfo_helper_policies(control_connection_t *conn, const char *question, char **answer); -int policy_write_item(char *buf, size_t buflen, addr_policy_t *item); +int policy_write_item(char *buf, size_t buflen, addr_policy_t *item, + int format_for_desc); void addr_policy_list_free(smartlist_t *p); void addr_policy_free(addr_policy_t *p); diff --git a/src/or/policies.c b/src/or/policies.c index 06ca6cdded..fb5c0d56be 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -45,7 +45,9 @@ policy_expand_private(smartlist_t **policy) { static const char *private_nets[] = { "0.0.0.0/8", "169.254.0.0/16", - "127.0.0.0/8", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12", NULL }; + "127.0.0.0/8", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12", + // "fc00::/7", "fe80::/10", "fec0::/10", "::/127", + NULL }; uint16_t port_min, port_max; int i; @@ -67,9 +69,8 @@ policy_expand_private(smartlist_t **policy) memcpy(&policy, p, sizeof(addr_policy_t)); policy.is_private = 0; policy.is_canonical = 0; - if (parse_addr_and_port_range(private_nets[i], - &policy.addr, - &policy.maskbits, &port_min, &port_max)) { + if (tor_addr_parse_mask_ports(private_nets[i], &policy.addr, + &policy.maskbits, &port_min, &port_max)<0) { tor_assert(0); } smartlist_add(tmp, addr_policy_get_canonical_entry(&policy)); @@ -408,7 +409,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=((int)a->addr - (int)b->addr))) + if ((r=tor_addr_compare(&a->addr, &b->addr))) return r; if ((r=((int)a->maskbits - (int)b->maskbits))) return r; @@ -464,7 +465,7 @@ policy_hash(policy_map_ent_t *ent) if (a->is_private) r = 0x1234abcd; else - r = (unsigned int)a->addr; + r = tor_addr_hash(&a->addr); r += a->prt_min << 8; r += a->prt_max << 16; r += a->maskbits; @@ -522,7 +523,7 @@ addr_policy_get_canonical_entry(addr_policy_t *e) * addresses (127.0.0.1, and so on). But we'll try this for now. */ addr_policy_result_t -compare_addr_to_addr_policy(uint32_t addr, uint16_t port, +compare_addr_to_addr_policy(uint32_t _addr, uint16_t port, smartlist_t *policy) { int maybe_reject = 0; @@ -530,13 +531,18 @@ compare_addr_to_addr_policy(uint32_t addr, uint16_t port, int match = 0; int maybe = 0; int i, len; + int addr_is_unknown; + tor_addr_t addr; + /*XXXX021 ipv6 this function should take a tor_addr_t, not a uint32_t. */ + tor_addr_from_ipv4h(&addr, _addr); + addr_is_unknown = tor_addr_is_null(&addr); len = policy ? smartlist_len(policy) : 0; for (i = 0; i < len; ++i) { addr_policy_t *tmpe = smartlist_get(policy, i); maybe = 0; - if (!addr) { + if (addr_is_unknown) { /* Address is unknown. */ if ((port >= tmpe->prt_min && port <= tmpe->prt_max) || (!port && tmpe->prt_min<=1 && tmpe->prt_max>=65535)) { @@ -552,7 +558,7 @@ compare_addr_to_addr_policy(uint32_t addr, uint16_t port, } } else { /* Address is known */ - if (!addr_mask_cmp_bits(addr, tmpe->addr, tmpe->maskbits)) { + if (!tor_addr_compare_masked(&addr, &tmpe->addr, tmpe->maskbits)) { if (port >= tmpe->prt_min && port <= tmpe->prt_max) { /* Exact match for the policy */ match = 1; @@ -595,7 +601,7 @@ addr_policy_covers(addr_policy_t *a, addr_policy_t *b) /* a has more fixed bits than b; it can't possibly cover b. */ return 0; } - if (addr_mask_cmp_bits(a->addr, b->addr, a->maskbits)) { + if (tor_addr_compare_masked(&a->addr, &b->addr, a->maskbits)) { /* There's a fixed bit in a that's set differently in b. */ return 0; } @@ -618,7 +624,7 @@ addr_policy_intersects(addr_policy_t *a, addr_policy_t *b) minbits = a->maskbits; else minbits = b->maskbits; - if (addr_mask_cmp_bits(a->addr, b->addr, minbits)) + if (tor_addr_compare_masked(&a->addr, &b->addr, minbits)) return 0; if (a->prt_max < b->prt_min || b->prt_max < a->prt_min) return 0; @@ -670,8 +676,8 @@ exit_policy_remove_redundancies(smartlist_t *dest) tor_assert(j > i); if (addr_policy_covers(ap, tmp)) { char p1[POLICY_BUF_LEN], p2[POLICY_BUF_LEN]; - policy_write_item(p1, sizeof(p1), tmp); - policy_write_item(p2, sizeof(p2), ap); + policy_write_item(p1, sizeof(p1), tmp, 0); + policy_write_item(p2, sizeof(p2), ap, 0); log(LOG_DEBUG, LD_CONFIG, "Removing exit policy %s (%d). It is made " "redundant by %s (%d).", p1, j, p2, i); smartlist_del_keeporder(dest, j--); @@ -699,8 +705,8 @@ exit_policy_remove_redundancies(smartlist_t *dest) } else { /* policy_types are equal. */ if (addr_policy_covers(tmp, ap)) { char p1[POLICY_BUF_LEN], p2[POLICY_BUF_LEN]; - policy_write_item(p1, sizeof(p1), ap); - policy_write_item(p2, sizeof(p2), tmp); + policy_write_item(p1, sizeof(p1), ap, 0); + policy_write_item(p2, sizeof(p2), tmp, 0); log(LOG_DEBUG, LD_CONFIG, "Removing exit policy %s. It is already " "covered by %s.", p1, p2); smartlist_del_keeporder(dest, i--); @@ -774,8 +780,8 @@ exit_policy_is_general_exit(smartlist_t *policy) continue; /* Doesn't cover our port. */ if (p->maskbits > 8) continue; /* Narrower than a /8. */ - if ((p->addr & 0xff000000ul) == 0x7f000000ul) - continue; /* 127.x */ + if (tor_addr_is_loopback(&p->addr)) + continue; /* 127.x or ::1. */ /* We have a match that is at least a /8. */ if (p->policy_type == ADDR_POLICY_ACCEPT) { ++n_allowed; @@ -807,16 +813,18 @@ policy_is_reject_star(smartlist_t *policy) /** Write a single address policy to the buf_len byte buffer at buf. Return * the number of characters written, or -1 on failure. */ int -policy_write_item(char *buf, size_t buflen, addr_policy_t *policy) +policy_write_item(char *buf, size_t buflen, addr_policy_t *policy, + int format_for_desc) { - struct in_addr in; size_t written = 0; - char addrbuf[INET_NTOA_BUF_LEN]; + char addrbuf[TOR_ADDR_BUF_LEN]; const char *addrpart; int result; + 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(buf, &policy->addr, sizeof(buf), 1); - in.s_addr = htonl(policy->addr); - tor_inet_ntoa(&in, addrbuf, sizeof(addrbuf)); /* write accept/reject 1.2.3.4 */ if (policy->is_private) addrpart = "private"; @@ -824,8 +832,11 @@ policy_write_item(char *buf, size_t buflen, addr_policy_t *policy) addrpart = "*"; else addrpart = addrbuf; - result = tor_snprintf(buf, buflen, "%s %s", - policy->policy_type == ADDR_POLICY_ACCEPT ? "accept" : "reject", + + result = tor_snprintf(buf, buflen, "%s%s%s %s", + (is_ip6&&format_for_desc)?"opt ":"", + is_accept ? "accept" : "reject", + (is_ip6&&format_for_desc)?"6":"", addrpart); if (result < 0) return -1; diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index e7ac4a1f0f..b9e2e81f0a 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -200,7 +200,7 @@ rend_encode_v2_intro_points(char **ipos_base64, goto done; } /* Assemble everything for this introduction point. */ - address = tor_dup_addr(info->addr); + address = tor_dup_ip(info->addr); res = tor_snprintf(unenc + unenc_written, unenc_len - unenc_written, "introduction-point %s\n" "ip-address %s\n" diff --git a/src/or/router.c b/src/or/router.c index 4cd02370af..bd8cb8351e 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1252,7 +1252,7 @@ router_rebuild_descriptor(int force) ri = tor_malloc_zero(sizeof(routerinfo_t)); ri->cache_info.routerlist_index = -1; - ri->address = tor_dup_addr(addr); + ri->address = tor_dup_ip(addr); ri->nickname = tor_strdup(options->Nickname); ri->addr = addr; ri->or_port = options->ORPort; @@ -1728,7 +1728,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, int i; for (i = 0; i < smartlist_len(router->exit_policy); ++i) { tmpe = smartlist_get(router->exit_policy, i); - result = policy_write_item(s+written, maxlen-written, tmpe); + result = policy_write_item(s+written, maxlen-written, tmpe, 1); if (result < 0) { log_warn(LD_BUG,"descriptor policy_write_item ran out of room!"); return -1; diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 896f0be4a1..c662aa2dc5 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -204,7 +204,7 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store, if (cert->addr && cert->dir_port && (ds->addr != cert->addr || ds->dir_port != cert->dir_port)) { - char *a = tor_dup_addr(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 in certificate.", ds->nickname, ds->address, (int)ds->dir_port, diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 6492d4baf7..811e276a73 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -23,9 +23,11 @@ const char routerparse_c_id[] = */ typedef enum { K_ACCEPT = 0, + K_ACCEPT6, K_DIRECTORY_SIGNATURE, K_RECOMMENDED_SOFTWARE, K_REJECT, + K_REJECT6, K_ROUTER, K_SIGNED_DIRECTORY, K_SIGNING_KEY, @@ -214,7 +216,9 @@ typedef struct token_rule_t { static token_rule_t routerdesc_token_table[] = { T0N("reject", K_REJECT, ARGS, NO_OBJ ), T0N("accept", K_ACCEPT, ARGS, NO_OBJ ), - T1_START( "router", K_ROUTER, GE(5), NO_OBJ ), + T0N("reject6", K_REJECT6, ARGS, NO_OBJ ), + T0N("accept6", K_ACCEPT6, ARGS, NO_OBJ ), + T1_START( "router", K_ROUTER, GE(5), NO_OBJ ), T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ), T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ), T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ), @@ -2607,12 +2611,12 @@ router_parse_addr_policy_item_from_string(const char *s, int assume_action) log_warn(LD_DIR, "Error reading address policy: %s", tok->error); goto err; } - if (tok->tp != K_ACCEPT && tok->tp != K_REJECT) { + if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 && + tok->tp != K_REJECT && tok->tp != K_REJECT6) { log_warn(LD_DIR, "Expected 'accept' or 'reject'."); goto err; } - /* Now that we've gotten an addr policy, add it to the router. */ r = router_parse_addr_policy(tok); goto done; err: @@ -2638,6 +2642,17 @@ router_add_exit_policy(routerinfo_t *router, directory_token_t *tok) if (! router->exit_policy) router->exit_policy = smartlist_create(); + if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) && + tor_addr_family(&newe->addr) == AF_INET) + || + ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) && + tor_addr_family(&newe->addr) == AF_INET6)) { + log_warn(LD_DIR, "Mismatch between field type and address type in exit " + "policy"); + addr_policy_free(newe); + return -1; + } + smartlist_add(router->exit_policy, newe); return 0; @@ -2651,7 +2666,8 @@ router_parse_addr_policy(directory_token_t *tok) addr_policy_t newe; char *arg; - tor_assert(tok->tp == K_REJECT || tok->tp == K_ACCEPT); + tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 || + tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6); if (tok->n_args != 1) return NULL; @@ -2662,18 +2678,18 @@ router_parse_addr_policy(directory_token_t *tok) memset(&newe, 0, sizeof(newe)); - newe.policy_type = (tok->tp == K_REJECT) ? ADDR_POLICY_REJECT - : ADDR_POLICY_ACCEPT; + if (tok->tp == K_REJECT || tok->tp == K_REJECT6) + newe.policy_type = ADDR_POLICY_REJECT; + else + newe.policy_type = ADDR_POLICY_ACCEPT; - if (parse_addr_and_port_range(arg, &newe.addr, &newe.maskbits, - &newe.prt_min, &newe.prt_max)) - goto policy_read_failed; + if (tor_addr_parse_mask_ports(arg, &newe.addr, &newe.maskbits, + &newe.prt_min, &newe.prt_max) < 0) { + log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg)); + return NULL; + } return addr_policy_get_canonical_entry(&newe); - -policy_read_failed: - log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg)); - return NULL; } /** Parse an exit policy line of the format "accept/reject private:...". @@ -2700,8 +2716,10 @@ router_parse_addr_policy_private(directory_token_t *tok) return NULL; memset(&result, 0, sizeof(result)); - result.policy_type = (tok->tp == K_REJECT) ? ADDR_POLICY_REJECT - : ADDR_POLICY_ACCEPT; + if (tok->tp == K_REJECT || tok->tp == K_REJECT6) + result.policy_type = ADDR_POLICY_REJECT; + else + result.policy_type = ADDR_POLICY_ACCEPT; result.is_private = 1; result.prt_min = port_min; result.prt_max = port_max; @@ -3076,8 +3094,9 @@ find_all_exitpolicy(smartlist_t *s) { smartlist_t *out = smartlist_create(); SMARTLIST_FOREACH(s, directory_token_t *, t, - if (t->tp == K_ACCEPT || t->tp == K_REJECT) - smartlist_add(out,t)); + if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 || + t->tp == K_REJECT || t->tp == K_REJECT6) + smartlist_add(out,t)); return out; } diff --git a/src/or/test.c b/src/or/test.c index 1b3e5c3b3e..71df85ad51 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -2519,11 +2519,11 @@ test_dir_format(void) ex1 = tor_malloc_zero(sizeof(addr_policy_t)); ex2 = tor_malloc_zero(sizeof(addr_policy_t)); ex1->policy_type = ADDR_POLICY_ACCEPT; - ex1->addr = 0; + tor_addr_from_ipv4h(&ex1->addr, 0); ex1->maskbits = 0; ex1->prt_min = ex1->prt_max = 80; ex2->policy_type = ADDR_POLICY_REJECT; - ex2->addr = 18 << 24; + tor_addr_from_ipv4h(&ex2->addr, 18<<24); ex2->maskbits = 8; ex2->prt_min = ex2->prt_max = 24; r2 = tor_malloc_zero(sizeof(routerinfo_t)); @@ -3279,9 +3279,10 @@ test_policies(void) policy = smartlist_create(); p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1); + test_assert(p != NULL); test_eq(ADDR_POLICY_REJECT, p->policy_type); - tor_addr_from_ipv4(&tar, 0xc0a80000u); - test_assert(p->addr == 0xc0a80000u); + tor_addr_from_ipv4h(&tar, 0xc0a80000u); + test_eq(0, tor_addr_compare(&p->addr, &tar)); test_eq(16, p->maskbits); test_eq(1, p->prt_min); test_eq(65535, p->prt_max); |