#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) */
/* Each site can be in one of several possible states. */
/* 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.
*/
-#define MAX_MOBILE_PEERS_MAX 5 /* send at most this many copies, compiled max */
-
typedef struct {
struct timeval last;
struct comm_addr addr;
/* 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 */
* 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
* 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);
}
}
-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, int was_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, was_naddrs, comm_addr_to_string(&addrs[0]));;
+ if (naddrs != was_naddrs) {
+ slog(st,LOG_SETUP_INIT,"resolution of supplied addresses/names"
+ " yielded too many results (%d > %d), some ignored",
+ was_naddrs, naddrs);
+ }
} 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 */
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. */
}
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. */
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");
* 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;
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);
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, st->address ? 4 : 3);
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)
}
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);
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;
}
static void transport_resolve_complete(struct site *st,
- const struct comm_addr *ca) {
- transport_expire_record_peers(st,&st->peers,ca,1,"resolved data");
- transport_expire_record_peers(st,&st->setup_peers,ca,1,"resolved setup");
+ const struct comm_addr *addrs,
+ int naddrs) {
+ transport_expire_record_peers(st,&st->peers,addrs,naddrs,
+ "resolved data");
+ transport_expire_record_peers(st,&st->setup_peers,addrs,naddrs,
+ "resolved setup");
}
static void transport_resolve_complete_tardy(struct site *st,
- const struct comm_addr *ca) {
- transport_expire_record_peers(st,&st->peers,ca,1,"resolved tardily");
+ const struct comm_addr *addrs,
+ int naddrs) {
+ transport_expire_record_peers(st,&st->peers,addrs,naddrs,
+ "resolved tardily");
}
static void transport_peers__copy_by_mask(transport_peer *out, int *nout_io,
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++) {