#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) */
string_t address; /* DNS name for bootstrapping, optional */
int remoteport; /* Port for bootstrapping, optional */
struct netlink_if *netlink;
- struct comm_if *comm;
+ struct comm_if **comms;
+ int ncomms;
struct resolver_if *resolver;
struct log_if *log;
struct random_if *random;
buffer_init(&st->buffer,st->transform->max_start_pad+(4*4));
/* Give the netlink code an opportunity to put its own stuff in the
message (configuration information, etc.) */
- st->netlink->output_config(st->netlink->st,&st->buffer);
buf_prepend_uint32(&st->buffer,LABEL_MSG5);
st->new_transform->forwards(st->new_transform->st,&st->buffer,
&transform_err);
slog(st,LOG_SEC,"MSG5/PING packet contained wrong label");
return False;
}
- if (!st->netlink->check_config(st->netlink->st,msg5)) {
- slog(st,LOG_SEC,"MSG5/PING packet contained bad netlink config");
- return False;
- }
- CHECK_EMPTY(msg5);
+ /* Older versions of secnet used to write some config data here
+ * which we ignore. So we don't CHECK_EMPTY */
return True;
}
buffer_init(&st->buffer,st->transform->max_start_pad+(4*4));
/* Give the netlink code an opportunity to put its own stuff in the
message (configuration information, etc.) */
- st->netlink->output_config(st->netlink->st,&st->buffer);
buf_prepend_uint32(&st->buffer,LABEL_MSG6);
st->new_transform->forwards(st->new_transform->st,&st->buffer,
&transform_err);
slog(st,LOG_SEC,"MSG6/PONG packet contained invalid data");
return False;
}
- if (!st->netlink->check_config(st->netlink->st,msg6)) {
- slog(st,LOG_SEC,"MSG6/PONG packet contained bad netlink config");
- return False;
- }
- CHECK_EMPTY(msg6);
+ /* Older versions of secnet used to write some config data here
+ * which we ignore. So we don't CHECK_EMPTY */
return True;
}
+static bool_t decrypt_msg0(struct site *st, struct buffer_if *msg0)
+{
+ cstring_t transform_err;
+ struct msg0 m;
+ uint32_t problem;
+
+ if (!unpick_msg0(st,msg0,&m)) return False;
+
+ problem = st->current_transform->reverse(st->current_transform->st,
+ msg0,&transform_err);
+ if (!problem) return True;
+
+ slog(st,LOG_SEC,"transform: %s",transform_err);
+ initiate_key_setup(st,"incoming message would not decrypt");
+ return False;
+}
+
static bool_t process_msg0(struct site *st, struct buffer_if *msg0,
const struct comm_addr *src)
{
- struct msg0 m;
- cstring_t transform_err;
uint32_t type;
- if (!st->current_valid) {
- slog(st,LOG_DROP,"incoming message but no current key -> dropping");
- return initiate_key_setup(st,"incoming message but no current key");
- }
-
- if (!unpick_msg0(st,msg0,&m)) return False;
+ if (!decrypt_msg0(st,msg0))
+ return False;
- if (st->current_transform->reverse(st->current_transform->st,
- msg0,&transform_err)) {
- /* There's a problem */
- slog(st,LOG_SEC,"transform: %s",transform_err);
- return initiate_key_setup(st,"incoming message would not decrypt");
- }
CHECK_AVAIL(msg0,4);
type=buf_unprepend_uint32(msg0);
switch(type) {
}
if (address) {
FILLZERO(ca_buf);
- ca_buf.comm=st->comm;
+ ca_buf.comm=st->comms[0];
ca_buf.sin.sin_family=AF_INET;
ca_buf.sin.sin_port=htons(st->remoteport);
ca_buf.sin.sin_addr=*address;
const struct comm_addr *source)
{
struct site *st=sst;
+
+ if (buf->size < 12) return False;
+
uint32_t dest=ntohl(*(uint32_t *)buf->start);
if (dest==0) {
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);
+
+ list_t *comms_cfg=dict_lookup(dict,"comm");
+ if (!comms_cfg) cfgfatal(loc,"site","closure list \"comm\" not found\n");
+ 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\n");
+ closure_t *cl=item->data.closure;
+ if (cl->type!=CL_COMM) cfgfatal(loc,"site","comm closure wrong type\n");
+ st->comms[i]=cl->interface;
+ }
+
st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc);
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->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);
dst->npeers=src->npeers;
memcpy(dst->peers, src->peers, sizeof(*dst->peers) * dst->npeers);
transport_peers_debug(st,dst,"copy",
- src->npeers, &src->peers->addr, sizeof(src->peers));
+ src->npeers, &src->peers->addr, sizeof(*src->peers));
}
void transport_xmit(struct site *st, transport_peers *peers,