/*----- 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
}
if (!n) {
a_warn("TUN %s slip eof", t->sl->name);
- t->st = SLIPST_EOF;
+ t->st = ST_EOF;
sel_rmfile(&t->f);
return;
}
o = *p;
switch (o) {
case SL_END:
- if (st & SLIPST_BAD)
+ if (st & ST_BAD)
;
- else if (st & SLIPST_ESC)
+ else if (st & ST_ESC)
a_warn("TUN %s slip escape-end", t->sl->name);
else if (q == t->buf) {
T( trace(T_TUNNEL, "tunnel: empty packet"); )
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)) {
+ if ((st & ST_ESC) && !(st & ST_BAD)) {
a_warn("TUN %s slip bad-escape", t->sl->name);
- st |= SLIPST_BAD;
+ 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)) {
+ if ((st & ST_ESC) && !(st & ST_BAD)) {
a_warn("TUN %s slip bad-escape", t->sl->name);
- st |= SLIPST_BAD;
+ 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;
+ 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 --- */
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)) {
+ if (!(sl->f & F_INUSE)) {
T( trace(T_TUNNEL, "tunnel: %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");
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 -- %s", strerror(errno));
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 -- %s", strerror(errno));
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 -- %s", strerror(errno));
goto fail;
}
if (ch == '\n')
sl->ofd = pin[1];
sl->kid = kid;
sl->next = 0;
- sl->f = SLIPIFF_DYNAMIC;
+ sl->f = F_DYNAMIC;
T( trace(T_TUNNEL, "tunnel: %s using dynamic slipif %s",
p_name(p), sl->name); )
fdflags(pout[0], O_NONBLOCK, O_NONBLOCK, 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;
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)) {
+ if (sl && (sl->f & F_DYNAMIC)) {
T( trace(T_TUNNEL, "tunnel: releasing dynamic slipif %s", sl->name); )
close(sl->ofd);
close(sl->ifd);
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 -------------------------------------------------*/