COPYING
-install-sh
-mkinstalldirs
-missing
-config.sub
-config.guess
## -*-makefile-*-
##
-## $Id: Makefile.am,v 1.10 2004/04/08 01:36:17 mdw Exp $
+## $Id$
##
## Makefile for TrIPE
##
keymgmt.c keyexch.c keyset.c \
servutil.c util.c util.h
EXTRA_tripe_SOURCES = \
- tun-unet.c tun-bsd.c
+ tun-unet.c tun-bsd.c tun-linux.c
tripe_LDADD = $(CATACOMB_LIBS)
tripectl_SOURCES = \
client.c util.c util.h
- tun-unet.c tun-bsd.c
tripe_mitm_SOURCES = \
mallory.c
tripe_mitm_LDADD = $(CATACOMB_LIBS)
+++ /dev/null
-/* -*-c-*-
- *
- * $Id: acconfig.h,v 1.6 2004/04/08 01:36:17 mdw Exp $
- *
- * Configuration header for TrIPE
- *
- * (c) 1999 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of Trivial IP Encryption (TrIPE).
- *
- * TrIPE is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * TrIPE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with TrIPE; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef ACCONFIG_H
-#define ACCONFIG_H
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/*----- Autoconfiguration data --------------------------------------------*/
-@TOP@
-
-/* Package and version number. */
-#define PACKAGE "tripe"
-#define VERSION "1.0.0"
-
-/* Define to disable the tracing options. This might improve performance a
- * little bit, and can prevent sensitive information from being leaked if
- * you're in the habit of typing things like `tripectl trace A' by
- * accident. */
-#undef NTRACE
-
-/* Define according to the type of tunneling interface appropriate for your
- * system. Linux types should say `TUN_LINUX' for the TUN/TAP driver if
- * using kernel 2.4.0 or later, or say `TUN_UNET' for 2.2-series kernels and
- * build the `usernet' module. BSD types should say `TUN_BSD' to use the
- * built-in `tun' devices. */
-#undef TUN_TYPE
-
-/* Define this to your default configuration directory. This is where
- * tripe searches for keys and other stuff. */
-#define CONFIGDIR "."
-
-/* Define this to the directory in which tripe's admin socket is to be
- * placed. Common choices are `.' -- the tripe configuration directory --
- * and /var/run. */
-#define SOCKETDIR "."
-
-/* Define if your Ethereal plugin headers are broken (e.g., Debian 3.0) but
- * you're running some sensible ELF system, and I should try to bodge around
- * the damage. */
-#undef ETHEREAL_BUGGERED
-
-@BOTTOM@
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
unsigned tr_flags = 0;
#endif
+static const trace_opt w_opts[] = {
+ { 't', AF_TRACE, "trace messages" },
+ { 'n', AF_NOTE, "asynchronous notifications" },
+ { 'w', AF_WARN, "warnings" },
+ { 'A', AF_ALLMSGS, "all of the above" },
+ { 0, 0, 0 }
+};
+
/*----- Static variables --------------------------------------------------*/
static admin *admins;
/*----- Output functions --------------------------------------------------*/
+/* --- @mystrieq@ --- *
+ *
+ * Arguments: @const char *x, *y@ = two strings
+ *
+ * Returns: True if @x@ and @y are equal, up to case.
+ */
+
+static int mystrieq(const char *x, const char *y)
+{
+ for (;;) {
+ if (!*x && !*y) return (1);
+ if (tolower((unsigned char)*x) != tolower((unsigned char)*y))
+ return (0);
+ x++; y++;
+ }
+}
+
/* --- @trywrite@ --- *
*
* Arguments: @admin *a@ = pointer to an admin block
goto again;
if (errno != EAGAIN && errno != EWOULDBLOCK) {
a_destroy(a);
- a_warn("disconnecting admin client due to write errors: %s",
- strerror(errno));
+ a_warn("ADMIN client-read-error -- %s", strerror(errno));
return (-1);
}
}
/*----- Utility functions -------------------------------------------------*/
-/* --- @a_write@ --- *
+/* --- @a_write@, @a_vwrite@ --- *
*
* Arguments: @admin *a@ = admin connection to write to
+ * @const char *tag@ = tag prefix string, or null
* @const char *fmt@ = pointer to format string
+ * @va_list ap@ = arguments in list
* @...@ = other arguments
*
* Returns: ---
* Use: Sends a message to an admin connection.
*/
-static void a_write(admin *a, const char *fmt, ...)
+static void a_vwrite(admin *a, const char *tag, const char *fmt, va_list ap)
{
- va_list ap;
dstr d = DSTR_INIT;
+ if (tag) {
+ dstr_puts(&d, tag);
+ if (fmt)
+ dstr_putc(&d, ' ');
+ }
+ if (fmt)
+ dstr_vputf(&d, fmt, &ap);
+ dstr_putc(&d, '\n');
+ dosend(a, d.buf, d.len);
+ dstr_destroy(&d);
+}
+
+static void a_write(admin *a, const char *tag, const char *fmt, ...)
+{
+ va_list ap;
va_start(ap, fmt);
- dstr_vputf(&d, fmt, &ap);
+ a_vwrite(a, tag, fmt, ap);
va_end(ap);
- dosend(a, d.buf, d.len);
+}
+
+/* --- @a_ok@, @a_info@, @a_fail@ --- *
+ *
+ * Arguments: @admin *a@ = connection
+ * @const char *fmt@ = format string
+ * @...@ = other arguments
+ *
+ * Returns: ---
+ *
+ * Use: Convenience functions for @a_write@.
+ */
+
+static void a_ok(admin *a) { a_write(a, "OK", 0); }
+
+static void a_info(admin *a, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ a_vwrite(a, "INFO", fmt, ap);
+ va_end(ap);
+}
+
+static void a_fail(admin *a, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ a_vwrite(a, "FAIL", fmt, ap);
+ va_end(ap);
+}
+
+/* --- @a_alert@, @a_valert@, @a_rawalert@ --- *
+ *
+ * Arguments: @unsigned f_and, f_eq@ = filter for connections
+ * @const char *tag@ = tag prefix string
+ * @const char *fmt@ = pointer to format string
+ @ @const char *p@ = pointer to raw string
+ * @size_t sz@ = size of raw string
+ * @va_list ap@ = arguments in list
+ * @...@ = other arguments
+ *
+ * Returns: ---
+ *
+ * Use: Write a message to all admin connections matched by the given
+ * filter.
+ */
+
+static void a_rawalert(unsigned f_and, unsigned f_eq, const char *tag,
+ const char *p, size_t sz)
+{
+ admin *a, *aa;
+ dstr d = DSTR_INIT;
+
+ if (!(flags & F_INIT))
+ return;
+ if (tag) {
+ dstr_puts(&d, tag);
+ if (p)
+ dstr_putc(&d, ' ');
+ }
+ if (p)
+ dstr_putm(&d, p, sz);
+ dstr_putc(&d, '\n');
+ p = d.buf;
+ sz = d.len;
+ for (a = admins; a; a = aa) {
+ aa = a->next;
+ if ((a->f & f_and) == f_eq)
+ dosend(a, d.buf, d.len);
+ }
dstr_destroy(&d);
}
+static void a_valert(unsigned f_and, unsigned f_eq, const char *tag,
+ const char *fmt, va_list ap)
+{
+ dstr d = DSTR_INIT;
+
+ if (!(flags & F_INIT))
+ return;
+ if (fmt)
+ dstr_vputf(&d, fmt, &ap);
+ a_rawalert(f_and, f_eq, tag, fmt ? d.buf : 0, fmt ? d.len : 0);
+ dstr_destroy(&d);
+}
+
+#if 0 /*unused*/
+static void a_alert(unsigned f_and, unsigned f_eq, const char *tag,
+ const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ a_valert(f_and, f_eq, tag, fmt, ap);
+ va_end(ap);
+}
+#endif
+
/* --- @a_warn@ --- *
*
* Arguments: @const char *fmt@ = pointer to format string
void a_warn(const char *fmt, ...)
{
va_list ap;
- admin *a, *aa;
- dstr d = DSTR_INIT;
- if (flags & F_INIT)
- dstr_puts(&d, "WARN ");
va_start(ap, fmt);
- dstr_vputf(&d, fmt, &ap);
- va_end(ap);
- if (!(flags & F_INIT))
- moan("%s", d.buf);
+ if (flags & F_INIT)
+ a_valert(0, 0, "WARN", fmt, ap);
else {
- dstr_putc(&d, '\n');
- for (a = admins; a; a = aa) {
- aa = a->next;
- dosend(a, d.buf, d.len);
- }
+ fprintf(stderr, "%s: ", QUIS);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
}
- dstr_destroy(&d);
+ va_end(ap);
}
/* --- @a_trace@ --- *
*
* Returns: ---
*
- * Use: Custom trace output handler.
+ * Use: Custom trace output handler. Sends trace messages to
+ * interested admin connections.
*/
#ifndef NTRACE
static void a_trace(const char *p, size_t sz, void *v)
{
- dstr d = DSTR_INIT;
- admin *a, *aa;
-
- dstr_puts(&d, "TRACE ");
- dstr_putm(&d, p, sz);
- dstr_putc(&d, '\n');
- for (a = admins; a; a = aa) {
- aa = a->next;
- dosend(a, d.buf, d.len);
- }
- dstr_destroy(&d);
+ a_rawalert(AF_TRACE, AF_TRACE, "TRACE", p, sz);
}
#endif
+/* --- @a_notify@ --- *
+ *
+ * Arguments: @const char *fmt@ = pointer to format string
+ * @...@ = other arguments
+ *
+ * Returns: ---
+ *
+ * Use: Sends a notification to interested admin connections.
+ */
+
+void a_notify(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ a_valert(AF_NOTE, AF_NOTE, "NOTE", fmt, ap);
+ va_end(ap);
+}
+
/* --- @a_quit@ --- *
*
* Arguments: ---
case SIGTERM: p = "SIGTERM"; break;
case SIGINT: p = "SIGINT"; break;
default:
- sprintf(buf, "signal %i", sig);
+ sprintf(buf, "%i", sig);
p = buf;
break;
}
- a_warn("shutting down on %s", p);
+ a_warn("SERVER quit signal %s", p);
a_quit();
}
static void a_sighup(int sig, void *v)
{
- a_warn("received SIGHUP: ignoring");
+ a_warn("SERVER ignore signal SIGHUP");
}
/*----- Adding peers ------------------------------------------------------*/
TIMER;
sel_rmtimer(&a->t);
if (!h)
- a_write(a, "FAIL couldn't resolve hostname `%s'\n", a->paddr);
+ a_fail(a, "resolve-error %s", a->paddr);
else if (p_find(a->pname))
- a_write(a, "FAIL peer `%s' already registered\n", a->pname);
+ a_fail(a, "peer-exists %s", a->pname);
else {
memcpy(&a->peer.sin.sin_addr, h->h_addr, sizeof(struct in_addr));
if (!p_create(a->pname, &a->peer.sa, a->sasz))
- a_write(a, "FAIL couldn't create peer\n");
+ a_fail(a, "peer-create-fail %s" a->pname);
else
- a_write(a, "OK\n");
+ a_ok(a);
}
xfree(a->pname);
xfree(a->paddr);
a_lock(a);
T( trace(T_ADMIN, "admin: %u resolver timeout", a->seq); )
bres_abort(&a->r);
- a_write(a, "FAIL timeout resolving `%s'\n", a->paddr);
+ a_fail(a, "resolver-timeout %s\n", a->paddr);
xfree(a->pname);
xfree(a->paddr);
a->pname = 0;
{
unsigned long pt;
struct timeval tv;
+ unsigned i;
char *p;
/* --- Make sure someone's not got there already --- */
if (p_find(av[0])) {
- a_write(a, "FAIL peer `%s' already registered\n", av[0]);
+ a_fail(a, "peer-exists %s", av[0]);
return;
}
/* --- Fill in the easy bits of address --- */
BURN(a->peer);
+ i = 1;
+ if (mystrieq(av[i], "inet")) i++;
+ if (ac - i != 2) {
+ a_fail(a, "bad-syntax -- add PEER [inet] ADDRESS PORT");
+ return;
+ }
a->peer.sin.sin_family = AF_INET;
a->sasz = sizeof(a->peer.sin);
- pt = strtoul(av[2], &p, 0);
+ pt = strtoul(av[i + 1], &p, 0);
if (*p) {
- struct servent *s = getservbyname(av[2], "udp");
+ struct servent *s = getservbyname(av[i + 1], "udp");
if (!s) {
- a_write(a, "FAIL service `%s' not known\n", av[2]);
+ a_fail(a, "unknown-service %s", av[i + 1]);
return;
}
pt = ntohs(s->s_port);
}
if (pt == 0 || pt >= 65536) {
- a_write(a, "FAIL bad port number %lu\n", pt);
+ a_fail(a, "invalid-port %lu", pt);
return;
}
a->peer.sin.sin_port = htons(pt);
/* --- If the name is numeric, do it the easy way --- */
- if (inet_aton(av[1], &a->peer.sin.sin_addr)) {
+ if (inet_aton(av[i], &a->peer.sin.sin_addr)) {
if (!p_create(av[0], &a->peer.sa, a->sasz))
- a_write(a, "FAIL couldn't create peer\n");
+ a_fail(a, "peer-create-fail %s", a->pname);
else
- a_write(a, "OK\n");
+ a_ok(a);
return;
}
*/
a->pname = xstrdup(av[0]);
- a->paddr = xstrdup(av[1]);
+ a->paddr = xstrdup(av[i]);
selbuf_disable(&a->b);
gettimeofday(&tv, 0);
tv.tv_sec += T_RESOLVE;
/* --- Miscellaneous commands --- */
-#ifndef NTRACE
+/* --- @traceish@ --- *
+ *
+ * Arguments: @admin *a@ = connection to complain on
+ * @unsigned ac@ = number of arguments
+ * @char *av[]@ = vector of arguments
+ * @const char *what@ = what we're messing with
+ * @const trace_opt *tt@ = options table
+ * @unsigned *ff@ = where the flags are
+ *
+ * Returns: Nonzero if anything changed.
+ *
+ * Use: Guts of trace-ish commands like `trace' and `watch'.
+ */
-static void acmd_trace(admin *a, unsigned ac, char *av[])
+static int traceish(admin *a, unsigned ac, char *av[],
+ const char *what, const trace_opt *tt, unsigned *ff)
{
+ int ch = 0;
+
if (!ac || strcmp(av[0], "?") == 0) {
const trace_opt *t;
- a_write(a, "INFO Trace options:\n");
- for (t = tr_opts; t->ch; t++) {
- a_write(a, "INFO %c %c %s\n",
- t->ch, (tr_flags & t->f) == t->f ? '*' : ' ', t->help);
+ a_info(a, "Current %s status:", what);
+ for (t = tt; t->ch; t++) {
+ a_info(a, "%c %c %s",
+ t->ch, (*ff & t->f) == t->f ? '*' : ' ', t->help);
}
} else {
unsigned sense = 1;
- unsigned f = tr_flags;
- const trace_opt *tt;
+ unsigned f = *ff;
+ const trace_opt *t;
char *p = av[0];
while (*p) {
case '+': sense = 1; break;
case '-': sense = 0; break;
default:
- for (tt = tr_opts; tt->ch; tt++) {
- if (tt->ch == *p) {
- if (sense) f |= tt->f;
- else f &= ~tt->f;
+ for (t = tt; t->ch; t++) {
+ if (t->ch == *p) {
+ if (sense) f |= t->f;
+ else f &= ~t->f;
goto tropt_ok;
}
}
- a_write(a, "FAIL unknown trace option `%c'\n", *p);
- return;
+ a_fail(a, "bad-%s-option %c", what, *p);
+ return (0);
tropt_ok:;
break;
}
p++;
}
- tr_flags = f;
- trace_level(tr_flags);
+ *ff = f;
+ ch = 1;
}
- a_write(a, "OK\n");
+ a_ok(a);
+ return (ch);
+}
+
+#ifndef NTRACE
+
+static void acmd_trace(admin *a, unsigned ac, char *av[])
+{
+ if (traceish(a, ac, av, "trace", tr_opts, &tr_flags))
+ trace_level(tr_flags);
}
#endif
+static void acmd_watch(admin *a, unsigned ac, char *av[])
+{
+ traceish(a, ac, av, "watch", w_opts, &a->f);
+}
+
+static void quotify(dstr *d, const char *p)
+{
+ if (d->len)
+ dstr_putc(d, ' ');
+ if (*p && !p[strcspn(p, "\"' \t\n\v")])
+ dstr_puts(d, p);
+ else {
+ dstr_putc(d, '\"');
+ while (*p) {
+ if (*p == '\\' || *p == '\"')
+ dstr_putc(d, '\\');
+ dstr_putc(d, *p++);
+ }
+ dstr_putc(d, '\"');
+ }
+}
+
+static void alertcmd(admin *a, unsigned f_and, unsigned f_eq,
+ const char *tag, unsigned ac, char *av[])
+{
+ dstr d = DSTR_INIT;
+ unsigned i;
+
+ dstr_puts(&d, "USER");
+ for (i = 0; i < ac; i++)
+ quotify(&d, av[i]);
+ dstr_putz(&d);
+ a_rawalert(f_and, f_eq, tag, d.buf, d.len);
+ dstr_destroy(&d);
+ a_ok(a);
+}
+
+static void acmd_notify(admin *a, unsigned ac, char *av[])
+ { alertcmd(a, AF_NOTE, AF_NOTE, "NOTE", ac, av); }
+static void acmd_warn(admin *a, unsigned ac, char *av[])
+ { alertcmd(a, AF_WARN, AF_WARN, "WARN", ac, av); }
+
static void acmd_port(admin *a, unsigned ac, char *av[])
{
- a_write(a, "INFO %u\nOK\n", p_port());
+ a_info(a, "%u", p_port());
+ a_ok(a);
}
static void acmd_daemon(admin *a, unsigned ac, char *av[])
{
if (flags & F_DAEMON)
- a_write(a, "FAIL already running as a daemon\n");
+ a_fail(a, "already-daemon");
else {
- a_warn("becoming a daemon");
+ a_notify("DAEMON");
if (a_stdin)
a_destroy(a_stdin);
if (u_daemon())
- a_write(a, "FAIL error becoming a daemon: %s", strerror(errno));
+ a_fail(a, "daemon-error -- %s", strerror(errno));
else {
flags |= F_DAEMON;
- a_write(a, "OK\n");
+ a_ok(a);
}
}
}
{
peer *p;
for (p = p_first(); p; p = p_next(p))
- a_write(a, "INFO %s\n", p_name(p));
- a_write(a, "OK\n");
+ a_info(a, "%s", p_name(p));
+ a_ok(a);
}
static void acmd_ifname(admin *a, unsigned ac, char *av[])
peer *p;
if ((p = p_find(av[0])) == 0)
- a_write(a, "FAIL peer `%s' not found\n", av[0]);
- else
- a_write(a, "INFO %s\nOK\n", p_ifname(p));
+ a_fail(a, "unknown-peer %s", av[0]);
+ else {
+ a_info(a, "%s", p_ifname(p));
+ a_ok(a);
+ }
}
static void acmd_addr(admin *a, unsigned ac, char *av[])
const addr *ad;
if ((p = p_find(av[0])) == 0)
- a_write(a, "FAIL peer `%s' not found\n", av[0]);
+ a_fail(a, "unknown-peer %s", av[0]);
else {
ad = p_addr(p);
assert(ad->sa.sa_family == AF_INET);
- a_write(a, "INFO %s %u\nOK\n",
+ a_info(a, "INET %s %u",
inet_ntoa(ad->sin.sin_addr),
(unsigned)ntohs(ad->sin.sin_port));
+ a_ok(a);
}
}
stats *st;
if ((p = p_find(av[0])) == 0)
- a_write(a, "FAIL peer `%s' not found\n", av[0]);
+ a_fail(a, "unknown-peer %s", av[0]);
else {
st = p_stats(p);
- a_write(a, "INFO start-time=%s\n", timestr(st->t_start));
- a_write(a, "INFO last-packet-time=%s\n", timestr(st->t_last));
- a_write(a, "INFO packets-in=%lu bytes-in=%lu\n", st->n_in, st->sz_in);
- a_write(a, "INFO packets-out=%lu bytes-out=%lu\n",
+ a_info(a, "start-time=%s", timestr(st->t_start));
+ a_info(a, "last-packet-time=%s", timestr(st->t_last));
+ a_info(a, "last-keyexch-time=%s", timestr(st->t_kx));
+ a_info(a, "packets-in=%lu bytes-in=%lu", st->n_in, st->sz_in);
+ a_info(a, "packets-out=%lu bytes-out=%lu",
st->n_out, st->sz_out);
- a_write(a, "INFO keyexch-packets-in=%lu keyexch-bytes-in=%lu\n",
+ a_info(a, "keyexch-packets-in=%lu keyexch-bytes-in=%lu",
st->n_kxin, st->sz_kxin);
- a_write(a, "INFO keyexch-packets-out=%lu keyexch-bytes-out=%lu\n",
+ a_info(a, "keyexch-packets-out=%lu keyexch-bytes-out=%lu",
st->n_kxout, st->sz_kxout);
- a_write(a, "INFO ip-packets-in=%lu ip-bytes-in=%lu\n",
+ a_info(a, "ip-packets-in=%lu ip-bytes-in=%lu",
st->n_ipin, st->sz_ipin);
- a_write(a, "INFO ip-packets-out=%lu ip-bytes-out=%lu\n",
+ a_info(a, "ip-packets-out=%lu ip-bytes-out=%lu",
st->n_ipout, st->sz_ipout);
- a_write(a, "INFO rejected-packets=%lu\n", st->n_reject);
- a_write(a, "OK\n");
+ a_info(a, "rejected-packets=%lu", st->n_reject);
+ a_ok(a);
}
}
{
peer *p;
if ((p = p_find(av[0])) == 0)
- a_write(a, "FAIL peer `%s' not found\n", av[0]);
+ a_fail(a, "unknown-peer %s", av[0]);
else {
p_destroy(p);
- a_write(a, "OK\n");
+ a_ok(a);
}
}
static void acmd_quit(admin *a, unsigned ac, char *av[])
{
- a_warn("closing down on admin request");
- a_write(a, "OK\n");
+ a_warn("SERVER quit admin-request");
+ a_ok(a);
a_quit();
}
+static void acmd_version(admin *a, unsigned ac, char *av[])
+{
+ a_info(a, "%s %s", PACKAGE, VERSION);
+ a_ok(a);
+}
+
/* --- The command table and help --- */
typedef struct acmd {
static const acmd acmdtab[] = {
{ "help", "help", 0, 0, acmd_help },
+ { "version", "version", 0, 0, acmd_version },
#ifndef NTRACE
{ "trace", "trace [OPTIONS]", 0, 1, acmd_trace },
#endif
+ { "watch", "watch [OPTIONS]", 0, 1, acmd_watch },
+ { "notify", "notify MESSAGE ...", 1, 0xffff, acmd_notify },
+ { "warn", "warn MESSAGE ...", 1, 0xffff, acmd_warn },
{ "port", "port", 0, 0, acmd_port },
{ "daemon", "daemon", 0, 0, acmd_daemon },
{ "list", "list", 0, 0, acmd_list },
{ "addr", "addr PEER", 1, 1, acmd_addr },
{ "stats", "stats PEER", 1, 1, acmd_stats },
{ "kill", "kill PEER", 1, 1, acmd_kill },
- { "add", "add PEER ADDR PORT", 3, 3, acmd_add },
+ { "add", "add PEER ADDR ...", 2, 0xffff, acmd_add },
{ "quit", "quit", 0, 0, acmd_quit },
{ 0, 0, 0, 0, 0 }
};
{
const acmd *c;
for (c = acmdtab; c->name; c++)
- a_write(a, "INFO %s\n", c->help);
- a_write(a, "OK\n");
+ a_info(a, "%s", c->help);
+ a_ok(a);
}
/*----- Connection handling -----------------------------------------------*/
{
admin *a = vp;
const acmd *c;
- char *av[4];
+ char *av[16];
size_t ac;
TIMER;
a_destroy(a);
return;
}
- ac = str_qsplit(p, av, 4, 0, STRF_QUOTE);
+ ac = str_qsplit(p, av, 16, 0, STRF_QUOTE);
if (!ac)
return;
- for (p = av[0]; *p; p++) *p = tolower((unsigned char)*p);
for (c = acmdtab; c->name; c++) {
- if (strcmp(av[0], c->name) == 0) {
+ if (mystrieq(av[0], c->name)) {
ac--;
if (c->argmin > ac || ac > c->argmax)
- a_write(a, "FAIL syntax: %s\n", c->help);
+ a_fail(a, "bad-syntax -- %s", c->help);
else {
a_lock(a);
c->func(a, ac, av + 1);
return;
}
}
- a_write(a, "FAIL unknown command `%s'\n", av[0]);
+ a_fail(a, "unknown-command %s", av[0]);
}
/* --- @a_create@ --- *
*
* Arguments: @int fd_in, fd_out@ = file descriptors to use
+ * @unsigned f@ = initial flags to set
*
* Returns: ---
*
* Use: Creates a new admin connection.
*/
-void a_create(int fd_in, int fd_out)
+void a_create(int fd_in, int fd_out, unsigned f)
{
admin *a = CREATE(admin);
+
T( static unsigned seq = 0;
a->seq = seq++; )
T( trace(T_ADMIN, "admin: accepted connection %u", a->seq); )
a->pname = 0;
- a->f = 0;
+ a->f = f;
if (fd_in == STDIN_FILENO)
a_stdin = a;
fdflags(fd_in, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
if ((nfd = accept(fd, (struct sockaddr *)&sun, &sz)) < 0) {
if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK &&
errno != ECONNABORTED && errno != EPROTO)
- a_warn("accept admin connection failed: %s", strerror(errno));
+ a_warn("ADMIN accept-error -- %s", strerror(errno));
return;
}
- a_create(nfd, nfd);
+ a_create(nfd, nfd, 0);
}
/* --- @a_daemon@ --- *
sig_add(&s_term, SIGTERM, a_sigdie, 0);
sig_add(&s_hup, SIGHUP, a_sighup, 0);
+ signal(SIGPIPE, SIG_IGN);
sigaction(SIGINT, 0, &sa);
if (sa.sa_handler != SIG_IGN)
sig_add(&s_int, SIGINT, a_sigdie, 0);
f |= f_uclose;
} else {
p[len] = '\n';
- write(fd, p, len + 1);
+ errno = EIO;
+ if (write(fd, p, len + 1) != len + 1)
+ moan("write failed: %s", strerror(errno));
+ }
+}
+
+static void setup(const char *cmd)
+{
+ dstr d = DSTR_INIT;
+ char ch;
+ char *p, *q;
+ int n;
+
+ dstr_puts(&d, cmd);
+ dstr_putc(&d, '\n');
+ errno = EIO; /* Relax: be vague */
+ if (write(fd, d.buf, d.len) != d.len) {
+ die(EXIT_FAILURE, "error sending setup command `%s': %s",
+ cmd, strerror(errno));
+ }
+ dstr_reset(&d);
+ for (;;) {
+ n = read(fd, &ch, 1);
+ if (!n)
+ die(EXIT_FAILURE, "unexpected EOF during setup");
+ if (n < 0) {
+ die(EXIT_FAILURE, "error receiving reply to `%s': %s",
+ cmd, strerror(errno));
+ }
+ if (d.len < 256)
+ dstr_putc(&d, ch);
+ if (ch == '\n') {
+ p = d.buf;
+ q = str_getword(&p);
+ if (!q)
+ ;
+ else if (strcmp(q, "OK") == 0)
+ return;
+ else if (strcmp(q, "FAIL") == 0)
+ die(EXIT_FAILURE, "setup command `%s' failed: %s", cmd, p);
+ dstr_reset(&d);
+ }
}
}
\n\
-D, --daemon Become a background task after connecting.\n\
-d, --directory=DIR Select current directory [default " CONFIGDIR "].\n\
--a, --admin-socket=FILE Select socket to connect to
+-a, --admin-socket=FILE Select socket to connect to\n\
[default " SOCKETDIR "/tripesock].\n\
-P, --pidfile=FILE Write process-id to FILE.\n\
\n\
fprintf(pidfp, "%li\n", (long)getpid());
fclose(pidfp);
}
+ signal(SIGPIPE, SIG_IGN);
/* --- If we're meant to be interactive, do that --- */
+ if (optind == argc)
+ setup("WATCH -A+tw");
if (!(f & f_noinput) && optind == argc) {
sel_state sel;
selbuf bu, bs;
if (optind < argc) {
dstr d = DSTR_INIT;
+ setup((f & f_warn) ? "WATCH -A+w" : "WATCH -A");
dstr_puts(&d, argv[optind++]);
while (optind < argc) {
dstr_putc(&d, ' ');
dstr_puts(&d, argv[optind++]);
}
dstr_putc(&d, '\n');
- write(fd, d.buf, d.len);
- shutdown(fd, 1);
+ errno = EIO;
+ if (write(fd, d.buf, d.len) != d.len || shutdown(fd, 1))
+ die(EXIT_FAILURE, "write failed: %s", strerror(errno));
dstr_destroy(&d);
f |= f_command;
}
dnl -*-autoconf-*-
dnl
-dnl $Id: configure.in,v 1.16 2004/04/19 07:44:16 mdw Exp $
+dnl $Id$
dnl
dnl Configuration script for TrIPE
dnl
AC_PROG_MAKE_SET
AC_PROG_CC
AM_PROG_LIBTOOL
+AC_CHECK_HEADERS([stdarg.h])
mdw_GCC_FLAGS([-Wall])
mdw_OPT_TRACE
2.[4-9].* | 2.[1-9][0-9]*.* | [3-9].* | [1-9][0-9]*.*)
changequote([,])dnl
tun=linux
- AC_DEFINE([TUN_TYPE], [TUN_LINUX])
+ AC_DEFINE([TUN_TYPE], [TUN_LINUX],
+ [Set to the tunnel driver for your OS. See TUN_* in tripe.h.])
;;
*)
tun=unet
- AC_DEFINE([TUN_TYPE], [TUN_UNET])
+ AC_DEFINE([TUN_TYPE], [TUN_UNET],
+ [Set to the tunnel driver for your OS. See TUN_* in tripe.h.])
;;
esac
;;
*bsd*)
tun=bsd
- AC_DEFINE([TUN_TYPE], [TUN_BSD])
+ AC_DEFINE([TUN_TYPE], [TUN_BSD],
+ [Set to the tunnel driver for your OS. See TUN_* in tripe.h.])
;;
*)
AC_MSG_ERROR([Unsupported OS: no tunnel interface available])
mdw_cv_ethereal_plugin_dir="failed"
ethprefix=none
for i in "${prefix}" /usr/local /usr `echo $PATH | tr : " "`; do
- if test -x "$i/bin/ethereal"; then
+ if test -x "$i/bin/tethereal"; then
ethprefix=$i
break
fi
done
if test "$ethprefix" != none; then
- ethbin=$ethprefix/bin/ethereal
- ethver=`$ethbin -v | sed 's/^[^ ]* \([0-9A-Za-z.]*\).*$/\1/'`
+ ethbin=$ethprefix/bin/tethereal
+ ethver=`$ethbin -v | sed 's/^[^ ]* \([0-9A-Za-z.]*\).*$/\1/;q'`
dir=$ethprefix/lib/ethereal/plugins/$ethver
if test -d "$dir"; then
mdw_cv_ethereal_plugin_dir=$dir
AC_TRY_COMPILE([
#include <netinet/in.h>
#include <glib.h>
-#include <epan/packet.h>
+#include <ethereal/config.h>
+#include <ethereal/epan/packet.h>
], [
dissector_handle_t dh;
- dh = creat_dissector_handle(0, 0);
+ dh = create_dissector_handle(0, 0);
], [bad=false; break])
done
if test $bad = false; then
fi
if test "$ethereal" = true; then
- AC_CACHE_CHECK([whether the Ethereal headers are broken],
- [mdw_cv_ethereal_buggered], [
- CFLAGS="$GLIB_CFLAGS $i"
- AC_TRY_COMPILE([
-#include <netinet/in.h>
-#include <glib.h>
-#include <epan/packet.h>
-#include <plugins/plugin_api.h>
-], [
- G_MODULE_EXPORT void plugin_init(plugin_address_table_t *pat)
- {
- plugin_address_table_init(pat);
- }
- ], [mdw_cv_ethereal_buggered=no], [mdw_cv_ethereal_buggered=yes])
- CFLAGS=$mdw_CFLAGS
- ])
- if test $mdw_cv_ethereal_buggered = yes; then
- AC_DEFINE(ETHEREAL_BUGGERED)
- fi
-
ETHEREAL_CFLAGS="$CFLAGS $GLIB_CFLAGS $mdw_cv_ethereal_includes"
AC_SUBST(ETHEREAL_CFLAGS)
AC_SUBST(ETHEREAL_PLUGIN_DIR)
AC_MSG_ERROR([failed to configure Ethereal plugin])
fi
+AH_TEMPLATE([CONFIGDIR],
+ [Tripe should look here for keys and other configuration.])
+AH_TEMPLATE([SOCKETDIR],
+ [Tripe should make its administration socket here.])
mdw_DEFINE_PATHS([
mdw_DEFINE_PATH([CONFIGDIR], [$configdir])
mdw_DEFINE_PATH([SOCKETDIR], [$socketdir])
Priority: extra
Maintainer: Mark Wooding <mdw@nsict.org>
Build-Depends: catacomb-dev (>= 2.1.0), mlib-dev (>= 2.0.3),
- ethereal-dev, debhelper (>= 4.0.2)
+ tethereal, ethereal-dev (>= 0.10.10), debhelper (>= 4.0.2)
Standards-Version: 3.1.1
Package: tripe
.TL "Straylight/Edgeware" "Mark Wooding"
.TL "Request for Comments: XXXX" "Straylight/Edgeware"
.TL "" "11 April 2003"
-
-
+.
.TT XXXX Wooding "April 2003" \
"TrIPE: The Trivial IP Encryption Protocol"
-
-.T0 "Status of this Memo"
-
+.
+.TI 0 "Status of this Memo"
+.P
This memo defines an Experimental Protocol for the Internet community.
This memo does not specify an Internet standard of any kind. Discussion
and suggestions for improvement are requested. Distribution of this
memo is unlimited.
-
+.P
.T0 "Introduction"
-
+.P
TrIPE is a simple protocol which enables IP datagrams (or other data) to
be exchanged between a pair of hosts over a hostile network while
maintaining the properties of secrecy and authenticity; i.e., that the
content of the datagrams cannot be determined by eavesdroppers on the
network, and that either endpoint can determine whether a datagram
received is an unaltered copy of one that was sent by the other.
-
+.P
While similar services are provided by other protocols (e.g., [IPSEC]),
they tend to be very complicated and difficult to analyze (see, for
example, [IPSEC-EVAL]). By contrast, TrIPE attempts to get away with
doing as little as possible. There are no negotiations to decide which
ciphers are to be used: these things are defined in the protocol
specification. There is only one key-exchange algorithm defined.
-
+.P
In addition to making analysis easier, a simpler protocol also helps
reduce the complexity of implementations: this makes implementation
errors less likely, and makes auditing an implementation for security
holes a more realistic proposition.
-
+.P
.T0 "Interpretation"
-
+.P
The key words `MUST', `MUST NOT', `REQUIRED', `SHALL', `SHALL NOT',
`SHOULD', `SHOULD NOT', `RECOMMENDED', `MAY', and `OPTIONAL' in this
document are to be interpreted as described in [REQ].
-
+.P
.T0 "Protocol overview"
-
+.P
The TrIPE protocol sets up a secure point-to-point channel between two
peer hosts, through which IP datagrams may be passed securely.
-
+.P
All TrIPE messages are sent as UDP datagrams. No UDP port has been
registered for TrIPE yet.
-
+.P
When a pair of peer hosts are made aware of each other, they begin a key
negotiation, using an authenticated Diffie-Hellman key exchange
protocol. This enables them to agree a
whichever happens first. Before the current keyset expires, a new key
negotation is started, so that the peers can seamlessly start using the
new keys before the old ones become invalid.
-
+.P
.T1 "Keysets"
-
+.P
A
.I keyset
is a collection of symmetric keys and associated state information. The
items required, and the symbolic names by which they are described in
this document are:
-
.UL
.LI
.B "Incoming and outgoing encryption keys"
and
.K' c "" )
.LE
-
+.P
.T1 "Key exchange"
-
-
-
+.
+.
+.P
.T0 "Data representation and notation"
+.
.de SD
+.P
.LS
..
.de SM
.SM "\\$1" "\\$2" "\\$3"
.LS 2n
..
-
+.P
We need to deal with a number of data items during the protocol.
.if t \{\
Object names are given in
.I alpha' )
indicates the peer's corresponding value. If a compound data item name
is primed, toggle the primed-ness of the components.
-
+.P
Data objects are given types which determine their representation in
protocol messages. Type names are given in
.B UPPERCASE .
-
+.P
.T1 "Atomic data items"
-
.DL
.DI OCTET
A single octet, representing a value between 0 and 255.
-
.DI U16
A pair of octets, representing a value between 0 and 65535. The more
significant octet appears first.
-
.DI U32
Four octets, representing a value between 0 and 4294967295. More
significant octets appear first.
-
.DI "STRING \fIn\fR\fB"
A string of
.I n
octets. A
.B STRING
does not have a numeric value.
-
.DI MP
A nonnegative multiprecision integer. Let
.I n
.I z
be the number of octets required to represent
.I n
-in base-256 format with no leading zeroes; i.e., if
-.I n
-= 0, then
+in base-256 format with no leading zeroes, except that if
+.I n
+= 0
+then
.I z
-= 0; otherwise
+= 1; in other cases,
.I z
is the unique integer such that
.ie t 256\*(^(\fIz\fP\-1\*(^) \(<= \fIn\fP < 256\*(^(\fIz\fP\*(^).
.I n ,
most significant first.
.LE
-
+.P
.T1 "Structured data items"
-
+.P
A
.I structure
is a compound object which is simply the concatenation of a number of
its component objects. Structures are used directly as messages, and
indirectly as things to be hashed or encrypted.
-
+.P
The notation
-
.SD
. ST STRUCT . kx-cookie
. SR OCTET . 0x11
. SM STRING 20 hash
. LE
.LE
-
+.P
indicates that
.I msg-cookie
consists of the two items
-
-
-
-
+.
+.f
+.
+.SD
+. ST STRUCT . msg-packet
+. SR OCTET . 0x00
+. br
+payload
+. LE
+.LE
+.
.SD
. ST STRUCT . kx-prechal
. SR OCTET . 0x10
. SM MP . c
. LE
.LE
-
+.
.SD
. ST STRUCT . kx-cookie
. SR OCTET . 0x11
. LE
. LE
.LE
-
+.P
.T0 "Security considerations"
-
+.P
This memo describes a cryptographic protocol for ensuring secrecy and
integrity of communications between network hosts. From this point of
view, it is entirely about security.
-
+.P
Before deploying TrIPE on their own systems, administrators ought to
satisfy themselves that the cryptographic algorithms used are
sufficiently strong for their purposes, and that their implementation of
the TrIPE software has come from a trustworthy source. They should also
ensure that they have adequate procedures in place for transporting
public keys without a risk of them being modified by adversaries.
-
+.P
.T0 "References"
-
.BS IPSEC-EVAL
.BR IPSEC
Kent, S., Atkinson, R., `Security Architecture for the Internet
Protocol', RFC 2401, November 1998.
-
+.
.BR IPSEC-EVAL
Ferguson, N., Schneier, B., `A Cryptographic Evaluation of IPsec',
December 1999.
-
+.
.BR REQ
Bradner, S., `Key words for use in RFCs to Indicate Requirement Levels',
BCP 14, RFC 2119, March 1997.
. if \n(.g \{\
. fam P
. \}
+. ps 10
+. vs 12
.\}
.el \{\
. po 0
.de I
.Ff I I "\\$1" "\\$2"
..
-.de P
+.de PF
.Ff P P "\\$1" "\\$2"
..
.de C
.Ff (HI I "\\$1" "\\$2"
..
.
+.\"----- Paragraphs ---------------------------------------------------------
+.
+.ie t \{\
+. de P
+. sp .67
+..
+.\}
+.el \{\
+. de P
+. sp 1
+..
+.\}
+.
.\"----- Titling ------------------------------------------------------------
.
.\" .TL left right
.de TL
.B
.tl '\\$1''\\$2'
-.P
+.PF
..
.
.\" .TT number author title
.ce
\&\\$4
.ps
-.P
+.PF
.fi
.in +3m
..
. el \&\\$3.\ \ \c
.\}
\&\\$2
-.P
+.PF
.ps
.br
..
.\" Puts in the header for a bibliography item.
.de BR
.ne 2
+.P
.ti -\\n(bwu
[\\$1]\h'\\n(bwu-\\w'[\\$1]'u'\c
..
.\" .DI name
.\" Starts a definition item for `name'
.de DI
-.br
+.P
.B
\h'-1i'\\$1\c
.ie \w'\\$1\h'2n''u<1i \h'1i-\w'\\$1'u'\c
.el .br
-.P
+.PF
..
.
.\" .LI [tag]
.\" Starts a new list item
.de LI
-.br
+.P
.ie '\\$1'' .ds LL \\*L
.el .ds LL \\$1
\h'-\w'\\*(LL\h'1n''u'\\*(LL\h'1n'\c
.\" .QS
.\" Starts a display.
.de QS
+.P
.in +4n
.ll -4n
..
.B OK
response contains no further data. A
.B FAIL
-code is followed by a human-readable explanation of why the command
+code is followed by a machine-readable explanation of why the command
failed.
.PP
-In addition, there are two types of asynchronous `responses', which
+In addition, there are three types of asynchronous messages which
aren't associated with any particular command. The
.B WARN
-response contains a human-readable message warning of an error
+message contains a machine-readable message warning of an error
encountered while processing a command, unexpected or unusual behaviour
by a peer, or a possible attack by an adversary. Under normal
conditions, the server shouldn't emit any warnings. The
.B TRACE
-response contains a human-readable tracing message containing diagnostic
+message contains a human-readable tracing message containing diagnostic
information. Trace messages are controlled using the
.B \-T
command-line option to the server, or the
.B TRACE
administration command (see below). Support for tracing can be disabled
when the package is being configured, and may not be available in your
-version.
-.SS "Command reference"
+version. Finally, the
+.B NOTE
+message is a machine-readable notification about some routine but
+interesting event such as creation or destruction of peers.
+.PP
+The presence of asynchronous messages can be controlled using the
+.B WATCH
+command.
+.SS "Network addresses"
+A network address is a sequence of words. The first is a token
+identifying the network address family. The length of an address and
+the meanings of the subsequent words depend on the address family.
+Address family tokens are not case-sensitive on input; on output, they
+are always in upper-case.
+.PP
+At present, only one address family is understood.
+.TP
+.BI "INET " address " " port
+An Internet socket, naming an IPv4 address and UDP port. On output, the
+address is always in numeric dotted-quad form, and the port is given as
+a plain number. On input, DNS hostnames and symbolic port names are
+permitted. Name resolution does not block the main server, but will
+block the requesting client. This hopefully makes life simpler for
+stupid clients. Complex clients which don't wish to be held up can open
+extra connections or do the resolution themselves.)
+.PP
+If, on input, no recognised address family token is found, the following
+words are assumed to represent an
+.B INET
+address.
+.SH "COMMAND REFERENCE"
The commands provided are:
.TP
+.BI "ADD " peer " " address\fR...
+Adds a new peer. The peer is given the name
+.IR peer ;
+the peer's public key is assumed to be in the file
+.B keyring.pub
+(or whatever alternative file was specified in the
+.B \-K
+option on the command line). The
+.I address
+is the network address (see above for the format) at which the peer can
+be contacted.
+.TP
+.BI "ADDR " peer
+Emits an
+.B INFO
+line reporting the IP address and port number stored for
+.IR peer .
+.TP
+.B "DAEMON"
+Causes the server to disassociate itself from its terminal and become a
+background task. This only works once. A warning is issued.
+.TP
.B "HELP"
Causes the server to emit an
.B INFO
line for each command it supports. Each line lists the command name,
followed by the names of the arguments. This may be helpful as a memory
aid for interactive use, or for program clients probing for features.
+.TP
+.BI "IFNAME " peer
+Emits an
+.B INFO
+line containing the name of the network interface used to collect IP
+packets which are to be encrypted and sent to
+.IR peer .
+Used by configuration scripts so that they can set up routing tables
+appropriately after adding new peers.
+.TP
+.BI "KILL " peer
+Causes the server to forget all about
+.IR peer .
+All keys are destroyed, and no more packets are sent. No notification
+is sent to the peer: if it's important that the peer be notified, you
+must think of a way to do that yourself.
+.TP
+.B "LIST"
+For each currently-known peer, an
+.B INFO
+line is written containing the peer's name, as given to
+.BR ADD .
+.TP
+.B "PORT"
+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.
+.TP
+.B "QUIT"
+Instructs the server to exit immediately. A warning is sent.
+.TP
+.BI "STATS " peer
+Emits a number of
+.B INFO
+lines, each containing one or more statistics in the form
+.IB name = value \fR.
+The statistics-gathering is experimental and subject to change.
.TP
.BR "TRACE " [\fIoptions\fP]
A trace argument consists of a string of letters (listed below)
.B x
or
.BR m .
+.TP
+.B A
+All of the above.
.RE
.TP
-.B "PORT"
-Emits an
+.BR "WATCH " [\fIoptions\fP]
+Enables or disables asynchronous messages
+.IR "for the current connection only" .
+This command has no effect on other connections. A watch argument
+consists of a string of letters (listed below) selecting message types,
+optionally interspersed with
+.RB ` + '
+to enable, or
+.RB ` \- '
+to disable, the subsequently listed types, similar to
+.B trace
+above. The default watch state for the connection the server opens
+automatically on stdin/stdout is to show warnings and trace messages;
+other connections show no asynchronous messages. (This is done in order
+to guarantee that a program reading the server's stdout does not miss
+any warnings.)
+.RS
+.PP
+Currently, the following watch options are supported:
+.TP
+.B t
+.B TRACE
+messages.
+.TP
+.B n
+.B NOTE
+messages.
+.TP
+.B w
+.B WARN
+messages.
+.TP
+.B a
+All of the above.
+.RE
+.TP
+.B "VERSION"
+Causes the server to emit an
.B INFO
-line containing just the number of the UDP port used by the
+line stating its software version, as two words: the server name, and
+its version string. The server name
.B tripe
-server. If you've allowed your server to allocate a port dynamically,
-this is how to find out which one it chose.
+is reserved to the Straylight/Edgeware implementation.
+.SH "ERROR MESSAGES"
+The following
+.B FAIL
+messages are sent to clients as a result of errors during command
+processing.
.TP
-.B "DAEMON"
-Causes the server to disassociate itself from its terminal and become a
-background task. This only works once. A warning is issued.
+.BI "already-daemon"
+(For
+.BR DAEMON .)
+The
+.B tripe
+server is already running as a daemon.
.TP
-.B "LIST"
-For each currently-known peer, an
-.B INFO
-line is written containing the peer's name, as given to
-.BR ADD .
-.TP
-.BI "IFNAME " peer
-Emits an
-.B INFO
-line containing the name of the network interface used to collect IP
-packets which are to be encrypted and sent to
-.IR peer .
-Used by configuration scripts so that they can set up routing tables
-appropriately after adding new peers.
+.BI "bad-syntax \-\- " message
+(For any command.) The command couldn't be understood: e.g., the number
+of arguments was wrong.
.TP
-.BI "ADDR " peer
-Emits an
-.B INFO
-line reporting the IP address and port number stored for
+.BI "bad-trace-option " char
+(For
+.BR TRACE .)
+An unknown trace option was requested.
+.TP
+.BI "bad-watch-option " char
+(For
+.BR WATCH .)
+An unknown watch option was requested.
+.TP
+.BI "daemon-error \-\- " message
+(For
+.BR DAEMON .)
+An error occurred during the attempt to become a daemon, as reported by
+.IR message .
+.TP
+.BI "invalid-port " number
+(For
+.BR ADD .)
+The given port number is out of range.
+.TP
+.BI "peer-create-fail " peer
+(For
+.BR ADD .)
+Adding
+.I peer
+failed for some reason. A warning should have been emitted explaining
+why.
+.TP
+.BI "peer-exists " peer
+(For
+.BR ADD .)
+There is already a peer named
.IR peer .
.TP
-.BI "STATS " peer
-Emits a number of
-.B INFO
-lines, each containing one or more statistics in the form
-.IB name = value \fR.
-The statistics-gathering is experimental and subject to change.
+.BI "resolve-error " hostname
+(For
+.BR ADD .)
+The DNS name
+.I hostname
+could not be resolved.
+.TP
+.BI "resolver-timeout " hostname
+(For
+.BR ADD .)
+The DNS name
+.I hostname
+took too long to resolve.
+.TP
+.BI "unknown-command " token
+The command
+.B token
+was not recognised.
+.TP
+.BI "unknown-peer " name
+(For
+.BR ADDR ,
+.BR IFNAME ,
+.BR KILL ,
+and
+.BR STATS .)
+There is no peer called
+.IR name .
+.TP
+.BI "unknown-service " service
+(For
+.BR ADD .)
+The service name
+.I service
+couldn't be found in
+.BR /etc/services .
+.SH "NOTIFICATIONS"
+The following notifications are sent to clients who request them.
+.TP
+.BI "ADD " peer " " address \fR...
+A new peer has been added. The peer's name is
+.I peer
+and its network address is
+.IR address .
+.TP
+.BI "DAEMON"
+The server has forked off into the sunset and become a daemon.
.TP
.BI "KILL " peer
-Causes the server to forget all about
-.IR peer .
-All keys are destroyed, and no more packets are sent. No notification
-is sent to the peer: if it's important that the peer be notified, you
-must think of a way to do that yourself.
+The peer
+.I peer
+has been killed.
.TP
-.BI "ADD " "peer addr port"
-Adds a new peer. The peer is given the name
-.IR peer ;
-the peer's public key is assumed to be in the file
-.B keyring.pub
-(or whatever alternative file was specified in the
-.B \-K
-option on the command line). The peer's
+.BI "KXDONE " peer
+Key exchange with
+.I peer
+finished successfully.
+.TP
+.BI "KXSTART " peer
+Key exchange with
+.I peer
+has begun or restarted. If key exchange keeps failing, this message
+will be repeated periodically.
+.SH "WARNINGS"
+There are many possible warnings. They are categorized according to
+their first tokens.
+.SS "ABORT warnings"
+These all indicate that the
.B tripe
-implementation may be contacted at the given UDP port and IP address.
+server has become unable to continue. If enabled, the server will dump
+core in its configuration directory.
.TP
-.B "QUIT"
-Instructs the server to exit immediately. A warning is sent.
+.BI "ABORT repeated-select-errors"
+The main event loop is repeatedly failing. If the server doesn't quit,
+it will probably waste all available CPU doing nothing.
+.SS "ADMIN warnings"
+These indicate a problem with the administration socket interface.
+.TP
+.BI "ADMIN accept-error \-\- " message
+There was an error while attempting to accept a connection from a new
+client.
+.TP
+.BI "ADMIN client-read-error \-\- " message
+There was an error sending data to a client. The connection to the
+client has been closed.
+.SS "KEYMGMT warnings"
+These indicate a problem with the keyring files, or the keys stored in
+them.
+.TP
+.BI "KEYMGMT bad-private-key \-\- " message
+The private key could not be read, or failed a consistency check. If
+there was a problem with the file, usually there will have been
+.B key-file-error
+warnings before this.
+.TP
+.BI "KEYMGMT bad-public-keyring \-\- " message
+The public keyring couldn't be read. Usually, there will have been
+.B key-file-error
+warnings before this.
+.TP
+.BI "KEYMGMT key-file-error " file ":" line " \-\- " message
+Reports a specific error with the named keyring file. This probably
+indicates a bug in
+.BR key (1).
+.TP
+.BI "KEYMGMT public-key " tag " " tokens\fR...
+These messages all indicate a problem with the public key named
+.IR tag .
+.TP
+.BI "KEYMGMT public-key " tag " algorithm-mismatch"
+The algorithms specified on the public key don't match the ones for our
+private key. All the peers in a network have to use the same
+algorithms.
+.TP
+.BI "KEYMGMT public-key " tag " bad \-\- " message
+The public key couldn't be read, or is invalid.
+.TP
+.BI "KEYMGMT public-key " tag " bad-public-group-element"
+The public key is invalid. This may indicate a malicious attempt to
+introduce a bogus key.
+.TP
+.BI "KEYMGMT public-key " tag " bad-algorithm-selection"
+The algorithms listed on the public key couldn't be understood. The
+algorithm selection attributes are probably malformed and need fixing.
+.TP
+.BI "KEYMGMT public-key " tag " incorrect-group"
+The public key doesn't use the same group as our private key. All the
+peers in a network have to use the same group.
+.TP
+.BI "KEYMGMT public-key " tag " not-found"
+The public key for peer
+.I tag
+wasn't in the public keyring.
+.TP
+.BI "KEYMGMT public-key " tag " unknown-type"
+The type of the public key isn't understood. Maybe you need to upgrade
+your copy of
+.BR tripe .
+(Even if you do, you'll have to regenerate your keys.)
+.SS "KX warnings"
+These indicate problems during key-exchange. Many indicate either a bug
+in the server (either yours or the remote one), or some kind of attack
+in progress. All name a
+.I peer
+as the second token: this is the peer the packet is apparently from,
+though it may have been sent by an attacker instead.
+.PP
+In the descriptions below,
+.I msgtoken
+is one of the tokens
+.BR pre-challenge ,
+.BR cookie ,
+.BR challenge ,
+.BR reply ,
+.BR switch-rq ,
+or
+.BR switch-ok .
+.TP
+.BI "KX " peer " bad-expected-reply-log"
+The challenges
+.B tripe
+uses in its protocol contain a check value which proves that the
+challenge is honest. This message indicates that the check value
+supplied is wrong: someone is attempting to use bogus challenges to
+persuade your
+.B tripe
+server to leak private key information. No chance!
+.TP
+.BI "KX " peer " decrypt-failed \fR[\fBreply\fR|\fBswitch-ok\fR]"
+A symmetrically-encrypted portion of a key-exchange message failed to
+decrypt.
+.TP
+.BI "KX " peer " invalid " msgtoken
+A key-exchange message was malformed. This almost certainly indicates a
+bug somewhere.
+.TP
+.BI "KX " peer " incorrect \fR[\fBcookie\fR|\fBswitch-rq\fR|\fBswitch-ok\fR]"
+A message didn't contain the right magic data. This may be a replay of
+some old exchange, or random packets being sent in an attempt to waste
+CPU.
+.TP
+.BI "KX " peer " public-key-expired"
+The peer's public key has expired. It's maintainer should have given
+you a replacement before now.
+.TP
+.BI "KX " peer " sending-cookie"
+We've received too many bogus pre-challenge messages. Someone is trying
+to flood us with key-exchange messages and make us waste CPU on doing
+hard asymmetric crypto sums.
+.TP
+.BI "KX " peer " unexpected " msgtoken
+The message received wasn't appropriate for this stage of the key
+exchange process. This may mean that one of our previous packets got
+lost. For
+.BR pre-challenge ,
+it may simply mean that the peer has recently restarted.
+.TP
+.BI "KX " peer " unknown-challenge"
+The peer is asking for an answer to a challenge which we don't know
+about. This may mean that we've been inundated with challenges from
+some malicious source
+.I who can read our messages
+and discarded the valid one.
+.TP
+.BI "KX " peer " unknown-message 0x" nn
+An unknown key-exchange message arrived.
+.SS "PEER warnings"
+These are largely concerned with management of peers and the low-level
+details of the network protocol. The second word is usually the name of
+a peer, or
+.RB ` \- '
+if none is relevant.
+.TP
+.BI "PEER \- unexpected-source " address\fR...
+A packet arrived from
+.I address
+(a network address \(en see above), but no peer is known at that
+address. This may indicate a misconfiguration, or simply be a result of
+one end of a connection being set up before the other.
+.TP
+.BI "PEER " peer " bad-packet no-type"
+An empty packet arrived. This is very strange.
+.TP
+.BI "PEER " peer " bad-packet unknown-category 0x" nn
+The message category
+.I nn
+(in hex) isn't understood. Probably a strange random packet from
+somewhere; could be an unlikely bug.
+.TP
+.BI "PEER " peer " bad-packet unknown-type 0x" nn
+The message type
+.I nn
+(in hex) isn't understood. Probably a strange random packet from
+somewhere; could be an unlikely bug.
+.TP
+.BI "PEER " peer " decrypt-failed"
+An encrypted IP packet failed to decrypt. It may have been mangled in
+transit, or may be a very old packet from an expired previous session
+key. There is usually a considerable overlap in the validity periods of
+successive session keys, so this shouldn't occur unless the key exchange
+takes ages or fails.
+.TP
+.BI "PEER " peer " packet-build-failed"
+There wasn't enough space in our buffer to put the packet we wanted to
+send. Shouldn't happen.
+.TP
+.BI "PEER \- socket-read-error \-\- " message
+An error occurred trying to read an incoming packet.
+.TP
+.BI "PEER " peer " socket-write-error \-\- " message
+An error occurred attempting to send a network packet. We lost that
+one.
+.SS "SERVER warnings"
+These indicate problems concerning the server process as a whole.
+.TP
+.BI "SERVER ignore signal " name
+A signal arrived, but the server ignored it. Currently this happens for
+.B SIGHUP
+because that's a popular way of telling daemons to re-read their
+configuration files. Since
+.B tripe
+re-reads its keyrings automatically and has no other configuration
+files, it's not relevant, but it seemed better to ignore the signal than
+let the server die.
+.TP
+.BI "SERVER quit signal " \fR[\fInn\fR|\fIname\fR]
+A signal arrived and
+.B tripe
+is going to quit.
+.TP
+.BI "SERVER quit admin-request"
+A client of the administration interface issued a
+.B QUIT
+command.
+.TP
+.BI "SERVER select-error \-\- " message
+An error occurred in the server's main event loop. This is bad: if it
+happens too many times, the server will abort.
+.SS "SYMM warnings"
+These are concerned with the symmetric encryption and decryption
+process.
+.TP
+.BI "SYMM replay old-sequence"
+A packet was received with an old sequence number. It may just have
+been delayed or duplicated, or it may have been an attempt at a replay
+attack.
+.TP
+.BI "SYMM replay duplicated-sequence"
+A packet was received with a sequence number we've definitely seen
+before. It may be an accidental duplication because the 'net is like
+that, or a deliberate attempt at a replay.
+.SS "TUN warnings"
+These concern the workings of the system-specific tunnel driver. The
+second word is the name of the tunnel interface in question, or
+.RB ` \- '
+if none.
+.TP
+.BI "TUN \- bsd no-tunnel-devices"
+The driver couldn't find an available tunnel device. Maybe if you
+create some more
+.BI /dev/tun nn
+files, it will work.
+.TP
+.BI "TUN - open-error " device " \-\- " message
+An attempt to open the tunnel device file
+.I device
+failed.
+.TP
+.BI "TUN " ifname " read-error \-\- " message
+Reading from the tunnel device failed.
+.TP
+.BI "TUN \- linux config-error \-\- " message
+Configuring the Linux TUN/TAP interface failed.
+.TP
+.BI "TUN \- unet config-error \-\- " message
+Configuring the Linux Unet interface failed. Unet is obsolete and
+shouldn't be used any more.
+.TP
+.BI "TUN \- unet getinfo-error \-\- " message
+Reading information about the Unet interface failed. Unet is obsolete
+and shouldn't be used any more.
+.TP
+.BI "TUN \- unet ifname-too-long \-\- " message
+The Unet interface's name overflowed, so we couldn't read it properly.
+Unet is obsolete and shouldn't be used any more.
.SH "SEE ALSO"
.BR tripectl (1),
.BR tripe (8).
.PP
-.IR "The Trivial IP Encryption Protocol" ,
+.IR "The Trivial IP Encryption Protocol" .
.SH "AUTHOR"
Mark Wooding, <mdw@nsict.org>
.B "\-u, \-\-usage"
Writes a brief usage summary to standard output and exits with status 0.
.TP
+.B "\-\-tunnel"
+Writes a string to standard output describing the configured tunnelling
+method and exits with status 0. This is intended for the use of the
+start-up script, so that it can check that it will actually work.
+.TP
.B "\-D, \-\-daemon"
Dissociates from its terminal and starts running in the background after
completing the initialization procedure described above. If running as
/* -*-c-*-
*
- * $Id: packet-tripe.c,v 1.4 2004/04/18 18:08:11 mdw Exp $
+ * $Id$
*
* TrIPE protocol dissector for Ethereal
*
#include <glib.h>
#include <gmodule.h>
-#include <epan/packet.h>
-#include <prefs.h>
-
-#ifdef ETHEREAL_BUGGERED
-# define plugin_address_table_t void
-# define plugin_address_table_init(x)
-#else
-# include <plugins/plugin_api.h>
-#endif
+#include <ethereal/config.h>
+#include <ethereal/epan/packet.h>
+#include <ethereal/epan/prefs.h>
#include "tripe-protocol.h"
proto_item *ti;
proto_tree *tt;
guint8 ty;
- gint off = tvb_raw_offset(b);
+ gint off = 0;
guint32 seq;
/* --- Initialize the summary cells --- */
if (check_col(p->cinfo, COL_PROTOCOL))
col_set_str(p->cinfo, COL_PROTOCOL, "TrIPE");
+ if (check_col(p->cinfo, COL_INFO))
+ col_clear(p->cinfo, COL_INFO);
ty = tvb_get_guint8(b, 0);
if (check_col(p->cinfo, COL_INFO)) {
col_clear(p->cinfo, COL_INFO);
};
static hf_register_info hfs[] = {
- &hf_tripe_cat, {
+ { &hf_tripe_cat, {
"Message category", "tripe.cat",
FT_UINT8, BASE_HEX, 0, MSG_CATMASK
- },
- &hf_tripe_packet_type, {
+ } },
+ { &hf_tripe_packet_type, {
"Packet message type", "tripe.packet.type",
FT_UINT8, BASE_HEX, 0, MSG_TYPEMASK,
"This is the TrIPE packet type subcode."
- },
- &hf_tripe_ct, {
+ } },
+ { &hf_tripe_ct, {
"Encrypted ciphertext", "tripe.ct",
FT_BYTES, BASE_NONE, 0, 0,
"This is an encrypted message."
- },
- &hf_tripe_ct_seq, {
+ } },
+ { &hf_tripe_ct_seq, {
"Ciphertext sequence number", "tripe.ct.seq",
FT_UINT32, BASE_DEC, 0, 0,
"This is the unique sequence number for the ciphertext."
- },
- &hf_tripe_ct_iv, {
+ } },
+ { &hf_tripe_ct_iv, {
"Ciphertext initialization vector", "tripe.ct.iv",
FT_BYTES, BASE_NONE, 0, 0,
"This is the initialization vector used for the actual encryption."
- },
- &hf_tripe_ct_ct, {
+ } },
+ { &hf_tripe_ct_ct, {
"Actual encrypted data", "tripe.ct.ct",
FT_BYTES, BASE_NONE, 0, 0,
"This is the encrypted message. Reading it ought to be hard."
- },
- &hf_tripe_ct_tag, {
+ } },
+ { &hf_tripe_ct_tag, {
"Message authentication code", "tripe.ct.tag",
FT_BYTES, BASE_NONE, 0, 0,
"This is the message authentication code tag for the ciphertext."
- },
- &hf_tripe_kx_type, {
+ } },
+ { &hf_tripe_kx_type, {
"Key-exchange message type", "tripe.kx.type",
FT_UINT8, BASE_HEX, vs_kxtype, MSG_TYPEMASK,
"This is the TrIPE key-exchange type subcode."
- },
- &hf_tripe_kx_mychal.hf, {
+ } },
+ { &hf_tripe_kx_mychal.hf, {
"Sender's challenge data", "tripe.kx.mychal",
FT_BYTES, BASE_NONE, 0, 0,
"This is the sender's challenge."
- },
- &hf_tripe_kx_mychal.hf_len, {
+ } },
+ { &hf_tripe_kx_mychal.hf_len, {
"Challenge length", "tripe.kx.mychal.len",
FT_UINT16, BASE_DEC, 0, 0,
"This is the length of the sender's challenge."
- },
- &hf_tripe_kx_mychal.hf_val, {
+ } },
+ { &hf_tripe_kx_mychal.hf_val, {
"Challenge", "tripe.kx.mychal.val",
FT_BYTES, BASE_NONE, 0, 0,
"This is the value of the sender's challenge."
- },
- &hf_tripe_kx_mychal.hfx_len, {
+ } },
+ { &hf_tripe_kx_mychal.hfx_len, {
"Challenge x length", "tripe.kx.mychal.x.len",
FT_UINT16, BASE_DEC, 0, 0,
"This is the length of the sender's challenge x-coordinate."
- },
- &hf_tripe_kx_mychal.hfy_val, {
+ } },
+ { &hf_tripe_kx_mychal.hfy_val, {
"Challenge x value", "tripe.kx.mychal.x.val",
FT_BYTES, BASE_NONE, 0, 0,
"This is the value of the sender's challenge x-coordinate."
- },
- &hf_tripe_kx_mychal.hfy_len, {
+ } },
+ { &hf_tripe_kx_mychal.hfy_len, {
"Challenge y length", "tripe.kx.mychal.y.len",
FT_UINT16, BASE_DEC, 0, 0,
"This is the length of the sender's challenge x-coordinate."
- },
- &hf_tripe_kx_mychal.hfx_val, {
+ } },
+ { &hf_tripe_kx_mychal.hfx_val, {
"Challenge y value", "tripe.kx.mychal.y.val",
FT_BYTES, BASE_NONE, 0, 0,
"This is the value of the sender's challenge x-coordinate."
- },
- &hf_tripe_kx_mycookie, {
+ } },
+ { &hf_tripe_kx_mycookie, {
"Sender's hashed cookie", "tripe.kx.mycookie",
FT_BYTES, BASE_NONE, 0, 0,
"This is the hash of the sender's challenge."
- },
- &hf_tripe_kx_yourcookie, {
+ } },
+ { &hf_tripe_kx_yourcookie, {
"Recipient's hashed cookie", "tripe.kx.yourcookie",
FT_BYTES, BASE_NONE, 0, 0,
"This is the hash of the recipient's challenge."
- },
- &hf_tripe_kx_check.hf, {
+ } },
+ { &hf_tripe_kx_check.hf, {
"Challenge check-value", "tripe.kx.check",
FT_BYTES, BASE_NONE, 0, 0,
"This is an encrypted check-value which proves that the sender "
"knows the answer to the challenge, and that it is therefore honest."
- },
- &hf_tripe_kx_check.hf_len, {
+ } },
+ { &hf_tripe_kx_check.hf_len, {
"Check-value length", "tripe.kx.check.len",
FT_UINT16, BASE_DEC, 0, 0,
"This is the length of the encrypted check-value."
- },
- &hf_tripe_kx_check.hf_val, {
+ } },
+ { &hf_tripe_kx_check.hf_val, {
"Check-value data", "tripe.kx.check.val",
FT_BYTES, BASE_NONE, 0, 0,
"This is the actual encrypted check-value."
- },
- &hf_tripe_huh, {
+ } },
+ { &hf_tripe_huh, {
"Unknown data", "tripe.huh",
FT_BYTES, BASE_NONE, 0, 0,
"I don't know what's meant to appear here."
- },
+ } },
};
static gint *tts[] = {
proto_reg_handoff_tripe();
}
-G_MODULE_EXPORT void plugin_init(plugin_address_table_t *pat)
+G_MODULE_EXPORT void plugin_register(void)
{
- plugin_address_table_init(pat);
if (proto_tripe == -1)
proto_register_tripe();
}
/* -*-c-*-
*
- * $Id: keyexch.c,v 1.13 2004/04/18 18:08:11 mdw Exp $
+ * $Id$
*
* Key exchange protocol
*
* Challenge accpeted: here's the answer. Commit to my challenge. Move
* to @KXS_COMMIT@.
*
- * %$\cookie{kx-switch}, c_A, c_B, E_K(r_B^\alpha, w_A))$%
+ * %$\cookie{kx-switch-rq}, c_A, c_B, E_K(r_B^\alpha, w_A))$%
* Reply received: here's my reply. Committed; send data; move to
* @KXS_SWITCH@.
*
#define T_VALID MIN(2) /* Challenge validity period */
#define T_RETRY SEC(10) /* Challenge retransmit interval */
-#define ISVALID(kx, now) ((now) < (kx)->t_valid)
+#define VALIDP(kx, now) ((now) < (kx)->t_valid)
+
+/*----- Static tables -----------------------------------------------------*/
+
+static const char *const pkname[] = {
+ "pre-challenge", "cookie", "challenge",
+ "reply", "switch-rq", "switch-ok"
+};
/*----- Various utilities -------------------------------------------------*/
G_EXP(gg, y, gg->g, a);
ok = G_EQ(gg, y, c);
if (!ok) {
- a_warn("invalid expected-reply check from `%s'", p_name(kx->p));
+ a_warn("KX %s bad-expected-reply-log", p_name(kx->p));
IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
trace(T_CRYPTO, "crypto: computed challenge = %s", gestr(gg, y));
}))
/* --- Ensure that we're in a sensible state --- */
if (kx->s != KXS_CHAL) {
- a_warn("unexpected challenge from `%s'", p_name(kx->p));
+ a_warn("KX %s unexpected %s", p_name(kx->p), pkname[msg]);
goto bad;
}
(msg >= KX_COOKIE && (hc = buf_get(b, algs.hashsz)) == 0) ||
(msg >= KX_CHAL && (ck = buf_getmp(b)) == 0) ||
BLEFT(b)) {
- a_warn("malformed packet from `%s'", p_name(kx->p));
+ a_warn("KX %s invalid %s", p_name(kx->p), pkname[msg]);
goto bad;
}
if (!hc && kx->nr >= KX_THRESH) {
T( trace(T_KEYEXCH, "keyexch: too many challenges -- sending cookie"); )
+ a_warn("KX %s sending-cookie", p_name(kx->p));
b = p_txstart(kx->p, MSG_KEYEXCH | KX_COOKIE);
G_TOBUF(gg, b, kx->c);
h = GH_INIT(algs.h);
/* --- Discard a packet with an invalid cookie --- */
if (hc && memcmp(hc, kx->hc, algs.hashsz) != 0) {
- a_warn("incorrect cookie from `%s'", p_name(kx->p));
+ a_warn("KX %s incorrect cookie", p_name(kx->p));
goto bad;
}
if (ck) trace(T_CRYPTO, "crypto: check value = %s", mpstr(ck));
}))
if (memcmp(hc_out, kx->hc, algs.hashsz) != 0) {
- a_warn("incorrect cookie from `%s'", p_name(kx->p));
+ a_warn("KX %s incorrect cookie", p_name(kx->p));
goto bad;
}
if ((kxc = kxc_byhc(kx, hc_in)) == 0) {
- a_warn("received reply for unknown challenge from `%s'", p_name(kx->p));
+ a_warn("KX %s unknown-challenge", p_name(kx->p));
goto bad;
}
if (!kxc->r) {
if (!ck) {
- a_warn("unexpected switch request from `%s'", p_name(kx->p));
+ a_warn("KX %s unexpected switch-rq", p_name(kx->p));
goto bad;
}
if ((r = getreply(kx, kxc->c, ck)) == 0)
buf_init(&bb, buf_o, sizeof(buf_o));
if (ks_decrypt(kxc->ks, ty, b, &bb)) {
- a_warn("failed to decrypt reply from `%s'", p_name(kx->p));
+ a_warn("KX %s decrypt-failed reply", p_name(kx->p));
goto bad;
}
buf_init(b, BBASE(&bb), BLEN(&bb));
r = G_CREATE(gg);
if (G_FROMBUF(gg, b, r)) {
- a_warn("invalid reply packet from `%s'", p_name(kx->p));
+ a_warn("KX %s invalid reply", p_name(kx->p));
goto bad;
}
IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
trace(T_CRYPTO, "crypto: reply = %s", gestr(gg, r));
}))
if (!G_EQ(gg, r, kx->rx)) {
- a_warn("incorrect reply from `%s'", p_name(kx->p));
+ a_warn("KX %s incorrect reply", p_name(kx->p));
goto bad;
}
kxchal *kxc;
if (kx->s != KXS_CHAL && kx->s != KXS_COMMIT) {
- a_warn("unexpected reply from `%s'", p_name(kx->p));
+ a_warn("KX %s unexpected-reply", p_name(kx->p));
goto bad;
}
if ((hc_in = buf_get(b, algs.hashsz)) == 0 ||
(hc_out = buf_get(b, algs.hashsz)) == 0 ||
(ck = buf_getmp(b)) == 0) {
- a_warn("invalid reply packet from `%s'", p_name(kx->p));
+ a_warn("KX %s invalid reply", p_name(kx->p));
goto bad;
}
if ((kxc = matchreply(kx, MSG_KEYEXCH | KX_REPLY,
hc_in, hc_out, ck, b)) == 0)
goto bad;
if (BLEFT(b)) {
- a_warn("invalid reply packet from `%s'", p_name(kx->p));
+ a_warn("KX %s invalid reply", p_name(kx->p));
goto bad;
}
if (kx->s == KXS_CHAL) {
return (-1);
}
+/* --- @kxfinish@ --- *
+ *
+ * Arguments: @keyexch *kx@ = pointer to key exchange block
+ *
+ * Returns: ---
+ *
+ * Use: Sets everything up following a successful key exchange.
+ */
+
+static void kxfinish(keyexch *kx)
+{
+ kxchal *kxc = kx->r[0];
+ ks_activate(kxc->ks);
+ settimer(kx, ks_tregen(kxc->ks));
+ kx->s = KXS_SWITCH;
+ a_notify("KXDONE %s", p_name(kx->p));
+ p_stats(kx->p)->t_kx = time(0);
+}
+
/* --- @doswitch@ --- *
*
* Arguments: @keyexch *kx@ = pointer to key exchange block
if ((hc_in = buf_get(b, algs.hashsz)) == 0 ||
(hc_out = buf_get(b, algs.hashsz)) == 0) {
- a_warn("invalid switch request from `%s'", p_name(kx->p));
+ a_warn("KX %s invalid switch-rq", p_name(kx->p));
goto bad;
}
if ((kxc = matchreply(kx, MSG_KEYEXCH | KX_SWITCH,
hc_in, hc_out, 0, b)) == 0)
goto bad;
if ((hswrq = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
- a_warn("invalid switch request from `%s'", p_name(kx->p));
+ a_warn("KX %s invalid switch-rq", p_name(kx->p));
goto bad;
}
IF_TRACING(T_KEYEXCH, {
trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, algs.hashsz);
})
if (memcmp(hswrq, kxc->hswrq_in, algs.hashsz) != 0) {
- a_warn("incorrect switch request hash from `%s'", p_name(kx->p));
+ a_warn("KX %s incorrect switch-rq", p_name(kx->p));
goto bad;
}
switch (kx->s) {
case KXS_CHAL:
commit(kx, kxc);
case KXS_COMMIT:
- ks_activate(kxc->ks);
- settimer(kx, ks_tregen(kxc->ks));
- kx->s = KXS_SWITCH;
+ kxfinish(kx);
break;
}
resend(kx);
buf bb;
if (kx->s < KXS_COMMIT) {
- a_warn("unexpected switch confirmation from `%s'", p_name(kx->p));
+ a_warn("KX %s unexpected switch-ok", p_name(kx->p));
goto bad;
}
kxc = kx->r[0];
buf_init(&bb, buf_o, sizeof(buf_o));
if (ks_decrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCHOK, b, &bb)) {
- a_warn("failed to decrypt switch confirmation from `%s'", p_name(kx->p));
+ a_warn("KX %s decrypt-failed switch-ok", p_name(kx->p));
goto bad;
}
buf_init(b, BBASE(&bb), BLEN(&bb));
if ((hswok = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
- a_warn("invalid switch confirmation from `%s'", p_name(kx->p));
+ a_warn("KX %s invalid switch-ok", p_name(kx->p));
goto bad;
}
IF_TRACING(T_KEYEXCH, {
hswok, algs.hashsz);
})
if (memcmp(hswok, kxc->hswok_in, algs.hashsz) != 0) {
- a_warn("incorrect switch confirmation hash from `%s'", p_name(kx->p));
+ a_warn("KX %s incorrect switch-ok", p_name(kx->p));
goto bad;
}
- if (kx->s < KXS_SWITCH) {
- ks_activate(kxc->ks);
- settimer(kx, ks_tregen(kxc->ks));
- kx->s = KXS_SWITCH;
- }
+ if (kx->s < KXS_SWITCH)
+ kxfinish(kx);
return (0);
bad:
now = time(0);
if (KEY_EXPIRED(now, kx->texp_kpub)) {
stop(kx);
- a_warn("public key for `%s' has expired", p_name(kx->p));
+ a_warn("KX %s public-key-expired", p_name(kx->p));
G_COPY(gg, kx->kpub, gg->i);
kx->f &= ~KXF_PUBKEY;
return (-1);
if (checkpub(kx))
return;
- if (!ISVALID(kx, now)) {
+ if (!VALIDP(kx, now)) {
stop(kx);
start(kx, now);
+ a_notify("KXSTART %s", p_name(kx->p));
}
resend(kx);
}
size_t sz = BSZ(b);
int rc;
-#ifndef NTRACE
- static const char *const pkname[] = {
- "prechallenge", "cookie", "challenge",
- "reply", "switch request", "switch confirmation"
- };
-#endif
-
if (checkpub(kx))
return;
- if (!ISVALID(kx, now)) {
+ if (!VALIDP(kx, now)) {
stop(kx);
start(kx, now);
}
rc = doswitchok(kx, b);
break;
default:
- a_warn("unexpected key exchange message type %u from `%p'",
- p_name(kx->p));
+ a_warn("KX %s unknown-message 0x%02x", p_name(kx->p), msg);
rc = -1;
break;
}
kx->f = KXF_DEAD | KXF_PUBKEY;
start(kx, time(0));
resend(kx);
+ a_notify("KXSTART %s", p_name(kx->p));
return (0);
}
/* -*-c-*-
*
- * $Id: keymgmt.c,v 1.7 2004/04/19 08:49:40 mdw Exp $
+ * $Id$
*
* Key loading and storing
*
if ((p = key_getattr(kf, k, "cipher")) == 0)
p = "blowfish-cbc";
if ((a->c = gcipher_byname(p)) == 0)
- FAIL("unknown cipher");
+ FAIL("unknown-cipher");
if ((p = key_getattr(kf, k, "hash")) == 0)
p = "rmd160";
if ((a->h = ghash_byname(p)) == 0)
- FAIL("unknown hash function");
+ FAIL("unknown-hash");
if ((p = key_getattr(kf, k, "mgf")) == 0) {
dstr_reset(&d);
p = d.buf;
}
if ((a->mgf = gcipher_byname(p)) == 0)
- FAIL("unknown MGF cipher");
+ FAIL("unknown-mgf-cipher");
if ((p = key_getattr(kf, k, "mac")) != 0) {
dstr_reset(&d);
if ((q = strchr(d.buf, '/')) != 0)
*q++ = 0;
if ((a->m = gmac_byname(d.buf)) == 0)
- FAIL("unknown message authentication code");
+ FAIL("unknown-mac");
if (!q)
a->tagsz = a->m->hashsz;
else {
unsigned long n = strtoul(q, &q, 0);
- if (*q) FAIL("bad tag length string");
- if (n%8 || n > ~(size_t)0) FAIL("bad tag length");
+ if (*q) FAIL("bad-tag-length-string");
+ if (n%8 || n > ~(size_t)0) FAIL("bad-tag-length");
a->tagsz = n/8;
}
} else {
dstr_reset(&d);
dstr_putf(&d, "%s-hmac", a->h->name);
if ((a->m = gmac_byname(d.buf)) == 0)
- FAIL("failed to derive HMAC from hash function");
+ FAIL("no-hmac-for-hash");
a->tagsz = a->h->hashsz/2;
}
*/
static void keymoan(const char *file, int line, const char *msg, void *p)
- { a_warn("%s:%i: error: %s", file, line, msg); }
+ { a_warn("KEYMGMT key-file-error %s:%i -- %s", file, line, msg); }
/* --- @loadpriv@ --- *
*
T( trace(T_KEYMGMT, "keymgmt: private keyring updated: reloading..."); )
DRESET(&d);
if (loadpriv(&d))
- a_warn("%s -- ignoring changes", d.buf);
+ a_warn("KEYMGMT bad-private-key -- %s", d.buf);
else
reload = 1;
}
kf = kf_pub;
DRESET(&d);
if (loadpub(&d))
- a_warn("%s -- ignoring changes", d.buf);
+ a_warn("KEYMGMT bad-public-keyring -- %s", d.buf);
else {
reload = 1;
key_close(kf);
/* --- Find the key --- */
if (key_qtag(kf_pub, tag, &t, &k, &kd)) {
- a_warn("public key `%s' not found in keyring `%s'", tag, kr_pub);
+ a_warn("KEYMGMT public-key %s not-found", tag);
goto done;
}
if (strcmp((*ko)->ty, k->type) == 0)
goto tymatch;
}
- a_warn("public key `%s' has unknown type `%s'", t.buf, k->type);
+ a_warn("KEYMGMT public-key %s unknown-type %s", t.buf, k->type);
goto done;
tymatch:;
/* --- Load the key --- */
if ((e = (*ko)->loadpub(kd, &g, &p, &t)) != 0) {
- a_warn("error reading public key `%s': %s", t.buf, e);
+ a_warn("KEYMGMT public-key %s bad -- %s", t.buf, e);
goto done;
}
*/
if (!group_samep(gg, g)) {
- a_warn("public key `%s' has incorrect group", t.buf);
+ a_warn("KEYMGMT public-key %s incorrect-group", t.buf);
goto done;
}
/* --- Check the public group element --- */
if (group_check(gg, p)) {
- a_warn("public key `%s' has bad public group element", t.buf);
+ a_warn("KEYMGMT public-key %s bad-public-group-element", t.buf);
goto done;
}
/* --- Check the algorithms --- */
if ((e = algs_get(&a, kf_pub, k)) != 0) {
- a_warn("public key `%s' has bad algorithm selection: %s", t.buf, e);
+ a_warn("KEYMGMT public-key %s bad-algorithm-selection %s", t.buf, e);
goto done;
}
- if (!algs_samep(&a, &algs)) {
- a_warn("public key `%s' specifies different algorithms", t.buf);
+ if (!algs_samep(&a, &algs)) {
+ a_warn("KEYMGMT public-key %s algorithm-mismatch", t.buf);
goto done;
}
/* -*-c-*-
*
- * $Id: keyset.c,v 1.11 2004/04/18 18:08:11 mdw Exp $
+ * $Id$
*
* Handling of symmetric keysets
*
uint32 n;
if (seq < ks->iseq) {
- a_warn("received packet has old sequence number (possible replay)");
+ a_warn("SYMM replay old-sequence");
return (-1);
}
if (seq >= ks->iseq + KS_SEQWINSZ) {
}
seqbit = 1 << (seq - ks->iseq);
if (ks->iwin & seqbit) {
- a_warn("received packet repeats old sequence number");
+ a_warn("SYMM replay duplicated-sequence");
return (-1);
}
ks->iwin |= seqbit;
putc('\n', fp);
usage(fp);
fputs("\n\
-Options:
-
--h, --help Show this help text.
--v, --version Show the version number.
--u, --usage Show terse usage summary.
-
--k, --keyring=FILE Fetch keys from FILE.
-
+Options:\n\
+\n\
+-h, --help Show this help text.\n\
+-v, --version Show the version number.\n\
+-u, --usage Show terse usage summary.\n\
+\n\
+-k, --keyring=FILE Fetch keys from FILE.\n\
+\n\
Directives:\n\
peer:NAME:LOCAL-PORT:REMOTE-ADDR:REMOTE-PORT\n\
include:FILE\n\
/* -*-c-*-
*
- * $Id: peer.c,v 1.11 2004/04/08 01:36:17 mdw Exp $
+ * $Id$
*
* Communication with the peer
*
sz = sizeof(addr);
n = recvfrom(fd, buf_i, sizeof(buf_i), 0, &a.sa, &sz);
if (n < 0) {
- a_warn("error reading socket: %s", strerror(errno));
+ a_warn("PEER - socket-read-error -- %s", strerror(errno));
return;
}
p->peer.sin.sin_port == a.sin.sin_port)
goto found;
}
- a_warn("packet from unexpected peer: %s:%u",
- inet_ntoa(a.sin.sin_addr), (unsigned)ntohs(a.sin.sin_port));
+ a_warn("PEER - unexpected-source INET %s %u",
+ inet_ntoa(a.sin.sin_addr), (unsigned)ntohs(a.sin.sin_port));
return;
found:
p->st.sz_in += n;
buf_init(&b, buf_i, n);
if ((ch = buf_getbyte(&b)) < 0) {
- a_warn("bad packet from `%s': no type byte", p->name);
+ a_warn("PEER %s bad-packet no-type", p->name);
return;
}
switch (ch & MSG_CATMASK) {
case MSG_PACKET:
if (ch & MSG_TYPEMASK) {
- a_warn("unknown packet type from `%s'", p->name);
+ a_warn("PEER %s bad-packet unknown-type 0x%02x", p->name, ch);
p->st.n_reject++;
return;
}
buf_init(&bb, buf_o, sizeof(buf_o));
if (ksl_decrypt(&p->ks, MSG_PACKET, &b, &bb)) {
p->st.n_reject++;
- a_warn("couldn't decrypt inbound packet from `%s'", p->name);
+ a_warn("PEER %s decrypt-failed", p->name);
return;
}
if (BOK(&bb)) {
tun_inject(&p->t, &bb);
} else {
p->st.n_reject++;
- a_warn("packet build failed");
+ a_warn("PEER %s packet-build-failed", p->name);
}
break;
case MSG_KEYEXCH:
break;
default:
p->st.n_reject++;
- a_warn("bad packet from `%s': unknown packet type", p->name);
+ a_warn("PEER %s bad-packet unknown-category 0x%02x", p->name, ch);
break;
}
}
void p_txend(peer *p)
{
if (!BOK(&p->b)) {
- a_warn("packet build failed");
+ a_warn("PEER %s packet-build-failed", p->name);
return;
}
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),
0, &p->peer.sa, p->sasz) < 0)
- a_warn("packet send to `%s' failed: %s", p->name, strerror(errno));
+ a_warn("PEER %s socket-write-error -- %s", p->name, strerror(errno));
else {
p->st.n_out++;
p->st.sz_out += BLEN(&p->b);
if (peers)
peers->prev = p;
peers = p;
+ switch (p->peer.sa.sa_family) {
+ case AF_INET:
+ a_notify("ADD %s INET %s %u",
+ name,
+ inet_ntoa(p->peer.sin.sin_addr),
+ (unsigned)ntohs(p->peer.sin.sin_port));
+ break;
+ default:
+ a_notify("ADD %s UNKNOWN", name);
+ break;
+ }
return (p);
tidy_1:
void p_destroy(peer *p)
{
T( trace(T_PEER, "peer: destroying peer `%s'", p->name); )
+ a_notify("KILL %s", p->name);
ksl_free(&p->ks);
kx_free(&p->kx);
tun_destroy(&p->t);
libtoolize
autoheader
autoconf
-automake
+automake -a
mkdir -p build
[ -f @initconfig@ ] && . @initconfig@
: ${prefix=@prefix@} ${exec_prefix=@exec_prefix@}
: ${bindir=@bindir@} ${sbindir=@sbindir@}
-: ${TRIPEDIR=@configdir@}
+: ${TRIPEDIR=@configdir@} ${tripesock=@socketdir@/tripesock}
+: ${pidfile=@pidfile@}
: ${tripe=$sbindir/tripe} ${tripectl=$bindir/tripectl}
PATH=/usr/bin:/usr/sbin:/bin:/sbin:$bindir
export PATH TRIPEDIR
+# --- Give up if there's no key ---
+
+if test ! -f $TRIPEDIR/keyring || test ! -f $TRIPEDIR/keyring.pub; then
+ echo >&2 "Not starting/stopping TrIPE: keyring files missing"
+ exit 0
+fi
+
# --- Check it will work, or at least stands a fighting chance ---
#
# Having loads of different tunnel types doesn't help any.
case "$1" in
start)
echo -n "Starting TrIPE VPN daemon:"
- if $tripectl help >/dev/null 2>/dev/null; then
+ if $tripectl version >/dev/null 2>/dev/null; then
echo " already running"
exit 0
fi
$tripectl -D -s -p$tripe \
-f${logfile-@logfile@} \
- -P${pidfile-@pidfile@} \
+ -P$pidfile \
${keytag+-S-t}$keytag \
${addr+-S-b}$addr \
${port+-S-p}${port} \
;;
stop)
echo -n "Stopping TrIPE VPN daemon:"
- $tripectl quit
- echo " done"
+ if test ! -S $tripesock; then
+ echo " not running"
+ elif $tripectl quit >/dev/null 2>&1; then
+ echo " done"
+ elif test ! -f $pidfile; then
+ echo " stale socket found: removing"
+ rm -f $tripesock
+ elif kill `cat $pidfile`; then
+ echo " done (killed violently)"
+ else
+ echo " it doesn't want do die!"
+ exit 1
+ fi
;;
status)
for i in `$tripectl list`; do
-h, --help Display this help text.\n\
-v, --version Display version number.\n\
-u, --usage Display pointless usage message.\n\
+ --tunnel Display IP tunnelling technique and exit.\n\
\n\
-D, --daemon Run in the background.\n\
-d, --directory=DIR Switch to directory DIR [default " CONFIGDIR "].\n\
signal(SIGPIPE, SIG_IGN);
tun_init();
p_init(baddr, port);
- if (!(f & f_daemon))
- a_create(STDIN_FILENO, STDOUT_FILENO);
+ if (!(f & f_daemon)) {
+#ifndef NTRACE
+ a_create(STDIN_FILENO, STDOUT_FILENO, AF_TRACE | AF_WARN);
+#else
+ a_create(STDIN_FILENO, STDOUT_FILENO, AF_WARN);
+#endif
+ }
if (g != (gid_t)-1) {
if (setgid(g) || (getuid() == 0 && setgroups(1, &g))) {
die(EXIT_FAILURE, "couldn't setgid to %u: %s",
if (!sel_select(&sel))
selerr = 0;
else if (errno != EINTR && errno != EAGAIN) {
- a_warn("select failed: %s", strerror(errno));
+ a_warn("SERVER select-error -- %s", strerror(errno));
selerr++;
if (selerr > 8) {
- a_warn("too many select errors: bailing out");
- a_quit();
+ a_warn("ABORT repeated-select-errors");
+ abort();
}
}
}
/* -*-c-*-
*
- * $Id: tripe.h,v 1.20 2004/04/18 18:08:11 mdw Exp $
+ * $Id$
*
* Main header file for TrIPE
*
unsigned long sz_in, sz_out; /* Size of all data in and out */
unsigned long sz_kxin, sz_kxout; /* Size of key exchange messages */
unsigned long sz_ipin, sz_ipout; /* Size of encapsulated IP packets */
- time_t t_start, t_last; /* Time peer created, last recv */
+ time_t t_start, t_last, t_kx; /* Time peer created, last pk, kx */
unsigned long n_reject; /* Number of rejected packets */
unsigned long n_in, n_out; /* Number of packets in and out */
unsigned long n_kxin, n_kxout; /* Number of key exchange packets */
#define AF_DEAD 1u /* Destroy this admin block */
#define AF_LOCK 2u /* Don't destroy it yet */
+#define AF_NOTE 4u /* Catch notifications */
+#ifndef NTRACE
+ #define AF_TRACE 8u /* Catch tracing */
+#endif
+#define AF_WARN 16u /* Catch warning messages */
+
+#ifndef NTRACE
+# define AF_ALLMSGS (AF_NOTE | AF_TRACE | AF_WARN)
+#else
+# define AF_ALLMSGS (AF_NOTE | AF_WARN)
+#endif
/*----- Global variables --------------------------------------------------*/
extern void a_warn(const char */*fmt*/, ...);
+/* --- @a_notify@ --- *
+ *
+ * Arguments: @const char *fmt@ = pointer to format string
+ * @...@ = other arguments
+ *
+ * Returns: ---
+ *
+ * Use: Sends a notification to interested admin connections.
+ */
+
+extern void a_notify(const char */*fmt*/, ...);
+
/* --- @a_create@ --- *
*
* Arguments: @int fd_in, fd_out@ = file descriptors to use
+ * @unsigned f@ = initial flags to set
*
* Returns: ---
*
* Use: Creates a new admin connection.
*/
-extern void a_create(int /*fd_in*/, int /*fd_out*/);
+extern void a_create(int /*fd_in*/, int /*fd_out*/, unsigned /*f*/);
/* --- @a_quit@ --- *
*
/* -*-c-*-
*
- * $Id: tun-bsd.c,v 1.3 2004/04/08 01:36:17 mdw Exp $
+ * $Id$
*
* Tunnel interface for 4.4BSD-derived systems
*
n = read(fd, buf_i, sizeof(buf_i));
if (n < 0) {
- a_warn("tunnel read failed (%s): %s", tun_ifname(t), strerror(errno));
+ a_warn("TUN %s read-error -- %s", tun_ifname(t), strerror(errno));
return;
}
IF_TRACING(T_TUNNEL, {
T( trace(T_TUNNEL, "tunnel device %u busy: skipping", n); )
break;
case ENOENT:
- a_warn("no suitable tunnel devices found");
+ a_warn("TUN - bsd no-tunnel-devices");
return (-1);
default:
- a_warn("error opening `%s': %s (skipping)", buf, strerror(errno));
+ a_warn("TUN - open-error %s -- %s", buf, strerror(errno));
break;
}
n++;
/* -*-c-*-
*
- * $Id: tun-linux.c,v 1.3 2004/04/08 01:36:17 mdw Exp $
+ * $Id$
*
* Tunnel interface based on Linux TUN/TAP driver
*
n = read(fd, buf_i, sizeof(buf_i));
if (n < 0) {
- a_warn("tunnel read failed (%s): %s", t->ifn, strerror(errno));
+ a_warn("TUN %s read-error -- %s", t->ifn, strerror(errno));
return;
}
IF_TRACING(T_TUNNEL, {
struct ifreq iff;
if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
- a_warn("open `/dev/net/tun' failed: %s", strerror(errno));
+ a_warn("TUN - open-error /dev/net/tun -- %s", strerror(errno));
return (-1);
}
fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
iff.ifr_name[0] = 0;
iff.ifr_flags = IFF_TUN;
if ((f = ioctl(fd, TUNSETIFF, &iff)) < 0) {
- a_warn("couldn't set configure new TUN/TAP interface: %s",
- strerror(errno));
+ a_warn("TUN - linux config-error -- %s", strerror(errno));
close(fd);
return (-1);
}
/* -*-c-*-
*
- * $Id: tun-unet.c,v 1.6 2004/04/08 01:36:17 mdw Exp $
+ * $Id$
*
* Tunnel interface based on Linux Usernet
*
n = read(fd, buf_i, sizeof(buf_i));
if (n < 0) {
- a_warn("tunnel read failed (%s): %s", tun_ifname(t), strerror(errno));
+ a_warn("TUN %s read-error -- %s", tun_ifname(t), strerror(errno));
return;
}
IF_TRACING(T_TUNNEL, {
int f;
if ((fd = open("/dev/unet", O_RDWR)) < 0) {
- a_warn("open `/dev/unet' failed: %s", strerror(errno));
+ a_warn("TUN - open-error /dev/unet -- %s", strerror(errno));
return (-1);
}
fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
if ((f = ioctl(fd, UNIOCGIFFLAGS)) < 0 ||
ioctl(fd, UNIOCSIFFLAGS, f | IFF_POINTOPOINT)) {
- a_warn("couldn't set point-to-point flag: %s", strerror(errno));
+ a_warn("TUN - unet config-error -- %s", strerror(errno));
close(fd);
return (-1);
}
static char b[UNET_NAMEMAX];
struct unet_info uni;
if (ioctl(t->f.fd, UNIOCGINFO, &uni)) {
- a_warn("ioctl(UNIOCGINFO) failed: %s", strerror(errno));
+ a_warn("TUN - unet getinfo-error -- %s", strerror(errno));
return ("<error>");
}
if (strlen(uni.uni_ifname) + 1 > sizeof(b)) {
- a_warn("interface name too long!");
+ a_warn("TUN - unet ifname-too-long");
return ("<error>");
}
strcpy(b, uni.uni_ifname);