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.
*['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):
{ 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[])
{
{ "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 },
+/*----- 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 unsigned nmobile;
/*----- Tunnel table ------------------------------------------------------*/
static unsigned nmobile;
/*----- Tunnel table ------------------------------------------------------*/
{
peer *q;
peer_byaddr *pa, *qa;
{
peer *q;
peer_byaddr *pa, *qa;
unsigned f;
/* --- Figure out how to proceed --- *
unsigned f;
/* --- Figure out how to proceed --- *
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 {
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);
}
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);
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);
+ * Arguments: @int i@ = address family index to retrieve
*
* Returns: Port number used for socket.
*/
*
* Returns: Port number used for socket.
*/
{
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));
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))
+/*----- 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
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
.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
/*----- 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.
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 */
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 */
+ * Arguments: @int i@ = address family index to retrieve
*
* Returns: Port number used for socket.
*/
*
* Returns: Port number used for socket.
*/
+extern unsigned p_port(int /*i*/);
/* --- @p_create@ --- *
*
/* --- @p_create@ --- *
*
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