chiark / gitweb /
General overhaul of tunnelling: allow multiple tunnel drivers in one daemon,
[tripe] / tun-slip.c
index b9914e43f902580270ef2d5de282b99f93a91684..2d94033ba494c7006df6c7959af449b033edc6ec 100644 (file)
 
 /*----- 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 */
@@ -37,10 +64,6 @@ static const char *slipcmd;          /* Script to make new 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
@@ -82,7 +105,7 @@ static void t_read(int fd, unsigned mode, void *v)
   }
   if (!n) {
     a_warn("TUN %s slip eof", t->sl->name);
-    t->st = SLIPST_EOF;
+    t->st = ST_EOF;
     sel_rmfile(&t->f);
     return;
   }
@@ -100,9 +123,9 @@ static void t_read(int fd, unsigned mode, void *v)
     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"); )
@@ -116,38 +139,38 @@ static void t_read(int fd, unsigned mode, void *v)
          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;
     }
   }
@@ -156,7 +179,7 @@ static void t_read(int fd, unsigned mode, void *v)
   t->st = st;
 }
 
-/* --- @tun_init@ --- *
+/* --- @t_init@ --- *
  *
  * Arguments:  ---
  *
@@ -166,7 +189,7 @@ static void t_read(int fd, unsigned mode, void *v)
  *             opening file descriptors or something.
  */
 
-void tun_init(void)
+static void t_init(void)
 {
   char *p, *q;
   dstr d = DSTR_INIT;
@@ -175,7 +198,7 @@ void tun_init(void)
   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 --- */
 
@@ -224,32 +247,32 @@ void tun_init(void)
   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;
@@ -259,18 +282,18 @@ int tun_create(tunnel *t, peer *p)
   /* --- 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) {
@@ -290,8 +313,7 @@ int tun_create(tunnel *t, peer *p)
   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')
@@ -304,7 +326,7 @@ int tun_create(tunnel *t, peer *p)
   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);
@@ -313,16 +335,18 @@ int tun_create(tunnel *t, peer *p)
   /* --- 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 --- */
 
@@ -332,21 +356,21 @@ fail:
   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
@@ -356,7 +380,7 @@ const char *tun_ifname(tunnel *t) { return (t->sl->name); }
  * 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;
@@ -384,7 +408,7 @@ void tun_inject(tunnel *t, buf *b)
   write(t->sl->ofd, buf, q - buf);
 }
 
-/* --- @tun_destroy@ --- *
+/* --- @t_destroy@ --- *
  *
  * Arguments:  @tunnel *t@ = pointer to tunnel block
  *
@@ -393,17 +417,17 @@ void tun_inject(tunnel *t, buf *b)
  * 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);
@@ -411,6 +435,16 @@ void tun_destroy(tunnel *t)
     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 -------------------------------------------------*/