X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=site.c;h=1d8c77788d532968f8cae245450fa16e2be46f3f;hb=1a448682f9a56b3e33e24fc07767a07e40feaec7;hp=e6c34c8dffdaccc5edb042304fa91115e9cc1d6a;hpb=e001e8c056deecfdd295638262a9d61ca9995e23;p=secnet.git diff --git a/site.c b/site.c index e6c34c8..1d8c777 100644 --- a/site.c +++ b/site.c @@ -234,6 +234,7 @@ struct site { string_t tunname; /* localname<->remotename by default, used in logs */ string_t address; /* DNS name for bootstrapping, optional */ int remoteport; /* Port for bootstrapping, optional */ + uint32_t mtu_target; struct netlink_if *netlink; struct comm_if **comms; int ncomms; @@ -282,6 +283,7 @@ struct site { timeout before we can listen for another setup packet); perhaps we should keep a list of 'bad' sources for setup packets. */ uint32_t remote_capabilities; + uint16_t remote_adv_mtu; struct transform_if *chosen_transform; uint32_t setup_session_id; transport_peers setup_peers; @@ -297,35 +299,57 @@ struct site { struct transform_inst_if *new_transform; /* For key setup/verify */ }; +static uint32_t event_log_priority(struct site *st, uint32_t event) +{ + if (!(event&st->log_events)) + return 0; + switch(event) { + case LOG_UNEXPECTED: return M_INFO; + case LOG_SETUP_INIT: return M_INFO; + case LOG_SETUP_TIMEOUT: return M_NOTICE; + case LOG_ACTIVATE_KEY: return M_INFO; + case LOG_TIMEOUT_KEY: return M_INFO; + case LOG_SEC: return M_SECURITY; + case LOG_STATE: return M_DEBUG; + case LOG_DROP: return M_DEBUG; + case LOG_DUMP: return M_DEBUG; + case LOG_ERROR: return M_ERR; + case LOG_PEER_ADDRS: return M_DEBUG; + default: return M_ERR; + } +} + +static void vslog(struct site *st, uint32_t event, cstring_t msg, va_list ap) +FORMAT(printf,3,0); +static void vslog(struct site *st, uint32_t event, cstring_t msg, va_list ap) +{ + uint32_t class; + + class=event_log_priority(st, event); + if (class) { + slilog_part(st->log,class,"%s: ",st->tunname); + vslilog_part(st->log,class,msg,ap); + slilog_part(st->log,class,"\n"); + } +} + static void slog(struct site *st, uint32_t event, cstring_t msg, ...) FORMAT(printf,3,4); static void slog(struct site *st, uint32_t event, cstring_t msg, ...) { va_list ap; - char buf[240]; - uint32_t class; - va_start(ap,msg); + vslog(st,event,msg,ap); + va_end(ap); +} - if (event&st->log_events) { - switch(event) { - case LOG_UNEXPECTED: class=M_INFO; break; - case LOG_SETUP_INIT: class=M_INFO; break; - case LOG_SETUP_TIMEOUT: class=M_NOTICE; break; - case LOG_ACTIVATE_KEY: class=M_INFO; break; - case LOG_TIMEOUT_KEY: class=M_INFO; break; - case LOG_SEC: class=M_SECURITY; break; - case LOG_STATE: class=M_DEBUG; break; - case LOG_DROP: class=M_DEBUG; break; - case LOG_DUMP: class=M_DEBUG; break; - case LOG_ERROR: class=M_ERR; break; - case LOG_PEER_ADDRS: class=M_DEBUG; break; - default: class=M_ERR; break; - } - - vsnprintf(buf,sizeof(buf),msg,ap); - slilog(st->log,class,"%s: %s",st->tunname,buf); - } +static void logtimeout(struct site *st, const char *fmt, ...) +FORMAT(printf,2,3); +static void logtimeout(struct site *st, const char *fmt, ...) +{ + va_list ap; + va_start(ap,fmt); + vslog(st,LOG_SETUP_TIMEOUT,fmt,ap); va_end(ap); } @@ -386,6 +410,14 @@ static void dispose_transform(struct transform_inst_if **transform_var) type=buf_unprepend_uint32((b)); \ if (type!=(t)) return False; } while(0) +static _Bool type_is_msg34(uint32_t type) +{ + return + type == LABEL_MSG3 || + type == LABEL_MSG3BIS || + type == LABEL_MSG4; +} + struct parsedname { int32_t len; uint8_t *name; @@ -399,6 +431,7 @@ struct msg { struct parsedname remote; struct parsedname local; uint32_t remote_capabilities; + uint16_t remote_mtu; int capab_transformnum; uint8_t *nR; uint8_t *nL; @@ -487,6 +520,9 @@ static bool_t generate_msg(struct site *st, uint32_t type, cstring_t what) if ((st->local_capabilities & CAPAB_EARLY) || (type != LABEL_MSG1)) { buf_append_uint32(&st->buffer,st->local_capabilities); } + if (type_is_msg34(type)) { + buf_append_uint16(&st->buffer,st->mtu_target); + } append_string_xinfo_done(&st->buffer,&xia); buf_append_string(&st->buffer,st->remotename); @@ -542,10 +578,15 @@ static bool_t unpick_msg(struct site *st, uint32_t type, CHECK_TYPE(msg,type); if (!unpick_name(msg,&m->remote)) return False; m->remote_capabilities=0; + m->remote_mtu=0; if (m->remote.extrainfo.size) { CHECK_AVAIL(&m->remote.extrainfo,4); m->remote_capabilities=buf_unprepend_uint32(&m->remote.extrainfo); } + if (type_is_msg34(type) && m->remote.extrainfo.size) { + CHECK_AVAIL(&m->remote.extrainfo,2); + m->remote_mtu=buf_unprepend_uint16(&m->remote.extrainfo); + } if (!unpick_name(msg,&m->local)) return False; if (type==LABEL_PROD) { CHECK_EMPTY(msg); @@ -722,6 +763,8 @@ static bool_t process_msg3_msg4(struct site *st, struct msg *m) } free(hash); + st->remote_adv_mtu=m->remote_mtu; + return True; } @@ -1056,7 +1099,7 @@ static bool_t send_msg(struct site *st) st->retries--; return True; } else if (st->state==SITE_SENTMSG5) { - slog(st,LOG_SETUP_TIMEOUT,"timed out sending MSG5, stashing new key"); + logtimeout(st,"timed out sending MSG5, stashing new key"); /* We stash the key we have produced, in case it turns out that * our peer did see our MSG5 after all and starts using it. */ /* This is a bit like some of activate_new_key */ @@ -1074,7 +1117,7 @@ static bool_t send_msg(struct site *st) enter_state_wait(st); return False; } else { - slog(st,LOG_SETUP_TIMEOUT,"timed out sending key setup packet " + logtimeout(st,"timed out sending key setup packet " "(in state %s)",state_name(st->state)); enter_state_wait(st); return False; @@ -1145,7 +1188,15 @@ static void activate_new_key(struct site *st) transport_peers_copy(st,&st->peers,&st->setup_peers); st->current.remote_session_id=st->setup_session_id; - slog(st,LOG_ACTIVATE_KEY,"new key activated"); + /* Compute the inter-site MTU. This is min( our_mtu, their_mtu ). + * But their mtu be unspecified, in which case we just use ours. */ + uint32_t intersite_mtu= + MIN(st->mtu_target, st->remote_adv_mtu ?: ~(uint32_t)0); + st->netlink->set_mtu(st->netlink->st,intersite_mtu); + + slog(st,LOG_ACTIVATE_KEY,"new key activated" + " (mtu ours=%"PRId32" theirs=%"PRId32" intersite=%"PRId32")", + st->mtu_target, st->remote_adv_mtu, intersite_mtu); enter_state_run(st); } @@ -1765,6 +1816,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->setup_retries= CFG_NUMBER("setup-retries", SETUP_RETRIES); st->setup_retry_interval= CFG_NUMBER("setup-timeout", SETUP_RETRY_INTERVAL); st->wait_timeout= CFG_NUMBER("wait-time", WAIT_TIME); + st->mtu_target= dict_read_number(dict,"mtu-target",False,"site",loc,0); st->mobile_peer_expiry= dict_read_number( dict,"mobile-peer-expiry",False,"site",loc,DEFAULT_MOBILE_PEER_EXPIRY); @@ -1833,7 +1885,10 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, } /* We need to register the remote networks with the netlink device */ - st->netlink->reg(st->netlink->st, site_outgoing, st, 0); + uint32_t netlink_mtu; /* local virtual interface mtu */ + st->netlink->reg(st->netlink->st, site_outgoing, st, &netlink_mtu); + if (!st->mtu_target) + st->mtu_target=netlink_mtu; for (i=0; incomms; i++) st->comms[i]->request_notify(st->comms[i]->st, st, site_incoming); @@ -1878,14 +1933,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); } } @@ -1922,7 +1977,7 @@ static void transport_record_peer(struct site *st, transport_peers *peers, changed=1; if (peers->npeers==st->transport_peers_max) - slot=st->transport_peers_max; + slot=st->transport_peers_max-1; else slot=peers->npeers++;