#include <catacomb/mprand.h>
#include <catacomb/dh.h>
+#include <catacomb/chacha20.h>
#include <catacomb/noise.h>
#include <catacomb/rand.h>
-#include <catacomb/rc4.h>
#include "util.h"
static unsigned npeer = 0;
static key_file keys;
static grand *rng;
+static const char *delim = ":";
#define PASS(f, buf, sz) ((f) ? (f)->func((f), (buf), (sz)) : (void)0)
#define RND(i) (rng->ops->range(rng, (i)))
}
}
-static void addpeer(unsigned ac, char **av)
+static void addpeer_common(const char *cmd, int af, unsigned ac, char **av)
{
- struct hostent *h;
- struct sockaddr_in sin;
- int len = PKBUFSZ;
+ struct addrinfo aihint = { 0 }, *ai0, *ai1;
+ int len = PKBUFSZ, yes = 1;
+ int err;
peer *p;
int fd;
- if (ac != 4) die(1, "syntax: peer:NAME:PORT:ADDR:PORT");
- if (npeer >= 2) die(1, "enough peers already");
+ if (ac != 4) die(1, "syntax: %s:NAME:PORT:ADDR:PORT", cmd);
if (!key_bytag(&keys, av[0])) die(1, "no key named `%s'", av[0]);
p = &peers[npeer++];
p->name = xstrdup(av[0]);
- if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
+ aihint.ai_family = af;
+ aihint.ai_socktype = SOCK_DGRAM;
+ aihint.ai_flags = AI_ADDRCONFIG;
+ if ((err = getaddrinfo(av[2], av[3], &aihint, &ai1)) != 0)
+ die(1, "getaddrinfo(`%s', `%s'): %s", av[2], av[3], gai_strerror(err));
+ aihint.ai_family = ai1->ai_family;
+ aihint.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
+ if ((err = getaddrinfo(0, av[1], &aihint, &ai0)) != 0)
+ die(1, "getaddrinfo(passive, `%s'): %s", av[1], gai_strerror(err));
+ if ((fd = socket(ai1->ai_family, SOCK_DGRAM, ai1->ai_protocol)) < 0)
die(1, "socket: %s", strerror(errno));
- fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = htons(atoi(av[1]));
- if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)))
+ if (ai1->ai_family == AF_INET6) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)))
+ die(1, "setsockopt: %s", strerror(errno));
+ }
+ if (bind(fd, ai0->ai_addr, ai0->ai_addrlen))
die(1, "bind: %s", strerror(errno));
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- if ((h = gethostbyname(av[2])) == 0)
- die(1, "gethostbyname `%s'", av[2]);
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)) ||
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len)))
die(1, "setsockopt: %s", strerror(errno));
- memcpy(&sin.sin_addr, h->h_addr, sizeof(sin.sin_addr));
- sin.sin_port = htons(atoi(av[3]));
- if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)))
+ if (connect(fd, ai1->ai_addr, ai1->ai_addrlen))
die(1, "connect: %s", strerror(errno));
sel_initfile(&sel, &p->sf, fd, SEL_READ, dopacket, p);
sel_addfile(&p->sf);
+ freeaddrinfo(ai0); freeaddrinfo(ai1);
}
+static void addpeer(unsigned ac, char **av)
+ { addpeer_common("peer", AF_UNSPEC, ac, av); }
+static void addpeer4(unsigned ac, char **av)
+ { addpeer_common("peer4", AF_INET, ac, av); }
+static void addpeer6(unsigned ac, char **av)
+ { addpeer_common("peer6", AF_INET6, ac, av); }
+
/*----- Fork filter -------------------------------------------------------*/
typedef struct forknode {
void (*func)(unsigned /*ac*/, char **/*av*/);
} cmdtab[] = {
{ "peer", addpeer },
+ { "peer4", addpeer4 },
+ { "peer6", addpeer6 },
{ "include", include },
{ "filt", addfilter },
{ "lfilt", addlfilter },
unsigned c = 0;
const struct cmdtab *ct;
- p = strtok(p, ":");
+ p = strtok(p, delim);
if (!p || *p == '#') return;
do {
v[c++] = p;
- p = strtok(0, ":");
+ p = strtok(0, delim);
} while (p && c < AVMAX - 1);
v[c] = 0;
for (ct = cmdtab; ct->name; ct++) {
{ pquis(fp, "$, TrIPE version " VERSION "\n"); }
static void usage(FILE *fp)
- { pquis(fp, "Usage: $ [-k KEYRING] DIRECTIVE...\n"); }
+ { pquis(fp, "Usage: $ [-d CHAR] [-k KEYRING] DIRECTIVE...\n"); }
static void help(FILE *fp)
{
-v, --version Show the version number.\n\
-u, --usage Show terse usage summary.\n\
\n\
+-d, --delimiter=CHAR Use CHAR rather than `:' as delimiter.\n\
-k, --keyring=FILE Fetch keys from FILE.\n\
\n\
Directives:\n\
- peer:NAME:LOCAL-PORT:REMOTE-ADDR:REMOTE-PORT\n\
+ peer{,4,6}:NAME:LOCAL-PORT:REMOTE-ADDR:REMOTE-PORT\n\
include:FILE\n\
{,l,r}filt:FILTER:ARGS:...\n\
next:TAG\n\
const char *kfname = "keyring.pub";
int i;
unsigned f = 0;
- char buf[16];
+ char buf[32];
+ static octet zero[CHACHA_NONCESZ];
#define f_bogus 1u
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'v' },
{ "usage", 0, 0, 'u' },
+ { "delimiter", OPTF_ARGREQ, 0, 'd' },
{ "keyring", OPTF_ARGREQ, 0, 'k' },
{ 0, 0, 0, 0 }
};
- if ((i = mdwopt(argc, argv, "hvuk:", opt, 0, 0, 0)) < 0) break;
+ if ((i = mdwopt(argc, argv, "hvud:k:", opt, 0, 0, 0)) < 0) break;
switch (i) {
case 'h': help(stdout); exit(0);
case 'v': version(stdout); exit(0);
case 'u': usage(stdout); exit(0);
+ case 'd':
+ if (!optarg[0] || optarg[1])
+ die(1, "delimiter must be a single character");
+ delim = optarg;
+ break;
case 'k': kfname = optarg; break;
default: f |= f_bogus; break;
}
if (f & f_bogus) { usage(stderr); exit(1); }
rand_noisesrc(RAND_GLOBAL, &noise_source);
- rand_seed(RAND_GLOBAL, 160);
+ rand_seed(RAND_GLOBAL, 256);
rand_get(RAND_GLOBAL, buf, sizeof(buf));
- rng = rc4_rand(buf, sizeof(buf));
+ rng = chacha20_rand(buf, sizeof(buf), zero);
sel_init(&sel);
if (key_open(&keys, kfname, KOPEN_READ, key_moan, 0))
die(1, "couldn't open `%s': %s", kfname, strerror(errno));