*['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):
{ 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[])
{
{ "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 },
#include "tripe.h"
+/*----- Global state ------------------------------------------------------*/
+
+sel_file udpsock[NADDRFAM];
+
/*----- Static variables --------------------------------------------------*/
static sym_table byname;
static addrmap byaddr;
-static sel_file sock;
static unsigned nmobile;
/*----- Tunnel table ------------------------------------------------------*/
{
peer *q;
peer_byaddr *pa, *qa;
+ int ix;
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;
+ 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 {
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);
}
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);
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);
/* --- @p_port@ --- *
*
- * Arguments: ---
+ * Arguments: @int i@ = address family index to retrieve
*
* Returns: Port number used for socket.
*/
-unsigned p_port(void)
+unsigned p_port(int i)
{
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));
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))
}
}
+/*----- 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
.RE
.SP
.B "PORT"
+.RI [ family ]
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
.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
/*----- 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.
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 */
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 */
/* --- @p_port@ --- *
*
- * Arguments: ---
+ * Arguments: @int i@ = address family index to retrieve
*
* Returns: Port number used for socket.
*/
-unsigned p_port(void);
+extern unsigned p_port(int /*i*/);
/* --- @p_create@ --- *
*
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