X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=site.c;h=f87328fda51fbb4cbf6482b30ac342e7fedd34a0;hb=dbe11c2091cfdb8f99f032a9ed81321b09c4094e;hp=00a3a4c9153a8477c1d56fb041f81abdde1261b0;hpb=1c085348edf120e964a6cdeff182faccfc8146d7;p=secnet.git diff --git a/site.c b/site.c index 00a3a4c..f87328f 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; @@ -386,6 +388,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 +409,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 +498,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 +556,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); @@ -703,12 +722,34 @@ static bool_t generate_msg3(struct site *st) "site:MSG3"); } +static bool_t process_msg3_msg4(struct site *st, struct msg *m) +{ + uint8_t *hash; + void *hst; + + /* Check signature and store g^x mod m */ + hash=safe_malloc(st->hash->len, "process_msg3_msg4"); + hst=st->hash->init(); + st->hash->update(hst,m->hashstart,m->hashlen); + st->hash->final(hst,hash); + /* Terminate signature with a '0' - cheating, but should be ok */ + m->sig[m->siglen]=0; + if (!st->pubkey->check(st->pubkey->st,hash,st->hash->len,m->sig)) { + slog(st,LOG_SEC,"msg3/msg4 signature failed check!"); + free(hash); + return False; + } + free(hash); + + st->remote_adv_mtu=m->remote_mtu; + + return True; +} + static bool_t process_msg3(struct site *st, struct buffer_if *msg3, const struct comm_addr *src, uint32_t msgtype) { struct msg m; - uint8_t *hash; - void *hst; cstring_t err; assert(msgtype==LABEL_MSG3 || msgtype==LABEL_MSG3BIS); @@ -741,19 +782,8 @@ static bool_t process_msg3(struct site *st, struct buffer_if *msg3, transform_found: st->chosen_transform=ti; - /* Check signature and store g^x mod m */ - hash=safe_malloc(st->hash->len, "process_msg3"); - hst=st->hash->init(); - st->hash->update(hst,m.hashstart,m.hashlen); - st->hash->final(hst,hash); - /* Terminate signature with a '0' - cheating, but should be ok */ - m.sig[m.siglen]=0; - if (!st->pubkey->check(st->pubkey->st,hash,st->hash->len,m.sig)) { - slog(st,LOG_SEC,"msg3 signature failed check!"); - free(hash); + if (!process_msg3_msg4(st,&m)) return False; - } - free(hash); /* Terminate their DH public key with a '0' */ m.pk[m.pklen]=0; @@ -777,8 +807,6 @@ static bool_t process_msg4(struct site *st, struct buffer_if *msg4, const struct comm_addr *src) { struct msg m; - uint8_t *hash; - void *hst; cstring_t err; if (!unpick_msg(st,LABEL_MSG4,msg4,&m)) return False; @@ -787,19 +815,8 @@ static bool_t process_msg4(struct site *st, struct buffer_if *msg4, return False; } - /* Check signature and store g^x mod m */ - hash=safe_malloc(st->hash->len, "process_msg4"); - hst=st->hash->init(); - st->hash->update(hst,m.hashstart,m.hashlen); - st->hash->final(hst,hash); - /* Terminate signature with a '0' - cheating, but should be ok */ - m.sig[m.siglen]=0; - if (!st->pubkey->check(st->pubkey->st,hash,st->hash->len,m.sig)) { - slog(st,LOG_SEC,"msg4 signature failed check!"); - free(hash); + if (!process_msg3_msg4(st,&m)) return False; - } - free(hash); /* Terminate their DH public key with a '0' */ m.pk[m.pklen]=0; @@ -1149,7 +1166,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); } @@ -1769,6 +1794,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); @@ -1837,7 +1863,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);