X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=site.c;h=b04f3b340b91f9e90057636c9f6ba1b347d4f850;hb=0391d9ee80a1847381ad205b8f707e43707b90b0;hp=1af21ea91f8351b262622d50a2d274abe44d799b;hpb=4f3c75ac833ae611c37db7911aecd2873a20ed41;p=secnet.git diff --git a/site.c b/site.c index 1af21ea..b04f3b3 100644 --- a/site.c +++ b/site.c @@ -229,7 +229,7 @@ struct site { /* configuration information */ string_t localname; string_t remotename; - bool_t peer_mobile; /* Mobile client support */ + bool_t local_mobile, peer_mobile; /* Mobile client support */ int32_t transport_peers_max; string_t tunname; /* localname<->remotename by default, used in logs */ string_t address; /* DNS name for bootstrapping, optional */ @@ -267,6 +267,7 @@ struct site { uint32_t state; uint64_t now; /* Most recently seen time */ bool_t allow_send_prod; + bool_t resolving; /* The currently established session */ struct data_key current; @@ -347,9 +348,27 @@ static void logtimeout(struct site *st, const char *fmt, ...) FORMAT(printf,2,3); static void logtimeout(struct site *st, const char *fmt, ...) { + uint32_t class=event_log_priority(st,LOG_SETUP_TIMEOUT); + if (!class) + return; + va_list ap; va_start(ap,fmt); - vslog(st,LOG_SETUP_TIMEOUT,fmt,ap); + + slilog_part(st->log,class,"%s: ",st->tunname); + vslilog_part(st->log,class,fmt,ap); + + const char *delim; + int i; + for (i=0, delim=" (tried "; + isetup_peers.npeers; + i++, delim=", ") { + transport_peer *peer=&st->setup_peers.peers[i]; + const char *s=comm_addr_to_string(&peer->addr); + slilog_part(st->log,class,"%s%s",delim,s); + } + + slilog_part(st->log,class,")\n"); va_end(ap); } @@ -1129,6 +1148,8 @@ static void site_resolve_callback(void *sst, struct in_addr *address) struct site *st=sst; struct comm_addr ca_buf, *ca_use; + st->resolving=False; + if (st->state!=SITE_RESOLVE) { slog(st,LOG_UNEXPECTED,"site_resolve_callback called unexpectedly"); return; @@ -1156,6 +1177,7 @@ static void site_resolve_callback(void *sst, struct in_addr *address) static bool_t initiate_key_setup(struct site *st, cstring_t reason, const struct comm_addr *prod_hint) { + /* Reentrancy hazard: can call enter_new_state/enter_state_* */ if (st->state!=SITE_RUN) return False; slog(st,LOG_SETUP_INIT,"initiating key exchange (%s)",reason); if (st->address) { @@ -1266,14 +1288,33 @@ static void enter_state_run(struct site *st) set_link_quality(st); } +static bool_t ensure_resolving(struct site *st) +{ + /* Reentrancy hazard: may call site_resolve_callback and hence + * enter_new_state, enter_state_* and generate_msg*. */ + if (st->resolving) + return True; + + /* resolver->request might reentrantly call site_resolve_callback + * which will clear st->resolving, so we need to set it beforehand + * rather than afterwards; also, it might return False, in which + * case we have to clear ->resolving again. */ + st->resolving=True; + bool_t ok = st->resolver->request(st->resolver->st,st->address, + site_resolve_callback,st); + if (!ok) + st->resolving=False; + + return ok; +} + static bool_t enter_state_resolve(struct site *st) { + /* Reentrancy hazard! See ensure_resolving. */ state_assert(st,st->state==SITE_RUN); slog(st,LOG_STATE,"entering state RESOLVE"); st->state=SITE_RESOLVE; - st->resolver->request(st->resolver->st,st->address, - site_resolve_callback,st); - return True; + return ensure_resolving(st); } static bool_t enter_new_state(struct site *st, uint32_t next) @@ -1744,7 +1785,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->remotename=dict_read_string(dict, "name", True, "site", loc); st->peer_mobile=dict_read_bool(dict,"mobile",False,"site",loc,False); - bool_t local_mobile= + st->local_mobile= dict_read_bool(dict,"local-mobile",False,"site",loc,False); /* Sanity check (which also allows the 'sites' file to include @@ -1753,14 +1794,14 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, if (strcmp(st->localname,st->remotename)==0) { Message(M_DEBUG,"site %s: local-name==name -> ignoring this site\n", st->localname); - if (st->peer_mobile != local_mobile) + if (st->peer_mobile != st->local_mobile) cfgfatal(loc,"site","site %s's peer-mobile=%d" " but our local-mobile=%d\n", - st->localname, st->peer_mobile, local_mobile); + st->localname, st->peer_mobile, st->local_mobile); free(st); return NULL; } - if (st->peer_mobile && local_mobile) { + if (st->peer_mobile && st->local_mobile) { Message(M_WARNING,"site %s: site is mobile but so are we" " -> ignoring this site\n", st->remotename); free(st); @@ -1808,7 +1849,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->dh=find_cl_if(dict,"dh",CL_DH,True,"site",loc); st->hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc); -#define DEFAULT(D) (st->peer_mobile || local_mobile \ +#define DEFAULT(D) (st->peer_mobile || st->local_mobile \ ? DEFAULT_MOBILE_##D : DEFAULT_##D) #define CFG_NUMBER(k,D) dict_read_number(dict,(k),False,"site",loc,DEFAULT(D)); @@ -1843,6 +1884,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->log_events=string_list_to_word(dict_lookup(dict,"log-events"), log_event_table,"site"); + st->resolving=False; st->allow_send_prod=0; st->tunname=safe_malloc(strlen(st->localname)+strlen(st->remotename)+5, @@ -1933,14 +1975,14 @@ static void transport_peers_debug(struct site *st, transport_peers *dst, i++, (argp+=stride?stride:sizeof(*args))) { const struct comm_addr *ca=(void*)argp; slog(st, LOG_PEER_ADDRS, " args: addrs[%d]=%s", - i, ca->comm->addr_to_string(ca->comm->st,ca)); + i, comm_addr_to_string(ca)); } for (i=0; inpeers; i++) { struct timeval diff; timersub(tv_now,&dst->peers[i].last,&diff); const struct comm_addr *ca=&dst->peers[i].addr; slog(st, LOG_PEER_ADDRS, " peers: addrs[%d]=%s T-%ld.%06ld", - i, ca->comm->addr_to_string(ca->comm->st,ca), + i, comm_addr_to_string(ca), (unsigned long)diff.tv_sec, (unsigned long)diff.tv_usec); } } @@ -2008,7 +2050,7 @@ static bool_t transport_compute_setupinit_peers(struct site *st, prod_hint_addr ? " PROD hint address;" : "", st->peers.npeers); - /* Non-mobile peers havve st->peers.npeers==0 or ==1, since they + /* Non-mobile peers have st->peers.npeers==0 or ==1, since they * have transport_peers_max==1. The effect is that this code * always uses the configured address if supplied, or otherwise * the address of the incoming PROD, or the existing data peer if