diff --git a/configure.in b/configure.in index e27924d635..1abc6b1428 100644 --- a/configure.in +++ b/configure.in @@ -181,6 +181,7 @@ AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) AC_CHECK_SIZEOF(__int64) AC_CHECK_SIZEOF(void *) +AC_CHECK_SIZEOF(time_t) # We want to make sure that we _don't_ have a cell_t defined, like IRIX does. diff --git a/doc/TODO b/doc/TODO index 2395fe348a..68cd475d17 100644 --- a/doc/TODO +++ b/doc/TODO @@ -49,20 +49,20 @@ R o Reset uptime when IP changes. Functionality N . Implement pending controller features. o Stubs for new functions. - . GETINFO + o GETINFO o Version o Descriptor list o Individual descriptors o Need to remember descriptors for all routers. o Replace everything else that remembers serverdescs with routerinfo. - - List of address mappings + o List of address mappings o POSTDESCRIPTOR - . MAPADDRESS + o 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 But only when the DontCare is of the same type. :/ o Way to handle overlong messages o Specify fragmented format o Implement fragmented format @@ -70,8 +70,9 @@ N . Implement pending controller features. o Better stream IDs o Stream status changed: "new" state. - EXTENDCIRCUIT - - ATTACHSTREAM - - Make streams have an 'unattached and unattachable' state. + - ATTACHSTREAM + - Make streams have an 'unattached and not-automatically-attachable' + state. - Add support to put new streams into this state rather than try to attach them automatically. ("Hidden" config option.) - Time out never-attached streams. diff --git a/src/common/torint.h b/src/common/torint.h index 75e45239c8..84f6b28dfa 100644 --- a/src/common/torint.h +++ b/src/common/torint.h @@ -235,6 +235,16 @@ typedef uint32_t uintptr_t; #endif #endif +#ifndef TIME_MAX +#if (SIZEOF_TIME_T == 4) +#define TIME_MAX ((time_t)UINT32_MAX) +#elif (SIZEOF_TIME_T == 8) +#define TIME_MAX ((time_t)UINT64_MAX) +#else +#error "Can't define TIME_MAX" +#endif +#endif + /* Any size_t larger than this amount is likely to be an underflow. */ #define SIZE_T_CEILING (sizeof(char)<<(sizeof(size_t)*8 - 1)) diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 7aea8ce2dc..87487b3181 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -356,7 +356,11 @@ void connection_ap_attach_pending(void) * When an addressmap request is made but one is already registered, * the new one is replaced only if the currently registered one has * no "new_address" (that is, it's in the process of dns resolve), - * or if the new one is permanent (expires==0). + * or if the new one is permanent (expires==0 or 1). + * + * (We overload the 'expires' field, using "0" for mappings set via + * the configuration file, "1" for mappings set from the control + * interface, and other values for DNS mappings that can expire.) */ typedef struct { char *new_address; @@ -438,7 +442,7 @@ static void * _addressmap_remove_if_expired(const char *addr, addressmap_entry_t *ent, time_t *nowp) { - if (ent->expires && ent->expires < *nowp) { + if (ent->expires > 1 && ent->expires < *nowp) { log(LOG_INFO, "Addressmap: expiring remap (%s to %s)", addr, ent->new_address); addressmap_ent_remove(addr,ent); @@ -493,7 +497,8 @@ int addressmap_already_mapped(const char *address) { } /** Register a request to map address to new_address, - * which will expire on expires (or 0 if never expires). + * which will expire on expires (or 0 if never expires from config + * file, 1 if never expires from controller). * * new_address should be a newly dup'ed string, which we'll use or * free as appropriate. We will leave address alone. @@ -505,7 +510,7 @@ void addressmap_register(const char *address, char *new_address, time_t expires) addressmap_entry_t *ent; ent = strmap_get(addressmap, address); - if (ent && ent->new_address && expires) { + if (ent && ent->new_address && expires>1) { log_fn(LOG_INFO,"Addressmap ('%s' to '%s') not performed, since it's already mapped to '%s'", address, new_address, ent->new_address); tor_free(new_address); return; @@ -688,7 +693,7 @@ addressmap_register_virtual_address(int type, char *new_address) tor_free(*addrp); *addrp = addressmap_get_virtual_address(type); strmap_set(virtaddress_reversemap, new_address, tor_strdup(*addrp)); - addressmap_register(*addrp, new_address, 0); + addressmap_register(*addrp, new_address, 1); return *addrp; } @@ -703,6 +708,30 @@ address_is_invalid_destination(const char *address) { return 0; } +/* DOCDOC */ +void +addressmap_get_mappings(smartlist_t *sl, time_t min_expires, time_t max_expires) +{ + strmap_iter_t *iter; + const char *key; + void *_val; + addressmap_entry_t *val; + + tor_assert(sl); + + for (iter = strmap_iter_init(addressmap); !strmap_iter_done(iter); + iter = strmap_iter_next(addressmap,iter)) { + strmap_iter_get(iter, &key, &_val); + val = _val; + if (val->expires >= min_expires && val->expires <= max_expires) { + size_t len = strlen(key)+strlen(val->new_address)+2; + char *line = tor_malloc(len); + tor_snprintf(line, len, "%s %s", key, val->new_address); + smartlist_add(sl, line); + } + } +} + /** connection_edge_process_inbuf() found a conn in state * socks_wait. See if conn->inbuf has the right bytes to proceed with * the socks handshake. diff --git a/src/or/control.c b/src/or/control.c index 4024fd4274..6b5c9bd1cb 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -487,7 +487,8 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body) SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); SMARTLIST_FOREACH(lines, const char *, line, { - smartlist_split_string(elts, body, " ", 0, 2); + tor_strlower(line); + smartlist_split_string(elts, line, " ", 0, 2); if (smartlist_len(elts) == 2) { const char *from = smartlist_get(elts,0); const char *to = smartlist_get(elts,1); @@ -510,7 +511,7 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body) smartlist_add(reply, ans); } } else { - addressmap_register(from, tor_strdup(to), 0); + addressmap_register(from, tor_strdup(to), 1); smartlist_add(reply, tor_strdup(line)); } } else { @@ -559,8 +560,27 @@ handle_getinfo_helper(const char *question) *cp++ = ','; }); return answer; - } else if (!strcmp(question, "addr-mappings")) { - return NULL; /* XXXX */ + } else if (!strcmpstart(question, "addr-mappings/")) { + time_t min_e, max_e; + smartlist_t *mappings; + char *answer; + if (!strcmp(question, "addr-mappings/all")) { + min_e = 0; max_e = TIME_MAX; + } else if (!strcmp(question, "addr-mappings/cache")) { + min_e = 2; max_e = TIME_MAX; + } else if (!strcmp(question, "addr-mappings/config")) { + min_e = 0; max_e = 0; + } else if (!strcmp(question, "addr-mappings/control")) { + min_e = 1; max_e = 1; + } else { + return NULL; + } + mappings = smartlist_create(); + addressmap_get_mappings(mappings, min_e, max_e); + answer = smartlist_join_strings(mappings, "\n", 1, NULL); + SMARTLIST_FOREACH(mappings, char *, cp, tor_free(cp)); + smartlist_free(mappings); + return answer; } else { /* unrecognized key */ return NULL; diff --git a/src/or/or.h b/src/or/or.h index 4622cfb196..a788bb65f7 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1320,6 +1320,7 @@ 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 *addressmap_register_virtual_address(int type, char *new_address); +void addressmap_get_mappings(smartlist_t *sl, time_t min_expires, time_t max_expires); void parse_socks_policy(void); void free_socks_policy(void);