chiark / gitweb /
autoconf: Update to autoconf 2.69
[secnet.git] / site.c
diff --git a/site.c b/site.c
index fd9ed4a7c63783880ff12e42f716e9df1bc88f94..e70570397d714f9e6983b88054d77df17a8f3cf2 100644 (file)
--- a/site.c
+++ b/site.c
@@ -41,6 +41,7 @@
 
 #define DEFAULT_MOBILE_PEER_EXPIRY            (2*60)      /* [s] */
 #define DEFAULT_MOBILE_PEERS_MAX 3 /* send at most this many copies (default) */
+#define DEFAULT_STATIC_PEERS_MAX 3 /* retain at most this many peer addresses */
 
 /* Each site can be in one of several possible states. */
 
@@ -144,9 +145,6 @@ static struct flagstr log_event_table[]={
 
 /* Details of "mobile peer" semantics:
 
- | Note: this comment is wishful thinking right now.  It will be
- | implemented in subsequent commits.
-
    - We use the same data structure for the different configurations,
      but manage it with different algorithms.
    
@@ -220,8 +218,6 @@ static struct flagstr log_event_table[]={
 
    */
 
-#define MAX_MOBILE_PEERS_MAX 5 /* send at most this many copies, compiled max */
-
 typedef struct {
     struct timeval last;
     struct comm_addr addr;
@@ -231,7 +227,7 @@ typedef struct {
 /* configuration information */
 /* runtime information */
     int npeers;
-    transport_peer peers[MAX_MOBILE_PEERS_MAX];
+    transport_peer peers[MAX_PEER_ADDRS];
 } transport_peers;
 
 /* Basic operations on transport peer address sets */
@@ -249,7 +245,8 @@ static void transport_data_msgok(struct site *st, const struct comm_addr *a);
  * resolve completing (or being determined not to be relevant) or an
  * incoming PROD; if we are the responder, as a result of the MSG1. */
 static bool_t transport_compute_setupinit_peers(struct site *st,
-        const struct comm_addr *configured_addr /* 0 if none or not found */,
+        const struct comm_addr *configured_addrs /* 0 if none or not found */,
+        int n_configured_addrs /* 0 if none or not found */,
         const struct comm_addr *incoming_packet_addr /* 0 if none */);
 
 /* Called if we are the responder in a key setup, when the resolve
@@ -260,9 +257,9 @@ static bool_t transport_compute_setupinit_peers(struct site *st,
  * setup is done (either completed or not) and only the data peers are
  * relevant */
 static void transport_resolve_complete(struct site *st,
-                                      const struct comm_addr *a);
+        const struct comm_addr *addrs, int naddrs);
 static void transport_resolve_complete_tardy(struct site *st,
-                                            const struct comm_addr *ca_use);
+        const struct comm_addr *addrs, int naddrs);
 
 static void transport_xmit(struct site *st, transport_peers *peers,
                           struct buffer_if *buf, bool_t candebug);
@@ -1195,30 +1192,23 @@ static bool_t send_msg(struct site *st)
     }
 }
 
-static void site_resolve_callback(void *sst, struct in_addr *address)
+static void site_resolve_callback(void *sst, const struct comm_addr *addrs,
+                                 int naddrs)
 {
     struct site *st=sst;
-    struct comm_addr ca_buf, *ca_use;
 
     st->resolving=False;
 
-    if (address) {
-       FILLZERO(ca_buf);
-       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;
-       ca_use=&ca_buf;
-       slog(st,LOG_STATE,"resolution of %s completed: %s",
-            st->address, comm_addr_to_string(ca_use));;
+    if (naddrs) {
+       slog(st,LOG_STATE,"resolution of %s completed, %d addrs, eg: %s",
+            st->address, naddrs, comm_addr_to_string(&addrs[0]));;
     } else {
        slog(st,LOG_ERROR,"resolution of %s failed",st->address);
-       ca_use=0;
     }
 
     switch (st->state) {
     case SITE_RESOLVE:
-        if (transport_compute_setupinit_peers(st,ca_use,0)) {
+        if (transport_compute_setupinit_peers(st,addrs,naddrs,0)) {
            enter_new_state(st,SITE_SENTMSG1);
        } else {
            /* Can't figure out who to try to to talk to */
@@ -1230,12 +1220,12 @@ static void site_resolve_callback(void *sst, struct in_addr *address)
     case SITE_SENTMSG1: case SITE_SENTMSG2:
     case SITE_SENTMSG3: case SITE_SENTMSG4:
     case SITE_SENTMSG5:
-       if (ca_use) {
+       if (naddrs) {
            /* We start using the address immediately for data too.
             * It's best to store it in st->peers now because we might
             * go via SENTMSG5, WAIT, and a MSG0, straight into using
             * the new key (without updating the data peer addrs). */
-           transport_resolve_complete(st,ca_use);
+           transport_resolve_complete(st,addrs,naddrs);
        } else if (st->local_mobile) {
            /* We can't let this rest because we may have a peer
             * address which will break in the future. */
@@ -1250,10 +1240,10 @@ static void site_resolve_callback(void *sst, struct in_addr *address)
        }
        break;
     case SITE_RUN:
-       if (ca_use) {
+       if (naddrs) {
            slog(st,LOG_SETUP_INIT,"resolution of %s completed tardily,"
                 " updating peer address(es)",st->address);
-           transport_resolve_complete_tardy(st,ca_use);
+           transport_resolve_complete_tardy(st,addrs,naddrs);
        } else if (st->local_mobile) {
            /* Not very good.  We should queue (another) renegotiation
             * so that we can update the peer address. */
@@ -1280,7 +1270,7 @@ static bool_t initiate_key_setup(struct site *st, cstring_t reason,
     if (st->address) {
        slog(st,LOG_SETUP_INIT,"resolving peer address");
        return enter_state_resolve(st);
-    } else if (transport_compute_setupinit_peers(st,0,prod_hint)) {
+    } else if (transport_compute_setupinit_peers(st,0,0,prod_hint)) {
        return enter_new_state(st,SITE_SENTMSG1);
     }
     slog(st,LOG_SETUP_INIT,"key exchange failed: no address for peer");
@@ -1400,6 +1390,7 @@ static bool_t ensure_resolving(struct site *st)
      * case we have to clear ->resolving again. */
     st->resolving=True;
     bool_t ok = st->resolver->request(st->resolver->st,st->address,
+                                     st->remoteport,st->comms[0],
                                      site_resolve_callback,st);
     if (!ok)
        st->resolving=False;
@@ -1679,7 +1670,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf,
        if (st->state==SITE_RUN || st->state==SITE_RESOLVE ||
            st->state==SITE_WAIT) {
            /* We should definitely process it */
-           transport_compute_setupinit_peers(st,0,source);
+           transport_compute_setupinit_peers(st,0,0,source);
            if (process_msg1(st,buf,source,&named_msg)) {
                slog(st,LOG_SETUP_INIT,"key setup initiated by peer");
                bool_t entered=enter_new_state(st,SITE_SENTMSG2);
@@ -1967,12 +1958,14 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
     st->mobile_peer_expiry= dict_read_number(
        dict,"mobile-peer-expiry",False,"site",loc,DEFAULT_MOBILE_PEER_EXPIRY);
 
-    st->transport_peers_max= !st->peer_mobile ? 1 : dict_read_number(
-       dict,"mobile-peers-max",False,"site",loc,DEFAULT_MOBILE_PEERS_MAX);
+    const char *peerskey= st->peer_mobile
+       ? "mobile-peers-max" : "static-peers-max";
+    st->transport_peers_max= dict_read_number(
+       dict,peerskey,False,"site",loc,DEFAULT_MOBILE_PEERS_MAX);
     if (st->transport_peers_max<1 ||
-       st->transport_peers_max>=MAX_MOBILE_PEERS_MAX) {
-       cfgfatal(loc,"site","mobile-peers-max must be in range 1.."
-                STRING(MAX_MOBILE_PEERS_MAX) "\n");
+       st->transport_peers_max>=MAX_PEER_ADDRS) {
+       cfgfatal(loc,"site", "%s must be in range 1.."
+                STRING(MAX_PEER_ADDRS) "\n", peerskey);
     }
 
     if (st->key_lifetime < DEFAULT(KEY_RENEGOTIATE_GAP)*2)
@@ -2164,24 +2157,24 @@ static void transport_record_peers(struct site *st, transport_peers *peers,
 }
 
 static bool_t transport_compute_setupinit_peers(struct site *st,
-        const struct comm_addr *configured_addr /* 0 if none or not found */,
+        const struct comm_addr *configured_addrs /* 0 if none or not found */,
+        int n_configured_addrs /* 0 if none or not found */,
         const struct comm_addr *incoming_packet_addr /* 0 if none */) {
-
-    if (!configured_addr && !incoming_packet_addr &&
+    if (!n_configured_addrs && !incoming_packet_addr &&
        !transport_peers_valid(&st->peers))
        return False;
 
     slog(st,LOG_SETUP_INIT,
-        "using:%s%s %d old peer address(es)",
-        configured_addr ? " configured address;" : "",
+        "using:%d configured addr(s);%s %d old peer addrs(es)",
+        n_configured_addrs,
         incoming_packet_addr ? " incoming packet address;" : "",
         st->peers.npeers);
 
-    /* Non-mobile peers have st->peers.npeers==0 or ==1, since they
-     * have transport_peers_max==1.  The effect is that this code
-     * always uses the configured address if supplied, or otherwise
-     * the address of the incoming PROD, or the existing data peer if
-     * one exists; this is as desired. */
+    /* Non-mobile peers try addresses until one is plausible.  The
+     * effect is that this code always tries first the configured
+     * address if supplied, or otherwise the address of the incoming
+     * PROD, or finally the existing data peer if one exists; this is
+     * as desired. */
 
     transport_peers_copy(st,&st->setup_peers,&st->peers);
     transport_peers_expire(st,&st->setup_peers);
@@ -2190,9 +2183,9 @@ static bool_t transport_compute_setupinit_peers(struct site *st,
        transport_record_peers(st,&st->setup_peers,
                               incoming_packet_addr,1, "incoming");
 
-    if (configured_addr)
+    if (n_configured_addrs)
        transport_record_peers(st,&st->setup_peers,
-                              configured_addr,1, "setupinit");
+                             configured_addrs,n_configured_addrs, "setupinit");
 
     assert(transport_peers_valid(&st->setup_peers));
     return True;
@@ -2227,17 +2220,19 @@ static void transport_peers_copy(struct site *st, transport_peers *dst,
 }
 
 static void transport_resolve_complete(struct site *st,
-                                      const struct comm_addr *ca_use) {
+                                      const struct comm_addr *addrs,
+                                      int naddrs) {
     transport_peers_expire(st,&st->peers);
-    transport_record_peers(st,&st->peers,ca_use,1,"resolved data");
+    transport_record_peers(st,&st->peers,addrs,naddrs,"resolved data");
     transport_peers_expire(st,&st->setup_peers);
-    transport_record_peers(st,&st->setup_peers,ca_use,1,"resolved setup");
+    transport_record_peers(st,&st->setup_peers,addrs,naddrs,"resolved setup");
 }
 
 static void transport_resolve_complete_tardy(struct site *st,
-                                            const struct comm_addr *ca_use) {
+                                            const struct comm_addr *addrs,
+                                            int naddrs) {
     transport_peers_expire(st,&st->peers);
-    transport_record_peers(st,&st->peers,ca_use,1,"resolved tardily");
+    transport_record_peers(st,&st->peers,addrs,naddrs,"resolved tardily");
 }
 
 static void transport_peers__copy_by_mask(transport_peer *out, int *nout_io,
@@ -2260,7 +2255,7 @@ void transport_xmit(struct site *st, transport_peers *peers,
     int slot;
     transport_peers_expire(st, peers);
     unsigned failed=0; /* bitmask */
-    assert(MAX_MOBILE_PEERS_MAX < sizeof(unsigned)*CHAR_BIT);
+    assert(MAX_PEER_ADDRS < sizeof(unsigned)*CHAR_BIT);
 
     int nfailed=0;
     for (slot=0; slot<peers->npeers; slot++) {