From 5f8e2c2bc42239e9347ef70f3775c0d4ad378e1c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 2 Mar 2005 21:02:11 +0000 Subject: [PATCH] Rename unused-address functions to virtual address; this is more accurate. Also, include almost-right implementation of reusing dont-care mappings. (It is still kind of wrong because it does not take type into account.) svn:r3728 --- doc/TODO | 7 +++-- src/or/connection_edge.c | 63 +++++++++++++++++++++++++++++++++++----- src/or/control.c | 7 +++-- src/or/or.h | 2 +- 4 files changed, 64 insertions(+), 15 deletions(-) diff --git a/doc/TODO b/doc/TODO index c62e89ed43..b07340d940 100644 --- a/doc/TODO +++ b/doc/TODO @@ -56,12 +56,13 @@ N . Implement pending controller features. o Need to remember descriptors for all routers. o Replace everything else that remembers serverdescs with routerinfo. - - List of address mappings (all, or mapaddress+config, - or just mapadddress?) + - List of address mappings o POSTDESCRIPTOR - o MAPADDRESS + . MAPADDRESS o Map A->B. o Map DontCare->B. + o Reuse mappings when asked to map DontCare->B for the same B. + - But only when the DontCare is of the same type. :/ o Way to handle overlong messages o Specify fragmented format o Implement fragmented format diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 52619e392f..2d9018d9a2 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -18,6 +18,7 @@ static addr_policy_t *socks_policy = NULL; static smartlist_t *redirect_exit_list = NULL; static int connection_ap_handshake_process_socks(connection_t *conn); +static int address_is_in_virtual_range(const char *addr); /** There was an EOF. Send an end and mark the connection for close. */ @@ -365,10 +366,13 @@ typedef struct { /** The tree of client-side address rewrite instructions. */ static strmap_t *addressmap; +/** Tree mapping addresses to which virtual address we assigned them to. */ +static strmap_t *virtaddress_reversemap; /** Initialize addressmap. */ void addressmap_init(void) { addressmap = strmap_new(); + virtaddress_reversemap = strmap_new(); } /** Free the memory associated with the addressmap entry _ent. */ @@ -379,6 +383,20 @@ addressmap_ent_free(void *_ent) { tor_free(ent); } +static void +addressmap_ent_remove(const char *addr, addressmap_entry_t *ent) +{ + if (ent && address_is_in_virtual_range(ent->new_address)) { + if (!strcasecmp(addr, + strmap_get(virtaddress_reversemap, ent->new_address))) { + char *a = strmap_remove(virtaddress_reversemap, ent->new_address); + tor_free(a); + } + } + addressmap_ent_free(ent); +} + + /** A helper function for addressmap_clean() below. If ent is too old, * then remove it from the tree and return NULL, else return ent. */ @@ -389,7 +407,7 @@ _addressmap_remove_if_expired(const char *addr, if (ent->expires && ent->expires < *nowp) { log(LOG_INFO, "Addressmap: expiring remap (%s to %s)", addr, ent->new_address); - addressmap_ent_free(ent); + addressmap_ent_remove(addr,ent); return NULL; } else { return ent; @@ -409,6 +427,7 @@ void addressmap_clean(time_t now) { void addressmap_free_all(void) { strmap_free(addressmap, addressmap_ent_free); addressmap = NULL; + strmap_free(virtaddress_reversemap, free); } /** Look at address, and rewrite it until it doesn't want any @@ -458,15 +477,21 @@ void addressmap_register(const char *address, char *new_address, time_t expires) return; } if (!new_address || !strcasecmp(address,new_address)) { + /* Remove the mapping, if any. */ tor_free(new_address); - /* Remove the old mapping, if any. */ if (ent) { - addressmap_ent_free(ent); + addressmap_ent_remove(address,ent); strmap_remove(addressmap, address); } return; } if (ent) { /* we'll replace it */ + if (address_is_in_virtual_range(ent->new_address) && + !strcasecmp(address, + strmap_get(virtaddress_reversemap, ent->new_address))) { + char *a = strmap_remove(virtaddress_reversemap, ent->new_address); + tor_free(a); + } tor_free(ent->new_address); } else { /* make a new one and register it */ ent = tor_malloc_zero(sizeof(addressmap_entry_t)); @@ -546,10 +571,10 @@ void client_dns_set_addressmap(const char *address, uint32_t val, const char *ex /** * Return true iff addr is likely to have been returned by - * client_dns_get_unmapped_address. + * client_dns_get_unused_address. **/ static int -address_is_in_unmapped_range(const char *addr) +address_is_in_virtual_range(const char *addr) { struct in_addr in; tor_assert(addr); @@ -567,8 +592,8 @@ address_is_in_unmapped_range(const char *addr) * (one of RESOLVED_TYPE_{IPV4|HOSTNAME}) that has not yet been mapped, * and that is very unlikely to be the address of any real host. */ -char * -client_dns_get_unmapped_address(int type) +static char * +addressmap_get_virtual_address(int type) { char buf[64]; static uint32_t next_ipv4 = MIN_UNUSED_IPV4; @@ -605,6 +630,28 @@ client_dns_get_unmapped_address(int type) } } +/* DOCDOC */ +char * +addressmap_register_virtual_address(int type, char *new_address) +{ + char *addr; + tor_assert(new_address); + + if ((addr = strmap_get(virtaddress_reversemap, new_address))) { + addressmap_entry_t *ent = strmap_get(addressmap, addr); + if (!strcasecmp(new_address, ent->new_address)) + return tor_strdup(addr); + else + log_fn(LOG_WARN, "Internal confusion: I thought that '%s' was mapped to by '%s', but '%s' really maps to '%s'. This is a harmless bug.", + new_address, addr, addr, ent->new_address); + } + + addr = addressmap_get_virtual_address(type); + strmap_set(virtaddress_reversemap, new_address, tor_strdup(addr)); + addressmap_register(addr, new_address, 0); + return addr; +} + /** Return 1 if address has funny characters in it like * colons. Return 0 if it's fine. */ @@ -664,7 +711,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) { /* For address map controls, remap the address */ addressmap_rewrite(socks->address, sizeof(socks->address)); - if (address_is_in_unmapped_range(socks->address)) { + if (address_is_in_virtual_range(socks->address)) { /* This address was probably handed out by client_dns_get_unmapped_address, * but the mapping was discarded for some reason. We *don't* want to send * the address through tor; that's likely to fail, and may leak diff --git a/src/or/control.c b/src/or/control.c index 4714e8ee7a..789cdc8898 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -496,8 +496,9 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body) } else if (!is_plausible_address(to)) { log_fn(LOG_WARN,"Skipping invalid argument '%s' in AddressMap msg",to); } else if (!strcmp(from, ".") || !strcmp(from, "0.0.0.0")) { - char *addr = client_dns_get_unmapped_address( - strcmp(from,".") ? RESOLVED_TYPE_HOSTNAME : RESOLVED_TYPE_IPV4); + char *addr = addressmap_register_virtual_address( + strcmp(from,".") ? RESOLVED_TYPE_HOSTNAME : RESOLVED_TYPE_IPV4, + tor_strdup(to)); if (!addr) { log_fn(LOG_WARN, "Unable to allocate address for '%s' in AdressMap msg", line); @@ -505,7 +506,7 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body) size_t anslen = strlen(addr)+strlen(to)+2; char *ans = tor_malloc(anslen); tor_snprintf(ans, anslen, "%s %s", addr, to); - addressmap_register(addr, tor_strdup(to), 0); + tor_free(addr); smartlist_add(reply, ans); } } else { diff --git a/src/or/or.h b/src/or/or.h index f01b6b31cf..9b86307c56 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1319,7 +1319,7 @@ int addressmap_already_mapped(const char *address); void addressmap_register(const char *address, char *new_address, time_t expires); int client_dns_incr_failures(const char *address); void client_dns_set_addressmap(const char *address, uint32_t val, const char *exitname); -char *client_dns_get_unmapped_address(int type); +char *addressmap_register_virtual_address(int type, char *new_address); void parse_socks_policy(void); void free_socks_policy(void);