chiark / gitweb /
server/: Institute `address family table'; contemplate multiple sockets.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 16 Sep 2017 14:30:42 +0000 (15:30 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Thu, 28 Jun 2018 23:26:40 +0000 (00:26 +0100)
This is a slightly oddly-shaped change which lays important groundwork
for the future.

  * Firstly, it creates a table of address families, currently not very
    interestingly since there's only one, but this will be an essential
    tool for adding IPv6 support later.

  * Secondly, it turns the peer module's `sock' into a global vector
    `udpsock' of UDP sockets, possibly one for each of the supported
    address families.  There's no real change here, because there's only
    one address family known, but the `port' command has grown an
    address-family argument in case they have different ports.  To make
    this work, each peer now keeps track of the index of the socket it
    should use for transmitting messages.

py/tripe.py.in
server/admin.c
server/peer.c
server/servutil.c
server/tripe-admin.5.in
server/tripe.h

index 5562d7b30b50c0b26d158bf9134d09b2783282e0..29911b0ea5f1556ff83e04cbfbed1f41c0b7c332 100644 (file)
@@ -878,8 +878,10 @@ class TripeCommandDispatcher (TripeConnection):
                                *['PING'] +
                                _kwopts(kw, ['timeout']) +
                                [peer]))
                                *['PING'] +
                                _kwopts(kw, ['timeout']) +
                                [peer]))
-  def port(me):
-    return _oneline(me.command('PORT', filter = _tokenjoin))
+  def port(me, af = None):
+    return _oneline(me.command('PORT',
+                               *((af is not None) and [af] or []),
+                               filter = _tokenjoin))
   def quit(me):
     return _simple(me.command('QUIT'))
   def reload(me):
   def quit(me):
     return _simple(me.command('QUIT'))
   def reload(me):
index 46a7348ab34fba4ccaa8c48c4b1a3180f0e26349..3b99848c74473a8689943c1d811894b55753a815 100644 (file)
@@ -1666,7 +1666,24 @@ static void acmd_warn(admin *a, unsigned ac, char *av[])
   { alertcmd(a, AF_WARN, AF_WARN, "WARN", av); }
 
 static void acmd_port(admin *a, unsigned ac, char *av[])
   { alertcmd(a, AF_WARN, AF_WARN, "WARN", av); }
 
 static void acmd_port(admin *a, unsigned ac, char *av[])
-  { a_info(a, "%u", p_port(), A_END); a_ok(a); }
+{
+  int i;
+
+  if (ac) {
+    for (i = 0; i < NADDRFAM; i++)
+      if (mystrieq(av[0], aftab[i].name)) goto found;
+    a_fail(a, "unknown-address-family", "%s", av[0], A_END);
+    return;
+  found:
+    assert(udpsock[i].fd >= 0);
+  } else {
+    for (i = 0; i < NADDRFAM; i++)
+      if (udpsock[i].fd >= 0) goto found;
+    abort();
+  }
+  a_info(a, "%u", p_port(i), A_END);
+  a_ok(a);
+}
 
 static void acmd_daemon(admin *a, unsigned ac, char *av[])
 {
 
 static void acmd_daemon(admin *a, unsigned ac, char *av[])
 {
@@ -1977,7 +1994,7 @@ static const acmd acmdtab[] = {
   { "notify",  "MESSAGE ...",          1,      0xffff, acmd_notify },
   { "peerinfo",        "PEER",                 1,      1,      acmd_peerinfo },
   { "ping",    "[OPTIONS] PEER",       1,      0xffff, acmd_ping },
   { "notify",  "MESSAGE ...",          1,      0xffff, acmd_notify },
   { "peerinfo",        "PEER",                 1,      1,      acmd_peerinfo },
   { "ping",    "[OPTIONS] PEER",       1,      0xffff, acmd_ping },
-  { "port",    0,                      0,      0,      acmd_port },
+  { "port",    "[FAMILY]",             0,      1,      acmd_port },
   { "quit",    0,                      0,      0,      acmd_quit },
   { "reload",  0,                      0,      0,      acmd_reload },
   { "servinfo",        0,                      0,      0,      acmd_servinfo },
   { "quit",    0,                      0,      0,      acmd_quit },
   { "reload",  0,                      0,      0,      acmd_reload },
   { "servinfo",        0,                      0,      0,      acmd_servinfo },
index 03ed2ae3a83580cc6446bd78dd5fd38aa42bf968..ba8d7baf11ccd8a5a11a7d947270e51ff25b4ed3 100644 (file)
 
 #include "tripe.h"
 
 
 #include "tripe.h"
 
+/*----- Global state ------------------------------------------------------*/
+
+sel_file udpsock[NADDRFAM];
+
 /*----- Static variables --------------------------------------------------*/
 
 static sym_table byname;
 static addrmap byaddr;
 /*----- Static variables --------------------------------------------------*/
 
 static sym_table byname;
 static addrmap byaddr;
-static sel_file sock;
 static unsigned nmobile;
 
 /*----- Tunnel table ------------------------------------------------------*/
 static unsigned nmobile;
 
 /*----- Tunnel table ------------------------------------------------------*/
@@ -181,6 +184,7 @@ int p_updateaddr(peer *p, const addr *a)
 {
   peer *q;
   peer_byaddr *pa, *qa;
 {
   peer *q;
   peer_byaddr *pa, *qa;
+  int ix;
   unsigned f;
 
   /* --- Figure out how to proceed --- *
   unsigned f;
 
   /* --- Figure out how to proceed --- *
@@ -197,6 +201,7 @@ int p_updateaddr(peer *p, const addr *a)
     T( trace(T_PEER, "peer: updating address for `%s'", p_name(p)); )
     am_remove(&byaddr, p->byaddr);
     p->byaddr = pa; p->spec.sa = *a; pa->p = p;
     T( trace(T_PEER, "peer: updating address for `%s'", p_name(p)); )
     am_remove(&byaddr, p->byaddr);
     p->byaddr = pa; p->spec.sa = *a; pa->p = p;
+    p->afix = afix(p->spec.sa.sa.sa_family); assert(p->afix >= 0);
     a_notify("NEWADDR", "?PEER", p, "?ADDR", a, A_END);
     return (0);
   } else {
     a_notify("NEWADDR", "?PEER", p, "?ADDR", a, A_END);
     return (0);
   } else {
@@ -205,6 +210,7 @@ int p_updateaddr(peer *p, const addr *a)
             p_name(p), p_name(q)); )
     q->byaddr = qa; qa->p = q; q->spec.sa = p->spec.sa;
     p->byaddr = pa; pa->p = p; p->spec.sa = *a;
             p_name(p), p_name(q)); )
     q->byaddr = qa; qa->p = q; q->spec.sa = p->spec.sa;
     p->byaddr = pa; pa->p = p; p->spec.sa = *a;
+    ix = p->afix; p->afix = q->afix; q->afix = ix;
     a_notify("NEWADDR", "?PEER", p, "?ADDR", a, A_END);
     a_notify("NEWADDR", "?PEER", q, "?ADDR", &q->spec.sa, A_END);
     return (0);
     a_notify("NEWADDR", "?PEER", p, "?ADDR", a, A_END);
     a_notify("NEWADDR", "?PEER", q, "?ADDR", &q->spec.sa, A_END);
     return (0);
@@ -510,7 +516,7 @@ static int p_dotxend(peer *p)
   }
   IF_TRACING(T_PEER, trace_block(T_PACKET, "peer: sending packet",
                                 BBASE(&p->b), BLEN(&p->b)); )
   }
   IF_TRACING(T_PEER, trace_block(T_PACKET, "peer: sending packet",
                                 BBASE(&p->b), BLEN(&p->b)); )
-  if (sendto(sock.fd, BBASE(&p->b), BLEN(&p->b),
+  if (sendto(udpsock[p->afix].fd, BBASE(&p->b), BLEN(&p->b),
             0, &p->spec.sa.sa, sasz) < 0) {
     a_warn("PEER", "?PEER", p, "socket-write-error", "?ERRNO", A_END);
     return (0);
             0, &p->spec.sa.sa, sasz) < 0) {
     a_warn("PEER", "?PEER", p, "socket-write-error", "?ERRNO", A_END);
     return (0);
@@ -802,8 +808,8 @@ void p_init(struct in_addr addr, unsigned port)
        strerror(errno));
   }
   fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
        strerror(errno));
   }
   fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
-  sel_initfile(&sel, &sock, fd, SEL_READ, p_read, 0);
-  sel_addfile(&sock);
+  sel_initfile(&sel, &udpsock[AFIX_INET], fd, SEL_READ, p_read, 0);
+  sel_addfile(&udpsock[AFIX_INET]);
   T( trace(T_PEER, "peer: created socket"); )
 
   sym_create(&byname);
   T( trace(T_PEER, "peer: created socket"); )
 
   sym_create(&byname);
@@ -812,17 +818,17 @@ void p_init(struct in_addr addr, unsigned port)
 
 /* --- @p_port@ --- *
  *
 
 /* --- @p_port@ --- *
  *
- * Arguments:  ---
+ * Arguments:  @int i@ = address family index to retrieve
  *
  * Returns:    Port number used for socket.
  */
 
  *
  * Returns:    Port number used for socket.
  */
 
-unsigned p_port(void)
+unsigned p_port(int i)
 {
   addr a;
   socklen_t sz = sizeof(addr);
 
 {
   addr a;
   socklen_t sz = sizeof(addr);
 
-  if (getsockname(sock.fd, &a.sa, &sz))
+  if (getsockname(udpsock[i].fd, &a.sa, &sz))
     die(EXIT_FAILURE, "couldn't read port number: %s", strerror(errno));
   assert(a.sa.sa_family == AF_INET);
   return (ntohs(a.sin.sin_port));
     die(EXIT_FAILURE, "couldn't read port number: %s", strerror(errno));
   assert(a.sa.sa_family == AF_INET);
   return (ntohs(a.sin.sin_port));
@@ -898,6 +904,7 @@ peer *p_create(peerspec *spec)
   p->ks = 0;
   p->pings = 0;
   p->ifname = 0;
   p->ks = 0;
   p->pings = 0;
   p->ifname = 0;
+  p->afix = afix(p->spec.sa.sa.sa_family); assert(p->afix >= 0);
   memset(&p->st, 0, sizeof(stats));
   p->st.t_start = time(0);
   if (!(tops->flags & TUNF_PRIVOPEN))
   memset(&p->st, 0, sizeof(stats));
   p->st.t_start = time(0);
   if (!(tops->flags & TUNF_PRIVOPEN))
index 707213968f9dd2be252e7485c313c3bbbce7e4e5..70776ddad9ab19539ef0d6380e4271181dc610cb 100644 (file)
@@ -121,6 +121,30 @@ int mystrieq(const char *x, const char *y)
   }
 }
 
   }
 }
 
+/*----- Address handling --------------------------------------------------*/
+
+const struct addrfam aftab[] = {
+#define DEF(af) { AF_##af, #af },
+  ADDRFAM(DEF)
+#undef DEF
+};
+
+/* --- @afix@ --- *
+ *
+ * Arguments:  @int af@ = an address family code
+ *
+ * Returns:    The index of the address family's record in @aftab@, or @-1@.
+ */
+
+int afix(int af)
+{
+  int i;
+
+  for (i = 0; i < NADDRFAM; i++)
+    if (af == aftab[i].af) return (i);
+  return (-1);
+}
+
 /* --- @addrsz@ --- *
  *
  * Arguments:  @const addr *a@ = a network address
 /* --- @addrsz@ --- *
  *
  * Arguments:  @const addr *a@ = a network address
index 5836eeaede84d7738db7d2bb4555179b2b53cafb..43f772546d3ab832f19e5f969de7e232eca93218 100644 (file)
@@ -663,12 +663,18 @@ given, seconds are assumed.
 .RE
 .SP
 .B "PORT"
 .RE
 .SP
 .B "PORT"
+.RI [ family ]
 Emits an
 .B INFO
 line containing just the number of the UDP port used by the
 .B tripe
 Emits an
 .B INFO
 line containing just the number of the UDP port used by the
 .B tripe
-server.  If you've allowed your server to allocate a port dynamically,
-this is how to find out which one it chose.
+server, for the given address
+.I family
+(or one chosen arbitrarily if omitted -- though
+.B tripe
+tries to use the same port number consistently so this is not a likely
+problem in practice).  If you've allowed your server to allocate a port
+dynamically, this is how to find out which one it chose.
 .SP
 .B "RELOAD"
 Instructs the server to recheck its keyring files.  The server checks
 .SP
 .B "RELOAD"
 Instructs the server to recheck its keyring files.  The server checks
@@ -1079,6 +1085,13 @@ is available, which does not meet the stated requirements.
 .I tag
 is already the tag of an outstanding job.
 .SP
 .I tag
 is already the tag of an outstanding job.
 .SP
+.BI "unknown-address-family " afam
+(For
+.BR PORT .)
+The address family
+.I afam
+is unrecognized.
+.SP
 .BI "unknown-command " token
 The command
 .I token
 .BI "unknown-command " token
 The command
 .I token
index 4b6c7101434260dc007298800d5e007aa72a830c..0eae8dc5bbea304ac9246d5b2dc8f7702be62758 100644 (file)
@@ -410,6 +410,23 @@ extern const bulkops bulktab[];
 
 /*----- Data structures ---------------------------------------------------*/
 
 
 /*----- Data structures ---------------------------------------------------*/
 
+/* --- The address-family table --- */
+
+#define ADDRFAM(_)                                                     \
+  _(INET)
+
+enum {
+#define ENUM(af) AFIX_##af,
+  ADDRFAM(ENUM)
+#undef ENUM
+  NADDRFAM
+};
+
+extern const struct addrfam {
+  int af;
+  const char *name;
+} aftab[NADDRFAM];
+
 /* --- Socket addresses --- *
  *
  * A magic union of supported socket addresses.
 /* --- Socket addresses --- *
  *
  * A magic union of supported socket addresses.
@@ -615,6 +632,7 @@ typedef struct peer {
   peer_byaddr *byaddr;                 /* Lookup-by-address block */
   struct ping *pings;                  /* Pings we're waiting for */
   peerspec spec;                       /* Specifications for this peer */
   peer_byaddr *byaddr;                 /* Lookup-by-address block */
   struct ping *pings;                  /* Pings we're waiting for */
   peerspec spec;                       /* Specifications for this peer */
+  int afix;                            /* Index of address family */
   tunnel *t;                           /* Tunnel for local packets */
   char *ifname;                                /* Interface name for tunnel */
   keyset *ks;                          /* List head for keysets */
   tunnel *t;                           /* Tunnel for local packets */
   char *ifname;                                /* Interface name for tunnel */
   keyset *ks;                          /* List head for keysets */
@@ -757,6 +775,7 @@ extern sel_state sel;                       /* Global I/O event state */
 extern octet buf_i[PKBUFSZ], buf_o[PKBUFSZ], buf_t[PKBUFSZ], buf_u[PKBUFSZ];
 extern const tunnel_ops *tunnels[];    /* Table of tunnels (0-term) */
 extern const tunnel_ops *tun_default;  /* Default tunnel to use */
 extern octet buf_i[PKBUFSZ], buf_o[PKBUFSZ], buf_t[PKBUFSZ], buf_u[PKBUFSZ];
 extern const tunnel_ops *tunnels[];    /* Table of tunnels (0-term) */
 extern const tunnel_ops *tun_default;  /* Default tunnel to use */
+extern sel_file udpsock[NADDRFAM];     /* The master UDP sockets */
 extern kdata *master;                  /* Default private key */
 extern const char *tag_priv;           /* Default private key tag */
 
 extern kdata *master;                  /* Default private key */
 extern const char *tag_priv;           /* Default private key tag */
 
@@ -1577,12 +1596,12 @@ extern void p_init(struct in_addr /*addr*/, unsigned /*port*/);
 
 /* --- @p_port@ --- *
  *
 
 /* --- @p_port@ --- *
  *
- * Arguments:  ---
+ * Arguments:  @int i@ = address family index to retrieve
  *
  * Returns:    Port number used for socket.
  */
 
  *
  * Returns:    Port number used for socket.
  */
 
-unsigned p_port(void);
+extern unsigned p_port(int /*i*/);
 
 /* --- @p_create@ --- *
  *
 
 /* --- @p_create@ --- *
  *
@@ -1742,6 +1761,15 @@ extern const char *timestr(time_t /*t*/);
 
 extern int mystrieq(const char */*x*/, const char */*y*/);
 
 
 extern int mystrieq(const char */*x*/, const char */*y*/);
 
+/* --- @afix@ --- *
+ *
+ * Arguments:  @int af@ = an address family code
+ *
+ * Returns:    The index of the address family's record in @aftab@, or @-1@.
+ */
+
+extern int afix(int af);
+
 /* --- @addrsz@ --- *
  *
  * Arguments:  @const addr *a@ = a network address
 /* --- @addrsz@ --- *
  *
  * Arguments:  @const addr *a@ = a network address