From 03cbfbd2fa5783bd57aa379c08e90312149023cf Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 23 Apr 2017 12:36:09 +0100 Subject: [PATCH] polypath: Introduce comm-info/dedicated-interface-addr Also, rename `interfs' to `interfs_general' in struct polypath, to ensure we found everywhere this list is processed. Signed-off-by: Ian Jackson --- README | 28 +++++++++++++++++++-------- polypath.c | 57 +++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/README b/README index 424f756..e56c444 100644 --- a/README +++ b/README @@ -236,14 +236,18 @@ polypath: dict argument buffer (buffer closure): buffer for incoming packets authbind (string): optional, path to authbind-helper program max-interfaces (number): optional, max number of different interfaces to - use (also, maximum steady-state amount of packet multiplication) + use (also, maximum steady-state amount of packet multiplication); + interfaces marked with `@' do not count. interfaces (string list): which interfaces to process; each entry is - optionally `!' or `+' followed by a glob pattern (which is applied to a - prospective interface using fnmatch with no flags). If no list is - specified, or the list ends with a `!' entry, a default list is - used/appended: "!tun*","!tap*","!sl*","!userv*","!lo","*". Patterns - which do not start with `*' or an alphanumeric need to be preceded - by `!' or `+'. + optionally `!' or `+' or `@' followed by a glob pattern (which is + applied to a prospective interface using fnmatch with no flags). + `+' or nothing means to process normally. `!' means to ignore; + `@' means to use only in conjunction with dedicated-interface-addr. + If no list is specified, or the list ends with a `!' entry, a + default list is used/appended: + "!tun*","!tap*","!sl*","!userv*","!lo","@hippo*","*". + Patterns which do not start with `*' or an alphanumeric need to be + preceded by `!' or `+' or `@'. monitor-command (string list): Program to use to monitor appearance and disappearance of addresses on local network interfaces. Should produce lines of the form `+|- 4|6 ' where is @@ -272,6 +276,14 @@ parameter set to `true'. When the local site site is not marked mobile the address selection machinery might fixate on an unsuitable address. +polypath takes site-specific informtion as passed to the `comm-info' +site closure parameter. The entries understood in the dictionary +are: + dedicated-interface-addr (string): IPv4 or IPv6 address + literal. Interfaces specified with `@' in `interfaces' will be + used for the corresponding site iff the interface local address + is this address. + For an interface to work with polypath, it must either have a suitable default route, or be a point-to-point interface. In the general case this might mean that the host would have to have multiple default @@ -446,7 +458,7 @@ site: dict argument to 0, the default is to use the local private link mtu. comm-info (dict): Information for the comm, used when this site wants to transmit. If the comm does not support this, it is - ignored. (Currently nothing uses this.) + ignored. Links involving mobile peers have some different tuning parameter default values, which are generally more aggressive about retrying key diff --git a/polypath.c b/polypath.c index d0c1400..1d73a0a 100644 --- a/polypath.c +++ b/polypath.c @@ -45,7 +45,8 @@ struct polypath { const char *const *ifname_pats; const char *const *monitor_command; bool_t permit_loopback; - LIST_HEAD(interf_list, interf) interfs; + LIST_HEAD(interf_list, interf) interfs_general; + struct interf_list interfs_dedicated; struct buffer_if lbuf; int monitor_fd; pid_t monitor_pid; @@ -53,6 +54,10 @@ struct polypath { int privsep_ipcsock_fd; }; +struct comm_clientinfo { + union iaddr dedicated; /* might be AF_UNSPEC */ +}; + static void polypath_phase_shutdown(void *sst, uint32_t newphase); #define LG 0, st->uc.cc.cl.description, &st->uc.cc.loc @@ -61,7 +66,7 @@ static const char *const default_loopback_ifname_pats[] = { "!lo", 0 }; static const char *const default_ifname_pats[] = { - "!tun*","!tap*","!sl*","!userv*", "*", 0 + "!tun*","!tap*","!sl*","!userv*", "@hippo*", "*", 0 }; static const char *const default_monitor_command[] = { @@ -119,6 +124,21 @@ static char ifname_wanted(struct polypath *st, struct cloc loc, abort(); } +static struct comm_clientinfo *polypath_clientinfo(void *state, + dict_t *dict, struct cloc cloc) { + struct comm_clientinfo *clientinfo; + + NEW(clientinfo); + FILLZERO(*clientinfo); + clientinfo->dedicated.sa.sa_family=AF_UNSPEC; + + item_t *item = dict_find_item(dict,"dedicated-interface-addr", + False,"polypath",cloc); + if (item) string_item_to_iaddr(item,0,&clientinfo->dedicated, + "polypath"); + return clientinfo; +} + static int polypath_beforepoll(void *state, struct pollfd *fds, int *nfds_io, int *timeout_io) { @@ -331,7 +351,8 @@ static void polypath_record_ifaddr(struct polypath *st, struct interf_list *interfs; switch (want) { - case '+': interfs=&st->interfs; max_interfs=st->max_interfs; + case '+': interfs=&st->interfs_general; max_interfs=st->max_interfs; + case '@': interfs=&st->interfs_dedicated; max_interfs=INT_MAX; default: fatal("polypath: got bad want (%#x, %s)", want, ifname); } @@ -457,14 +478,18 @@ static void polypath_sendmsg_interf(struct polypath *st, struct interf *interf, struct buffer_if *buf, const struct comm_addr *dest, + const union iaddr *dedicated, bool_t *allreasonable) { int i; int af=dest->ia.sa.sa_family; - bool_t attempted=False, reasonable=False; + bool_t wanted=False, attempted=False, reasonable=False; for (i=0; isocks.n_socks; i++) { struct udpsock *us=&interf->socks.socks[i]; + if (dedicated && !iaddr_equal(dedicated, &us->addr, True)) + continue; + wanted=True; if (af != us->addr.sa.sa_family) continue; attempted=True; @@ -482,6 +507,9 @@ static void polypath_sendmsg_interf(struct polypath *st, interf->name,iaddr_to_string(&us->addr), buf->size,iaddr_to_string(&dest->ia)); } + if (!wanted) + return; + if (!attempted) if (!interf->experienced_xmit_noaf[af]++) lg_perror(LG,M_WARNING,0, @@ -499,9 +527,15 @@ static bool_t polypath_sendmsg(void *commst, struct buffer_if *buf, struct interf *interf; bool_t allreasonable=True; - LIST_FOREACH(interf,&st->interfs,entry) { + LIST_FOREACH(interf,&st->interfs_general,entry) { polypath_sendmsg_interf(st,interf,buf,dest, - &allreasonable); + 0, &allreasonable); + } + if (clientinfo && clientinfo->dedicated.sa.sa_family != AF_UNSPEC) { + LIST_FOREACH(interf,&st->interfs_dedicated,entry) { + polypath_sendmsg_interf(st,interf,buf,dest, + &clientinfo->dedicated, &allreasonable); + } } return allreasonable; } @@ -588,7 +622,7 @@ struct privsep_mdata { bool_t add; char ifname[100]; union iaddr ia; - char want; /* `+', for now */ + char want; /* `+' or `@' */ }; static void papp_bad(struct polypath *st, void *badctx, @@ -836,7 +870,9 @@ static void polypath_phase_childpersist(void *sst, uint32_t newphase) struct polypath *st=sst; struct interf *interf; - LIST_FOREACH(interf,&st->interfs,entry) + LIST_FOREACH(interf,&st->interfs_general,entry) + udp_socks_childpersist(&st->uc,&interf->socks); + LIST_FOREACH(interf,&st->interfs_dedicated,entry) udp_socks_childpersist(&st->uc,&interf->socks); } @@ -854,6 +890,8 @@ static list_t *polypath_apply(closure_t *self, struct cloc loc, COMM_APPLY_STANDARD(st,&st->uc.cc,"polypath",args); UDP_APPLY_STANDARD(st,&st->uc,"polypath"); + st->uc.cc.ops.clientinfo = polypath_clientinfo; + struct udpcommon *uc=&st->uc; struct commcommon *cc=&uc->cc; @@ -873,7 +911,8 @@ static list_t *polypath_apply(closure_t *self, struct cloc loc, st->permit_loopback=dict_read_bool(d,"permit-loopback",False, "polypath",cc->loc,False); - LIST_INIT(&st->interfs); + LIST_INIT(&st->interfs_general); + LIST_INIT(&st->interfs_dedicated); buffer_new(&st->lbuf,ADNS_ADDR2TEXT_BUFLEN+100); BUF_ALLOC(&st->lbuf,"polypath lbuf"); -- 2.30.2