chiark / gitweb /
build system: New "make dist" uses git; add release checklist
[secnet.git] / site.c
diff --git a/site.c b/site.c
index 9d09ebc1e53c92988004ec0feef14826b6eb87e8..624752cec98bcd46f8dbc1ed1c01d313091f59b6 100644 (file)
--- a/site.c
+++ b/site.c
 #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) */
 
@@ -219,7 +226,8 @@ struct site {
     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;
@@ -796,7 +804,7 @@ static void site_resolve_callback(void *sst, struct in_addr *address)
     }
     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;
@@ -1281,6 +1289,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
     struct site *st;
     item_t *item;
     dict_t *dict;
+    int i;
 
     st=safe_malloc(sizeof(*st),"site_apply");
 
@@ -1300,20 +1309,48 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
     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");
+    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->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);
@@ -1331,7 +1368,8 @@ 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) 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);
@@ -1396,13 +1434,25 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
     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);