/*----- Header files ------------------------------------------------------*/
+#define TUN_INTERNALS
+
#include "tripe.h"
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct slipif {
+ struct slipif *next; /* Next one in the list */
+ int ifd, ofd; /* File descriptors to talk on */
+ char *name; /* Interface name */
+ pid_t kid; /* Child process id */
+ unsigned f; /* Various flags */
+# define F_INUSE 1u /* Interface is in use */
+# define F_DYNAMIC 2u /* Interface found dynamically */
+} slipif;
+
+struct tunnel {
+ const tunnel_ops *ops; /* Pointer to operations */
+ slipif *sl; /* My interface record */
+ sel_file f; /* Selector for SLIP tty */
+ struct peer *p; /* Pointer to my peer */
+ unsigned st; /* Current parser state */
+# define ST_ESC 1u /* Last saw an escape character */
+# define ST_BAD 2u /* This packet is malformed */
+# define ST_EOF 4u /* File descriptor reported EOF */
+ size_t n; /* Number of bytes used in buffer */
+ octet buf[PKBUFSZ]; /* Buffer for incoming data */
+};
+
/*----- Static variables --------------------------------------------------*/
static slipif *slipifs; /* List of available interfaces */
/*----- Main code ---------------------------------------------------------*/
-#if TUN_TYPE != TUN_SLIP
-# error "Tunnel type mismatch: fix the Makefile"
-#endif
-
#define SL_END 0xc0
#define SL_ESC 0xdb
#define SL_ESCEND 0xdc
#endif
errno == EAGAIN)
return;
- a_warn("TUN %s read-error -- %s", t->sl->name, strerror(errno));
+ a_warn("TUN", "%s", t->sl->name, "read-error", "?ERRNO", A_END);
return;
}
if (!n) {
- a_warn("TUN %s slip eof", t->sl->name);
- t->st = SLIPST_EOF;
+ a_warn("TUN", "%s", t->sl->name, "slip", "eof", A_END);
+ t->st = ST_EOF;
sel_rmfile(&t->f);
return;
}
IF_TRACING(T_TUNNEL, {
- trace_block(T_PACKET, "tunnel: SLIP-encapsulated data",
+ trace_block(T_PACKET, "tun-slip: SLIP-encapsulated data",
buf_t, n);
})
o = *p;
switch (o) {
case SL_END:
- if (st & SLIPST_BAD)
+ if (st & ST_BAD)
;
- else if (st & SLIPST_ESC)
- a_warn("TUN %s slip escape-end", t->sl->name);
+ else if (st & ST_ESC)
+ a_warn("TUN", "%s", t->sl->name, "slip", "escape-end", A_END);
else if (q == t->buf) {
- T( trace(T_TUNNEL, "tunnel: empty packet"); )
+ T( trace(T_TUNNEL, "tun-slip: empty packet"); )
} else {
IF_TRACING(T_TUNNEL, {
- trace(T_TUNNEL, "tunnel: packet arrived");
- trace_block(T_PACKET, "tunnel: packet contents",
+ trace(T_TUNNEL, "tun-slip: packet arrived");
+ trace_block(T_PACKET, "tun-slip: packet contents",
t->buf, q - t->buf);
})
buf_init(&b, t->buf, q - t->buf);
p_tun(t->p, &b);
}
q = t->buf;
- st &= ~(SLIPST_ESC | SLIPST_BAD);
+ st &= ~(ST_ESC | ST_BAD);
break;
case SL_ESC:
- if ((st & SLIPST_ESC) && !(st & SLIPST_BAD)) {
- a_warn("TUN %s slip bad-escape", t->sl->name);
- st |= SLIPST_BAD;
+ if ((st & ST_ESC) && !(st & ST_BAD)) {
+ a_warn("TUN", "%s", t->sl->name, "slip", "bad-escape", A_END);
+ st |= ST_BAD;
} else
- st |= SLIPST_ESC;
+ st |= ST_ESC;
break;
case SL_ESCEND:
- if (st & SLIPST_ESC)
+ if (st & ST_ESC)
o = SL_END;
goto emit;
case SL_ESCESC:
- if (st & SLIPST_ESC)
+ if (st & ST_ESC)
o = SL_ESC;
goto emit;
default:
- if ((st & SLIPST_ESC) && !(st & SLIPST_BAD)) {
- a_warn("TUN %s slip bad-escape", t->sl->name);
- st |= SLIPST_BAD;
+ if ((st & ST_ESC) && !(st & ST_BAD)) {
+ a_warn("TUN", "%s", t->sl->name, "slip", "bad-escape", A_END);
+ st |= ST_BAD;
}
emit:
- if (!(st & SLIPST_BAD)) {
+ if (!(st & ST_BAD)) {
if (q < ll)
*q++ = o;
else {
- a_warn("TUN %s slip overflow", t->sl->name);
- st |= SLIPST_BAD;
+ a_warn("TUN", "%s", t->sl->name, "slip", "overflow", A_END);
+ st |= ST_BAD;
}
}
- st &= ~SLIPST_ESC;
+ st &= ~ST_ESC;
break;
}
}
t->st = st;
}
-/* --- @tun_init@ --- *
+/* --- @t_init@ --- *
*
* Arguments: ---
*
* opening file descriptors or something.
*/
-void tun_init(void)
+static void t_init(void)
{
char *p, *q;
dstr d = DSTR_INIT;
size_t n;
if ((p = getenv("TRIPE_SLIPIF")) == 0)
- die(1, "no slip interfaces listed: set TRIPE_SLIPIF");
+ return;
/* --- Build the list of available interfaces --- */
for (;;) {
if (*p == '/' || *p == '.') {
slipcmd = p;
- T( trace(T_TUNNEL, "tunnel: declared slip command `%s'", slipcmd); )
+ T( trace(T_TUNNEL, "tun-slip: declared slip command `%s'", slipcmd); )
break;
}
uli = strtoul(p, &q, 0);
sl->name[n] = 0;
*tail = sl;
tail = &sl->next;
- T( trace(T_TUNNEL, "tunnel: declared slipif %d,%d=%s",
+ T( trace(T_TUNNEL, "tun-slip: declared slipif %d,%d=%s",
sl->ifd, sl->ofd, sl->name); )
p = q + n + 1;
if (!*p)
return;
whine:
- die(1, "bad slip interface list");
+ moan("bad slip interface list");
}
-/* --- @tun_create@ --- *
+/* --- @t_create@ --- *
*
- * Arguments: @tunnel *t@ = pointer to tunnel block
- * @peer *p@ = pointer to peer block
+ * Arguments: @peer *p@ = pointer to peer block
*
- * Returns: Zero if it worked, nonzero on failure.
+ * Returns: A tunnel block if it worked, or null on failure.
*
* Use: Initializes a new tunnel.
*/
-int tun_create(tunnel *t, peer *p)
+static tunnel *t_create(peer *p)
{
slipif *sl = 0;
int pin[2] = { -1, -1 }, pout[2] = { -1, -1 };
pid_t kid = -1;
dstr d = DSTR_INIT;
unsigned char ch;
+ tunnel *t;
static const char end[] = { SL_END, SL_END };
/* --- Try to find a spare static interface --- */
for (sl = slipifs; sl; sl = sl->next) {
- if (!(sl->f & SLIPIFF_INUSE)) {
- T( trace(T_TUNNEL, "tunnel: %s using static slipif %s",
+ if (!(sl->f & F_INUSE)) {
+ T( trace(T_TUNNEL, "tun-slip: %s using static slipif %s",
p_name(p), sl->name); )
goto found;
}
/* --- If no dynamic interfaces are available, give up --- */
if (!slipcmd) {
- a_warn("TUN %s slip no-slip-interfaces", p_name(p));
+ a_warn("TUN", "-", "slip", "no-slip-interfaces", A_END);
goto fail;
}
/* --- Fork off a child process to create a dynamic SLIP interface --- */
if (pipe(pin) || pipe(pout)) {
- a_warn("TUN %s slip pipe-error -- %s", p_name(p), strerror(errno));
+ a_warn("TUN", "-", "slip", "pipe-error", "?ERRNO", A_END);
goto fail;
}
if ((kid = fork()) < 0) {
- a_warn("TUN %s slip fork-error -- %s", p_name(p), strerror(errno));
+ a_warn("TUN", "-", "slip", "fork-error", "?ERRNO", A_END);
goto fail;
}
if (!kid) {
for (;;) {
errno = EIO;
if (read(pout[0], &ch, 1) != 1 || ch == SL_END) {
- a_warn("TUN %s slip read-ifname-failed -- %s",
- p_name(p), strerror(errno));
+ a_warn("TUN", "-", "slip", "read-ifname-failed", "?ERRNO", A_END);
goto fail;
}
if (ch == '\n')
sl->ofd = pin[1];
sl->kid = kid;
sl->next = 0;
- sl->f = SLIPIFF_DYNAMIC;
- T( trace(T_TUNNEL, "tunnel: %s using dynamic slipif %s",
+ sl->f = F_DYNAMIC;
+ T( trace(T_TUNNEL, "tun-slip: %s using dynamic slipif %s",
p_name(p), sl->name); )
fdflags(pout[0], O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
fdflags(pin[1], O_NONBLOCK, 0, FD_CLOEXEC, FD_CLOEXEC);
/* --- Set up the new tunnel --- */
found:
+ t = CREATE(tunnel);
+ t->ops = &tun_slip;
t->p = p;
t->sl = sl;
t->st = 0;
t->n = 0;
- sl->f |= SLIPIFF_INUSE;
+ sl->f |= F_INUSE;
sel_initfile(&sel, &t->f, sl->ifd, SEL_READ, t_read, t);
sel_addfile(&t->f);
write(sl->ofd, end, sizeof(end));
dstr_destroy(&d);
- return (0);
+ return (t);
/* --- Tidy up after a failure --- */
CLOSE(pin[1]); CLOSE(pout[1]);
#undef CLOSE
if (kid != -1) kill(kid, SIGTERM);
- if (sl && (sl->f & SLIPIFF_DYNAMIC)) DESTROY(sl);
+ if (sl && (sl->f & F_DYNAMIC)) DESTROY(sl);
dstr_destroy(&d);
- return (-1);
+ return (0);
}
-/* --- @tun_ifname@ --- *
+/* --- @t_ifname@ --- *
*
* Arguments: @tunnel *t@ = pointer to tunnel block
*
* Returns: A pointer to the tunnel's interface name.
*/
-const char *tun_ifname(tunnel *t) { return (t->sl->name); }
+static const char *t_ifname(tunnel *t) { return (t->sl->name); }
-/* --- @tun_inject@ --- *
+/* --- @t_inject@ --- *
*
* Arguments: @tunnel *t@ = pointer to tunnel block
* @buf *b@ = buffer to send
* Use: Injects a packet into the local network stack.
*/
-void tun_inject(tunnel *t, buf *b)
+static void t_inject(tunnel *t, buf *b)
{
octet buf[PKBUFSZ * 2 + 2];
const octet *p, *l;
octet *q;
IF_TRACING(T_TUNNEL, {
- trace(T_TUNNEL, "tunnel: inject decrypted packet");
- trace_block(T_PACKET, "tunnel: packet contents", BBASE(b), BLEN(b));
+ trace(T_TUNNEL, "tun-slip: inject decrypted packet");
+ trace_block(T_PACKET, "tun-slip: packet contents", BBASE(b), BLEN(b));
})
q = buf;
}
*q++ = SL_END;
IF_TRACING(T_TUNNEL, {
- trace_block(T_PACKET, "tunnel: SLIP-encapsulated contents",
+ trace_block(T_PACKET, "tun-slip: SLIP-encapsulated contents",
buf, q - buf);
})
write(t->sl->ofd, buf, q - buf);
}
-/* --- @tun_destroy@ --- *
+/* --- @t_destroy@ --- *
*
* Arguments: @tunnel *t@ = pointer to tunnel block
*
* Use: Destroys a tunnel.
*/
-void tun_destroy(tunnel *t)
+static void t_destroy(tunnel *t)
{
slipif *sl = t->sl;
/* --- If it reported EOF, leave it out-of-action --- */
- if (!(t->st & SLIPST_EOF)) {
+ if (!(t->st & ST_EOF)) {
sel_rmfile(&t->f);
- sl->f &= ~SLIPIFF_INUSE;
+ sl->f &= ~F_INUSE;
}
- if (sl && (sl->f & SLIPIFF_DYNAMIC)) {
- T( trace(T_TUNNEL, "tunnel: releasing dynamic slipif %s", sl->name); )
+ if (sl && (sl->f & F_DYNAMIC)) {
+ T( trace(T_TUNNEL, "tun-slip: releasing dynamic slipif %s", sl->name); )
close(sl->ofd);
close(sl->ifd);
kill(sl->kid, SIGTERM);
xfree(sl->name);
DESTROY(sl);
}
+ DESTROY(t);
}
+const tunnel_ops tun_slip = {
+ "slip",
+ t_init,
+ t_create,
+ t_ifname,
+ t_inject,
+ t_destroy
+};
+
/*----- That's all, folks -------------------------------------------------*/