#define DEFAULT_SETUP_RETRIES 5
#define DEFAULT_SETUP_RETRY_INTERVAL (2*1000) /* [ms] */
#define DEFAULT_WAIT_TIME (20*1000) /* [ms] */
+
+#define DEFAULT_MOBILE_KEY_LIFETIME (2*24*3600*1000) /* [ms] */
+#define DEFAULT_MOBILE_KEY_RENEGOTIATE_GAP (12*3600*1000) /* [ms] */
+#define DEFAULT_MOBILE_SETUP_RETRIES 30
+#define DEFAULT_MOBILE_SETUP_RETRY_INTERVAL (1*1000) /* [ms] */
+#define DEFAULT_MOBILE_WAIT_TIME (10*1000) /* [ms] */
+
#define DEFAULT_MOBILE_PEER_EXPIRY (2*60) /* [s] */
#define DEFAULT_MOBILE_PEERS_MAX 3 /* send at most this many copies (default) */
bool_t 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 */
- int remoteport; /* Port for bootstrapping, optional */
+ void *remote_addr_config; /* created and used by comm */
struct netlink_if *netlink;
- struct comm_if *comm;
- struct resolver_if *resolver;
+ struct comm_if **comms;
+ int ncomms;
struct log_if *log;
struct random_if *random;
struct rsaprivkey_if *privkey;
}
}
-static void site_resolve_callback(void *sst, struct in_addr *address)
+static void site_resolve_callback(void *sst, const struct comm_addr *address)
{
struct site *st=sst;
- struct comm_addr ca_buf, *ca_use;
if (st->state!=SITE_RESOLVE) {
slog(st,LOG_UNEXPECTED,"site_resolve_callback called unexpectedly");
return;
}
- if (address) {
- FILLZERO(ca_buf);
- ca_buf.comm=st->comm;
- ca_buf.sin.sin_family=AF_INET;
- ca_buf.sin.sin_port=htons(st->remoteport);
- ca_buf.sin.sin_addr=*address;
- ca_use=&ca_buf;
- } else {
- slog(st,LOG_ERROR,"resolution of %s failed",st->address);
- ca_use=0;
+ if (!address) {
+ slog(st,LOG_ERROR,"resolution of peer address failed");
}
- if (transport_compute_setupinit_peers(st,ca_use)) {
+ if (transport_compute_setupinit_peers(st,address)) {
enter_new_state(st,SITE_SENTMSG1);
} else {
/* Can't figure out who to try to to talk to */
{
if (st->state!=SITE_RUN) return False;
slog(st,LOG_SETUP_INIT,"initiating key exchange (%s)",reason);
- if (st->address) {
+ if (st->remote_addr_config) {
slog(st,LOG_SETUP_INIT,"resolving peer address");
return enter_state_resolve(st);
} else if (transport_compute_setupinit_peers(st,0)) {
quality=LINK_QUALITY_UP;
else if (st->state==SITE_WAIT || st->state==SITE_STOP)
quality=LINK_QUALITY_DOWN;
- else if (st->address)
+ else if (st->remote_addr_config)
quality=LINK_QUALITY_DOWN_CURRENT_ADDRESS;
else if (transport_peers_valid(&st->peers))
quality=LINK_QUALITY_DOWN_STALE_ADDRESS;
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);
+ st->comms[0]->peer_addr_request(st->comms[0]->st,st->remote_addr_config,
+ site_resolve_callback,st);
return True;
}
struct site *st;
item_t *item;
dict_t *dict;
+ int i;
st=safe_malloc(sizeof(*st),"site_apply");
dict=item->data.dict;
st->localname=dict_read_string(dict, "local-name", True, "site", loc);
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=
+ dict_read_bool(dict,"local-mobile",False,"site",loc,False);
+
/* Sanity check (which also allows the 'sites' file to include
site() closures for all sites including our own): refuse to
talk to ourselves */
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)
+ cfgfatal(loc,"site","site %s's peer-mobile=%d"
+ " but our local-mobile=%d\n",
+ st->localname, st->peer_mobile, local_mobile);
free(st);
return NULL;
}
+ if (st->peer_mobile && local_mobile) {
+ Message(M_WARNING,"site %s: site is mobile but so are we"
+ " -> ignoring this site\n", st->remotename);
+ free(st);
+ return NULL;
+ }
+
assert(index_sequence < 0xffffffffUL);
st->index = ++index_sequence;
- st->peer_mobile=dict_read_bool(dict,"mobile",False,"site",loc,False);
st->netlink=find_cl_if(dict,"link",CL_NETLINK,True,"site",loc);
- st->comm=find_cl_if(dict,"comm",CL_COMM,True,"site",loc);
- st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc);
+
+ list_t *comms_cfg=dict_lookup(dict,"comm");
+ if (!comms_cfg) cfgfatal(loc,"site","closure list \"comm\" not found");
+ st->ncomms=list_length(comms_cfg);
+ st->comms=safe_malloc_ary(sizeof(*st->comms),st->ncomms,"comms");
+ assert(st->ncomms);
+ for (i=0; i<st->ncomms; i++) {
+ item_t *item=list_elem(comms_cfg,i);
+ if (item->type!=t_closure) cfgfatal(loc,"site","comm is not a closure");
+ closure_t *cl=item->data.closure;
+ if (cl->type!=CL_COMM) cfgfatal(loc,"site","comm closure wrong type");
+ st->comms[i]=cl->interface;
+ }
+
st->log=find_cl_if(dict,"log",CL_LOG,True,"site",loc);
st->random=find_cl_if(dict,"random",CL_RANDOMSRC,True,"site",loc);
+ st->remote_addr_config=st->comms[0]->peer_addr_config(
+ st->comms[0]->st,dict,loc,"site");
st->privkey=find_cl_if(dict,"local-key",CL_RSAPRIVKEY,True,"site",loc);
- st->address=dict_read_string(dict, "address", False, "site", loc);
- if (st->address)
- st->remoteport=dict_read_number(dict,"port",True,"site",loc,0);
- else st->remoteport=0;
st->pubkey=find_cl_if(dict,"key",CL_RSAPUBKEY,True,"site",loc);
st->transform=
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) DEFAULT_##D
+#define DEFAULT(D) (st->peer_mobile || local_mobile \
+ ? DEFAULT_MOBILE_##D : DEFAULT_##D)
#define CFG_NUMBER(k,D) dict_read_number(dict,(k),False,"site",loc,DEFAULT(D));
st->key_lifetime= CFG_NUMBER("key-lifetime", KEY_LIFETIME);
st->dhsecret=safe_malloc(st->dh->len,"site:dhsecret");
st->sharedsecret=safe_malloc(st->transform->keylen,"site:sharedsecret");
+ /* We need to compute some properties of our comms */
+#define COMPUTE_WORST(pad) \
+ int worst_##pad=0; \
+ for (i=0; i<st->ncomms; i++) { \
+ int thispad=st->comms[i]->pad; \
+ if (thispad > worst_##pad) \
+ worst_##pad=thispad; \
+ }
+ COMPUTE_WORST(min_start_pad)
+ COMPUTE_WORST(min_end_pad)
+
/* We need to register the remote networks with the netlink device */
st->netlink->reg(st->netlink->st, site_outgoing, st,
st->transform->max_start_pad+(4*4)+
- st->comm->min_start_pad,
- st->transform->max_end_pad+st->comm->min_end_pad);
+ worst_min_start_pad,
+ st->transform->max_end_pad+worst_min_end_pad);
- st->comm->request_notify(st->comm->st, st, site_incoming);
+ for (i=0; i<st->ncomms; i++)
+ st->comms[i]->request_notify(st->comms[i]->st, st, site_incoming);
st->current_transform=st->transform->create(st->transform->st);
st->new_transform=st->transform->create(st->transform->st);