polypath: Introduce comm-info/dedicated-interface-addr
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 23 Apr 2017 11:36:09 +0000 (12:36 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 23 Apr 2017 17:06:21 +0000 (18:06 +0100)
Also, rename `interfs' to `interfs_general' in struct polypath, to
ensure we found everywhere this list is processed.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
README
polypath.c

diff --git a/README b/README
index 424f756..e56c444 100644 (file)
--- 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
   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
   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 `+|-<ifname> 4|6 <addr>' where <addr> is
   monitor-command (string list): Program to use to monitor appearance
    and disappearance of addresses on local network interfaces.  Should
    produce lines of the form `+|-<ifname> 4|6 <addr>' where <addr> 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.
 
 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
 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
     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
 
 Links involving mobile peers have some different tuning parameter
 default values, which are generally more aggressive about retrying key
index d0c1400..1d73a0a 100644 (file)
@@ -45,7 +45,8 @@ struct polypath {
     const char *const *ifname_pats;
     const char *const *monitor_command;
     bool_t permit_loopback;
     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;
     struct buffer_if lbuf;
     int monitor_fd;
     pid_t monitor_pid;
@@ -53,6 +54,10 @@ struct polypath {
     int privsep_ipcsock_fd;
 };
 
     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
 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[] = {
     "!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[] = {
 };
 
 static const char *const default_monitor_command[] = {
@@ -119,6 +124,21 @@ static char ifname_wanted(struct polypath *st, struct cloc loc,
     abort();
 }
 
     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)
 {
 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) {
 
     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);
     }
 
     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,
                                    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 *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; i<interf->socks.n_socks; i++) {
        struct udpsock *us=&interf->socks.socks[i];
 
     for (i=0; i<interf->socks.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;
        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));
     }
                  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,
     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;
 
     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,
        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;
 }
     }
     return allreasonable;
 }
@@ -588,7 +622,7 @@ struct privsep_mdata {
     bool_t add;
     char ifname[100];
     union iaddr ia;
     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,
 };
 
 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;
 
     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);
 }
 
        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");
 
     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;
 
     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);
 
     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");
 
     buffer_new(&st->lbuf,ADNS_ADDR2TEXT_BUFLEN+100);
     BUF_ALLOC(&st->lbuf,"polypath lbuf");