chiark / gitweb /
General overhaul of tunnelling: allow multiple tunnel drivers in one daemon,
authormdw <mdw>
Mon, 12 Sep 2005 14:00:00 +0000 (14:00 +0000)
committermdw <mdw>
Mon, 12 Sep 2005 14:00:00 +0000 (14:00 +0000)
running at the same time.

16 files changed:
Makefile.am
admin.c
configure.in
debian/control
debian/rules
doc/tripe-admin.5
doc/tripe.8
peer.c
tripe-init.in
tripe.c
tripe.conf
tripe.h
tun-bsd.c
tun-linux.c
tun-slip.c
tun-unet.c

index bbf743ea63ec8b69186d63ea67e8b6d4a7defb04..f5f5a255fb81708c0ddf0654503bc8ed0a596833 100644 (file)
@@ -39,10 +39,9 @@ bin_PROGRAMS = tripectl tripe-mitm pkstream
 noinst_SCRIPTS = tripe-init
 tripe_SOURCES = \
        tripe.c tripe.h tripe-protocol.h \
-       admin.c peer.c tun-$(tun).c \
+       admin.c peer.c \
        keymgmt.c keyexch.c keyset.c \
-       servutil.c util.c util.h
-EXTRA_tripe_SOURCES = \
+       servutil.c util.c util.h \
        tun-unet.c tun-bsd.c tun-linux.c tun-slip.c
 tripe_LDADD = $(CATACOMB_LIBS)
 tripectl_SOURCES = \
diff --git a/admin.c b/admin.c
index 57d9ccfacca6a895cff93939462117884c3fc7bf..24d86c64ac40dcf7a33e61c84d6ccb2eac48ae6a 100644 (file)
--- a/admin.c
+++ b/admin.c
@@ -78,23 +78,6 @@ static void a_unlock(admin */*a*/);
 
 /*----- 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
@@ -433,6 +416,10 @@ void a_notify(const char *fmt, ...)
 
 void a_quit(void)
 {
+  peer *p;
+
+  while ((p = p_first()) != 0)
+    p_destroy(p);
   close(sock.fd);
   unlink(sockname);
   exit(0);
@@ -506,7 +493,7 @@ static void a_resolve(struct hostent *h, void *v)
     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))
+    if (!p_create(a->pname, a->tops, &a->peer.sa, a->sasz))
       a_fail(a, "peer-create-fail %s", a->pname);
     else
       a_ok(a);
@@ -558,7 +545,8 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
 {
   unsigned long pt;
   struct timeval tv;
-  unsigned i;
+  unsigned i, j;
+  const tunnel_ops *tops = tun_default;
   char *p;
 
   /* --- Make sure someone's not got there already --- */
@@ -568,13 +556,40 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
     return;
   }
 
+  /* --- Parse options --- */
+
+  i = 1;
+  for (;;) {
+    if (!av[i])
+      goto bad_syntax;
+    if (mystrieq(av[i], "-tunnel")) {
+      i++;
+      if (!av[i])
+       goto bad_syntax;
+      for (j = 0;; j++) {
+       if (!tunnels[j]) {
+         a_fail(a, "unknown-tunnel %s", av[i]);
+         return;
+       }
+       if (mystrieq(av[i], tunnels[j]->name)) {
+         tops = tunnels[j];
+         break;
+       }
+      }
+      i++;
+    } else if (mystrieq(av[i], "--")) {
+      i++;
+      break;
+    } else
+      break;
+  }
+
   /* --- 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");
+    a_fail(a, "bad-syntax -- add PEER [-tunnel TUN] [inet] ADDRESS PORT");
     return;
   }
   a->peer.sin.sin_family = AF_INET;
@@ -597,7 +612,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
   /* --- If the name is numeric, do it the easy way --- */
   
   if (inet_aton(av[i], &a->peer.sin.sin_addr)) {
-    if (!p_create(av[0], &a->peer.sa, a->sasz))
+    if (!p_create(av[0], tops, &a->peer.sa, a->sasz))
       a_fail(a, "peer-create-fail %s", a->pname);
     else
       a_ok(a);
@@ -613,6 +628,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
 
   a->pname = xstrdup(av[0]);
   a->paddr = xstrdup(av[i]);
+  a->tops = tops;
   selbuf_disable(&a->b);
   gettimeofday(&tv, 0);
   tv.tv_sec += T_RESOLVE;
@@ -620,6 +636,11 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
   bres_byname(&a->r, a->paddr, a_resolve, a);
   T( trace(T_ADMIN, "admin: %u resolving hostname `%s'",
           a->seq, a->paddr); )
+  return;
+
+bad_syntax:
+  a_fail(a, "bad-syntax -- add PEER [-tunnel TUN] ADDR ...");
+  return;
 }
 
 /*----- Administration commands -------------------------------------------*/
@@ -848,6 +869,14 @@ static void acmd_version(admin *a, unsigned ac, char *av[])
   a_ok(a);
 }
 
+static void acmd_tunnels(admin *a, unsigned ac, char *av[])
+{
+  int i;
+  for (i = 0; tunnels[i]; i++)
+    a_info(a, "%s", tunnels[i]->name);
+  a_ok(a);
+}
+
 /* --- The command table and help --- */
 
 typedef struct acmd {
@@ -875,7 +904,9 @@ static const acmd acmdtab[] = {
   { "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 ...",    2,      0xffff, acmd_add },
+  { "add",     "add PEER [-tunnel TUN] ADDR ...",
+                                       2,      0xffff, acmd_add },
+  { "tunnels", "tunnels",              0,      0,      acmd_tunnels },
   { "quit",    "quit",                 0,      0,      acmd_quit },
   { 0,         0,                      0,      0,      0 }
 };
index c6d702e72207b0f40ee9bac8882afaeb6b93b260..d0c2dbd71ffdb0816c20ba9c4382d7b33b56c021 100644 (file)
@@ -84,14 +84,15 @@ AC_ARG_WITH([ethereal],
 esac],
 [ethereal=true requireethereal=false])
 
-tun=guess
+tun=auto
 AC_ARG_WITH([tunnel],
-[  --with-tunnel=KIND      kind of tunnel device to use
+[  --with-tunnel=KIND      kinds of tunnel device to use
                             (linux, unet, bsd, slip)],
 [tun=$withval])
 
-if test "$tun" = guess; then
-  AC_CACHE_CHECK([tunnel device to use], [mdw_cv_tunnel], [
+if test "$tun" = auto; then
+  AC_CACHE_CHECK([tunnel drivers to use], [mdw_cv_tunnel], [
+    mdw_cv_tunnel=""
     case $host_os in
       linux*)
        case `uname -r` in
@@ -108,21 +109,29 @@ changequote([,])dnl
       *bsd*)
        mdw_cv_tunnel=bsd
        ;;
-      *)
-        mdw_cv_tunnel=slip
-       ;;
     esac
+    mdw_cv_tunnel=$mdw_cv_tunnel${mdw_cv_tunnel:+ }slip
   ])
   tun=$mdw_cv_tunnel
 fi
 
-case $tun in
-  linux | unet | bsd | slip) ;;
-  *) AC_MSG_ERROR([Unknown tunnel type]) ;;
-esac
-AC_DEFINE_UNQUOTED([TUN_TYPE], [TUN_`echo $tun | tr a-z A-Z`],
-  [Set to the tunnel driver for your OS.  See TUN_* in tripe.h.])
+tunnels=""
+for i in $tun; do
+  case $i in
+    linux) AC_DEFINE([TUN_LINUX], [1],
+                    [Install the Linux TUN/TAP driver.]) ;;
+    bsd) AC_DEFINE([TUN_BSD], [1],
+                  [Install the BSD tunnel driver.]) ;;
+    unet) AC_DEFINE([TUN_UNET], [1],
+                    [Install the obsolete Linux Usernet driver.]) ;;
+    slip) ;;
+    *) AC_MSG_ERROR([Unknown tunnel type]) ;;
+  esac
+  tunnels="$tunnels&tun_$i, "
+done
 AC_SUBST(tun)
+AC_DEFINE_UNQUOTED([TUN_LIST], [$tunnels 0], 
+  [List of tunnel drivers to install.])
 
 mdw_MLIB(2.0.0)
 mdw_CATACOMB(2.1.0, [CFLAGS="$CFLAGS $CATACOMB_CFLAGS"])
index 337580a5d5e15b8286da38a6809f3ac07946c967..4386a9a3a30c0c306dcfab504ebf385848905d40 100644 (file)
@@ -15,8 +15,9 @@ Description: Trivial IP Encryption: a simple virtual private network
  TrIPE is a simple VPN protocol.  It uses cryptography to ensure secrecy
  and authenticity of packets it sends and receives.
  .
- This package contains the main daemon and support programs.  It needs
- a 2.4 series kernel with the TUN/TAP driver enabled.
+ This package contains the main daemon, support programs, and documentation. 
+ It ideally wants a 2.4 series kernel with the TUN/TAP driver enabled, but
+ it will work with any kernel which speaks SLIP.
 
 Package: pkstream
 Architecture: any
index e164a834cc9d6b7913b0c9ea2badb35e77f1c560..6a52d03028ed372448e0c276556e2343cfcc86d2 100755 (executable)
@@ -7,6 +7,7 @@ build:
        mkdir deb-build
        cd deb-build; ../configure \
                --prefix=/usr --mandir=/usr/share/man \
+               --with-tunnel="linux slip" \
                --with-configdir=/etc/tripe \
                --with-socketdir=/var/run \
                --with-logfile=/var/log/tripe.log \
index 1b101e6a87f537ec9fe69ad269b3938977c912a2..79874e914e2267c745e5e1f81c741c4971e7a029 100644 (file)
@@ -96,7 +96,7 @@ address.
 .SH "COMMAND REFERENCE"
 The commands provided are:
 .TP
-.BI "ADD " peer " " address\fR...
+.BI "ADD " peer " \fR[" options "\fR] " 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
@@ -106,7 +106,12 @@ the peer's public key is assumed to be in the file
 option on the command line).  The
 .I address
 is the network address (see above for the format) at which the peer can
-be contacted.
+be contacted.  The following options are recognised.
+.RS
+.TP
+.BI "-tunnel " tunnel
+Use the named tunnel driver, rather than the default.
+.RE
 .TP
 .BI "ADDR " peer
 Emits an
@@ -385,9 +390,11 @@ couldn't be found in
 .SH "NOTIFICATIONS"
 The following notifications are sent to clients who request them.
 .TP
-.BI "ADD " peer " " address \fR...
+.BI "ADD " peer " " ifname " " address \fR...
 A new peer has been added.  The peer's name is
-.I peer
+.IR peer ,
+its tunnel is network interface
+.IR ifname ,
 and its network address is
 .IR address .
 .TP
@@ -654,32 +661,20 @@ create some more
 .BI /dev/tun nn
 files, it will work.
 .TP
-.BI "TUN \- slip no-slip-interfaces"
-The driver ran out of SLIP interfaces.  You probably need to preallocate
-some more and restart.
-.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.
+.BI "TUN " ifname " read-error \-\- " message
+Reading from the tunnel device failed.
 .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.
+.BI "TUN " ifname " slip bad-escape"
+The SLIP driver encountered a escaped byte it wasn't expecting to see.
+The erroneous packet will be ignored.
 .TP
 .BI "TUN " ifname " slip eof"
 The SLIP driver encountered end-of-file on its input descriptor.
@@ -691,12 +686,36 @@ The SLIP driver encountered an escaped `end' marker.  This probably
 means that someone's been sending it junk.  The erroneous packet is
 discarded, and we hope that we've rediscovered synchronization.
 .TP
-.BI "TUN " ifname " slip bad-escape"
-The SLIP driver encountered a escaped byte it wasn't expecting to see.
-The erroneous packet will be ignored.
+.BI "TUN \- slip fork-error \-\- " message
+The SLIP driver encountered an error forking a child process while
+allocating a new dynamic interface.
+.TP
+.BI "TUN \- slip no-slip-interfaces"
+The driver ran out of static SLIP interfaces.  Either preallocate more,
+or use dynamic SLIP interface allocation.
 .TP
 .BI "TUN " ifname " slip overflow"
 The SLIP driver gave up reading a packet because it got too large.
+.TP
+.BI "TUN \- slip pipe-error \-\- " message
+The SLIP driver encountered an error creating pipes while allocating a
+new dynamic interface.
+.TP
+.BI "TUN \- slip read-ifname-failed \-\- " message
+The SLIP driver encountered an error reading the name of a dynamically
+allocated interface.  Maybe the allocation script is broken.
+.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.
 .SS "USER warnings"
 These are issued by administration clients using the
 .B WARN
index 7ff497c3b30611acda70694613abaa432f3e5030..40a5b6577bc6302a21850f4730096e864c3b3295 100644 (file)
@@ -41,6 +41,8 @@ tripe \- a simple VPN daemon
 .IR addr ]
 .RB [ \-p
 .IR port ]
+.RB [ \-n
+.IR tunnel ]
 .br
        
 .RB [ \-U
@@ -148,9 +150,9 @@ version number to standard output and exits with status 0.
 .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
+.B "\-\-tunnels"
+Writes to standard output a list of the configured tunnel drivers, one
+per line, 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"
@@ -185,6 +187,9 @@ to tunnel through the VPN.
 Use the specified UDP port for all communications with peers, rather
 than an arbitarary kernel-assigned port.
 .TP
+.BI "\-n, \-\-tunnel=" tunnel
+Use the specified tunnel driver for new peers by default.
+.TP
 .BI "\-U, \-\-setuid=" user
 Set uid to that of
 .I user
diff --git a/peer.c b/peer.c
index 15243b712c694715e0de45529bfe1702bf5ba8bb..402d08b556e120d7668d159184798236d747aa9b 100644 (file)
--- a/peer.c
+++ b/peer.c
 static peer *peers = 0;
 static sel_file sock;
 
+/*----- Tunnel table ------------------------------------------------------*/
+
+const tunnel_ops *tunnels[] = {
+#ifdef TUN_LINUX
+  &tun_linux,
+#endif
+#ifdef TUN_BSD
+  &tun_bsd,
+#endif
+#ifdef TUN_UNET
+  &tun_unet,
+#endif
+  &tun_slip,
+  0
+}, *tun_default;
+
 /*----- Main code ---------------------------------------------------------*/
 
 /* --- @p_read@ --- *
@@ -111,7 +127,7 @@ found:
       if (BOK(&bb)) {
        p->st.n_ipin++;
        p->st.sz_ipin += BSZ(&b);
-       tun_inject(&p->t, &bb);
+       p->t->ops->inject(p->t, &bb);
       } else {
        p->st.n_reject++;
        a_warn("PEER %s packet-build-failed", p->name);
@@ -234,7 +250,7 @@ stats *p_stats(peer *p) { return (&p->st); }
  * Returns:    A pointer to the peer's interface name.
  */
 
-const char *p_ifname(peer *p) { return (tun_ifname(&p->t)); }
+const char *p_ifname(peer *p) { return (p->t->ops->ifname(p->t)); }
 
 /* --- @p_addr@ --- *
  *
@@ -309,6 +325,7 @@ unsigned p_port(void)
 /* --- @p_create@ --- *
  *
  * Arguments:  @const char *name@ = name for this peer
+ *             @const tunnel_ops *tops@ = tunnel to use
  *             @struct sockaddr *sa@ = socket address of peer
  *             @size_t sz@ = size of socket address
  *
@@ -318,9 +335,11 @@ unsigned p_port(void)
  *             by this point.
  */
 
-peer *p_create(const char *name, struct sockaddr *sa, size_t sz)
+peer *p_create(const char *name, const tunnel_ops *tops,
+              struct sockaddr *sa, size_t sz)
 {
   peer *p = CREATE(peer);
+
   T( trace(T_PEER, "peer: creating new peer `%s'", name); )
   p->name = xstrdup(name);
   p->ks = 0;
@@ -331,7 +350,7 @@ peer *p_create(const char *name, struct sockaddr *sa, size_t sz)
   p->st.t_start = time(0);
   if (kx_init(&p->kx, p, &p->ks))
     goto tidy_0;
-  if (tun_create(&p->t, p))
+  if ((p->t = tops->create(p)) == 0)
     goto tidy_1;
   p->next = peers;
   if (peers)
@@ -339,13 +358,14 @@ peer *p_create(const char *name, struct sockaddr *sa, size_t sz)
   peers = p;
   switch (p->peer.sa.sa_family) {
     case AF_INET:
-      a_notify("ADD %s INET %s %u",
+      a_notify("ADD %s %s INET %s %u",
               name,
+              p->t->ops->ifname(p->t),
               inet_ntoa(p->peer.sin.sin_addr),
               (unsigned)ntohs(p->peer.sin.sin_port));
       break;
     default:
-      a_notify("ADD %s UNKNOWN", name);
+      a_notify("ADD %s %s UNKNOWN", name, p->t->ops->ifname(p->t));
       break;
   }
   a_notify("KXSTART %s", name);                /* Couldn't tell anyone before */
@@ -402,7 +422,7 @@ void p_destroy(peer *p)
   a_notify("KILL %s", p->name);
   ksl_free(&p->ks);
   kx_free(&p->kx);
-  tun_destroy(&p->t);
+  p->t->ops->destroy(p->t);
   xfree(p->name);
   if (p->next)
     p->next->prev = p->prev;
index 82ada434fedee70eed4da0e475afe1fae3335e07..b4c5e6d7336a10d35b857f96e887cb85155fce5e 100755 (executable)
@@ -29,7 +29,7 @@ fi
 
 test -x $tripe -a -x $tripectl || exit 0
 
-case `$tripe --tunnel` in
+case ${tunnel-`$tripe --tunnels | head -1`} in
   linux)
     case `uname -s` in
       Linux)
@@ -125,6 +125,7 @@ case "$1" in
       ${user+-S-u}${user} \
       ${group+-S-g}${group} \
       ${trace+-S-T}${trace} \
+      ${tunnel+-S-n}${tunnel} \
       ${miscopts}
     for i in 1 2 3 4 give-up; do
       $tripectl help >/dev/null 2>/dev/null && break
diff --git a/tripe.c b/tripe.c
index 180177ee66450b8876ff63f3b9fe064017a616d3..202a843ad6ab3ccbf259f50a4f3d5ce76e1a94b3 100644 (file)
--- a/tripe.c
+++ b/tripe.c
@@ -51,7 +51,7 @@ static sel_timer it;
  * Use:                Called periodically to do housekeeping tasks.
  */
 
-void interval(struct timeval *tv, void *v)
+static void interval(struct timeval *tv, void *v)
 {
   struct timeval tvv;
   T( trace(T_PEER, "peer: interval timer"); )
@@ -62,6 +62,23 @@ void interval(struct timeval *tv, void *v)
   sel_addtimer(&sel, &it, &tvv, interval, v);
 }
 
+/* --- @mystrieq@ --- *
+ *
+ * Arguments:  @const char *x, *y@ = two strings
+ *
+ * Returns:    True if @x@ and @y are equal, up to case.
+ */
+
+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++;
+  }
+}
+
 /* --- @main@ --- *
  *
  * Arguments:  @int argc@ = number of command line arguments
@@ -74,7 +91,7 @@ void interval(struct timeval *tv, void *v)
 
 static void usage(FILE *fp)
 {
-  pquis(fp, "Usage: $ [-D] [-d DIR] [-b ADDR] [-p PORT]\n\
+  pquis(fp, "Usage: $ [-D] [-d DIR] [-b ADDR] [-p PORT] [-n TUNNEL]\n\
        [-U USER] [-G GROUP] [-a SOCKET] [-T TRACE-OPTS]\n\
        [-k PRIV-KEYRING] [-K PUB-KEYRING] [-t KEY-TAG]\n");
 }
@@ -95,12 +112,13 @@ Options:\n\
 -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\
+    --tunnels          Display IP tunnel drivers and exit.\n\
 \n\
 -D, --daemon           Run in the background.\n\
 -d, --directory=DIR    Switch to directory DIR [default " CONFIGDIR "].\n\
 -b, --bind-address=ADDR        Bind UDP socket to this IP ADDR.\n\
 -p, --port=PORT                Select UDP port to listen to.\n\
+-n, --tunnel=TUNNEL    Seelect default tunnel driver.\n\
 -U, --setuid=USER      Set uid to USER after initialization.\n\
 -G, --setgid=GROUP     Set gid to GROUP after initialization.\n\
 -k, --priv-keyring=FILE        Get private key from FILE.\n\
@@ -123,6 +141,9 @@ int main(int argc, char *argv[])
   unsigned port = 0;
   struct in_addr baddr = { INADDR_ANY };
   unsigned f = 0;
+  int i;
+  int selerr = 0;
+  struct timeval tv;
   uid_t u = -1;
   gid_t g = -1;
 
@@ -134,12 +155,14 @@ int main(int argc, char *argv[])
 
   if ((p = getenv("TRIPEDIR")) != 0)
     dir = p;
+  tun_default = tunnels[0];
 
   for (;;) {
     static const struct option opts[] = {
       { "help",                0,              0,      'h' },
       { "version",     0,              0,      'v' },
       { "usage",       0,              0,      'u' },
+      { "tunnels",     0,              0,      '0' },
 
       { "daemon",      0,              0,      'D' },
       { "uid",         OPTF_ARGREQ,    0,      'U' },
@@ -147,6 +170,7 @@ int main(int argc, char *argv[])
       { "gid",         OPTF_ARGREQ,    0,      'G' },
       { "setgid",      OPTF_ARGREQ,    0,      'G' },
       { "bind-address",        OPTF_ARGREQ,    0,      'b' },
+      { "tunnel",      OPTF_ARGREQ,    0,      'n' },
       { "port",                OPTF_ARGREQ,    0,      'p' },
       { "directory",   OPTF_ARGREQ,    0,      'd' },
       { "priv-keyring",        OPTF_ARGREQ,    0,      'k' },
@@ -157,12 +181,11 @@ int main(int argc, char *argv[])
       { "trace",       OPTF_ARGREQ,    0,      'T' },
 #endif
 
-      { "tunnel",      0,              0,      '0' },
       { 0,             0,              0,      0 }
     };
 
-    int i = mdwopt(argc, argv, "hvuDU:G:b:p:d:k:K:t:a:" T("T:"),
-                  opts, 0, 0, 0);
+    i = mdwopt(argc, argv, "hvuDU:G:b:p:d:k:K:t:a:" T("T:"),
+              opts, 0, 0, 0);
     if (i < 0)
       break;
     switch (i) {
@@ -225,6 +248,16 @@ int main(int argc, char *argv[])
          die(EXIT_FAILURE, "bad port number %lu", i);
        port = i;
       } break;
+      case 'n': {
+       int i;
+       for (i = 0;; i++) {
+         if (!tunnels[i])
+           die(EXIT_FAILURE, "unknown tunnel `%s'", optarg);
+         if (mystrieq(optarg, tunnels[i]->name))
+           break;
+       }
+       tun_default = tunnels[i];
+      } break;
       case 'd':
        dir = optarg;
        break;
@@ -247,9 +280,9 @@ int main(int argc, char *argv[])
        break;
 #endif
       case '0': {
-       static const char *tun[] =
-         { "notdef", "unet", "bsd", "linux", "slip" };
-       puts(tun[TUN_TYPE]);
+       int i;
+       for (i = 0; tunnels[i]; i++)
+         puts(tunnels[i]->name);
        exit(0);
       } break;
       default:
@@ -273,7 +306,8 @@ int main(int argc, char *argv[])
   rand_noisesrc(RAND_GLOBAL, &noise_source);
   rand_seed(RAND_GLOBAL, MAXHASHSZ);
   signal(SIGPIPE, SIG_IGN);
-  tun_init();
+  for (i = 0; tunnels[i]; i++)
+    tunnels[i]->init();
   p_init(baddr, port);
   if (!(f & f_daemon)) {
 #ifndef NTRACE
@@ -302,25 +336,19 @@ int main(int argc, char *argv[])
     a_daemon();
   }
 
-  {
-    struct timeval tv;
-    tv.tv_sec = time(0) + T_INTERVAL;
-    tv.tv_usec = 0;
-    sel_addtimer(&sel, &it, &tv, interval, 0);
-  }
+  tv.tv_sec = time(0) + T_INTERVAL;
+  tv.tv_usec = 0;
+  sel_addtimer(&sel, &it, &tv, interval, 0);
 
-  {
-    int selerr = 0;
-    for (;;) {
-      if (!sel_select(&sel))
-        selerr = 0;
-      else if (errno != EINTR && errno != EAGAIN) {
-       a_warn("SERVER select-error -- %s", strerror(errno));
-       selerr++;
-       if (selerr > 8) {
-         a_warn("ABORT repeated-select-errors");
-         abort();
-       }
+  for (;;) {
+    if (!sel_select(&sel))
+      selerr = 0;
+    else if (errno != EINTR && errno != EAGAIN) {
+      a_warn("SERVER select-error -- %s", strerror(errno));
+      selerr++;
+      if (selerr > 8) {
+       a_warn("ABORT repeated-select-errors");
+       abort();
       }
     }
   }
index dd2de57e710931c9087529d54db544640d782371..8105a2a1525e116f1228fda4d8e8abf9b66d24e1 100644 (file)
 # saying `tripectl port'.
 # port=22003
 
+# The tunnel device you want tripe to use.  The default is to use a system-
+# specific device, if there's one compiled in, or SLIP if not.
+# tunnel=slip
+
 # The user to run as once tripe has initialized.  The user (or group -- see
 # `group' below) must be able to open new tunnel interfaces.
 # user=tripe
diff --git a/tripe.h b/tripe.h
index 6dbfbad3c4ffa5814162c45c9c4c442dfbe76d65..9cf7abf3103705250669f86f9b68d1346acb5b7e 100644 (file)
--- a/tripe.h
+++ b/tripe.h
 
 /*----- Magic numbers -----------------------------------------------------*/
 
-/* --- Tunnel types --- */
-
-#define TUN_NOTDEF 0
-#define TUN_UNET 1
-#define TUN_BSD 2
-#define TUN_LINUX 3
-#define TUN_SLIP 4
-
 /* --- Trace flags --- */
 
 #define T_TUNNEL 1u
@@ -260,49 +252,21 @@ enum {
  * Used to maintain system-specific information about the tunnel interface.
  */
 
-#if TUN_TYPE == TUN_LINUX
-#  include <linux/if.h>
-#  include <linux/if_tun.h>
-#endif
+typedef struct tunnel tunnel;
+struct peer;
 
-#if TUN_TYPE == TUN_SLIP
-  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 SLIPIFF_INUSE 1u          /*   Interface is in use */
-#     define SLIPIFF_DYNAMIC 2u                /*   Interface found dynamically */
-  } slipif;
-#endif
+typedef struct tunnel_ops {
+  const char *name;                    /* Name of this tunnel driver */
+  void (*init)(void);                  /* Initializes the system */
+  tunnel *(*create)(struct peer */*p*/); /* Initializes a new tunnel */
+  const char *(*ifname)(tunnel */*t*/);        /* Returns tunnel's interface name */
+  void (*inject)(tunnel */*t*/, buf */*b*/); /* Sends packet through if */
+  void (*destroy)(tunnel */*t*/);      /* Destroys a tunnel */
+} tunnel_ops;
 
-typedef struct tunnel {
-#if TUN_TYPE == TUN_UNET 
-  sel_file f;                          /* Selector for Usernet device */
-  struct peer *p;                      /* Pointer to my peer */
-#elif TUN_TYPE == TUN_LINUX
-  sel_file f;                          /* Selector for TUN/TAP device */
-  struct peer *p;                      /* Pointer to my peer */
-  char ifn[IFNAMSIZ];                  /* Interface name buffer */
-#elif TUN_TYPE == TUN_BSD
-  sel_file f;                          /* Selector for tunnel device */
-  struct peer *p;                      /* Pointer to my peer */
-  unsigned n;                          /* Number of my tunnel device */
-#elif TUN_TYPE == TUN_SLIP
-  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 SLIPST_ESC 1u               /*   Last saw an escape character */
-#   define SLIPST_BAD 2u               /*   This packet is malformed */
-#   define SLIPST_EOF 4u               /*   File descriptor reported EOF */
-  size_t n;                            /* Number of bytes used in buffer */
-  octet buf[PKBUFSZ];                  /* Buffer for incoming data */
-#else
-#  error "No support for this tunnel type"
+#ifndef TUN_INTERNALS
+struct tunnel { const tunnel_ops *ops; };
 #endif
-} tunnel;
 
 /* --- Peer statistics --- *
  *
@@ -331,7 +295,7 @@ typedef struct stats {
 typedef struct peer {
   struct peer *next, *prev;            /* Links to next and previous */
   char *name;                          /* Name of this peer */
-  tunnel t;                            /* Tunnel for local packets */
+  tunnel *t;                           /* Tunnel for local packets */
   keyset *ks;                          /* List head for keysets */
   buf b;                               /* Buffer for sending packets */
   addr peer;                           /* Peer socket address */
@@ -363,6 +327,7 @@ typedef struct admin {
   sel_file w;                          /* Selector for write buffering */
   bres_client r;                       /* Background resolver task */
   sel_timer t;                         /* Timer for resolver */
+  const tunnel_ops *tops;              /* Tunnel to use */
   addr peer;                           /* Address to set */
   size_t sasz;                         /* Size of the address */
 } admin;
@@ -387,6 +352,8 @@ extern sel_state sel;                       /* Global I/O event state */
 extern group *gg;                      /* The group we work in */
 extern mp *kpriv;                      /* Our private key */
 extern octet buf_i[PKBUFSZ], buf_o[PKBUFSZ], buf_t[PKBUFSZ];
+extern const tunnel_ops *tunnels[];    /* Table of tunnels (0-term) */
+extern const tunnel_ops *tun_default;  /* Default tunnel to use */
 
 #ifndef NTRACE
 extern const trace_opt tr_opts[];      /* Trace options array */
@@ -843,6 +810,7 @@ unsigned p_port(void);
 /* --- @p_create@ --- *
  *
  * Arguments:  @const char *name@ = name for this peer
+ *             @const tunnel_ops *tops@ = tunnel to use
  *             @struct sockaddr *sa@ = socket address of peer
  *             @size_t sz@ = size of socket address
  *
@@ -852,7 +820,7 @@ unsigned p_port(void);
  *             by this point.
  */
 
-extern peer *p_create(const char */*name*/,
+extern peer *p_create(const char */*name*/, const tunnel_ops */*tops*/,
                      struct sockaddr */*sa*/, size_t /*sz*/);
 
 /* --- @p_name@ --- *
@@ -898,63 +866,21 @@ extern void p_destroy(peer */*p*/);
 extern peer *p_first(void);
 extern peer *p_next(peer */*p*/);
 
-/*----- Tunnel interface --------------------------------------------------*/
-
-/* --- @tun_init@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    ---
- *
- * Use:                Initializes the tunneling system.  Maybe this will require
- *             opening file descriptors or something.
- */
-
-extern void tun_init(void);
-
-/* --- @tun_create@ --- *
- *
- * Arguments:  @tunnel *t@ = pointer to tunnel block
- *             @peer *p@ = pointer to peer block
- *
- * Returns:    Zero if it worked, nonzero on failure.
- *
- * Use:                Initializes a new tunnel.
- */
-
-extern int tun_create(tunnel */*t*/, peer */*p*/);
-
-/* --- @tun_ifname@ --- *
- *
- * Arguments:  @tunnel *t@ = pointer to tunnel block
- *
- * Returns:    A pointer to the tunnel's interface name.
- */
-
-extern const char *tun_ifname(tunnel */*t*/);
+/*----- Tunnel drivers ----------------------------------------------------*/
 
-/* --- @tun_inject@ --- *
- *
- * Arguments:  @tunnel *t@ = pointer to tunnel block
- *             @buf *b@ = buffer to send
- *
- * Returns:    ---
- *
- * Use:                Injects a packet into the local network stack.
- */
+#ifdef TUN_LINUX
+  extern const tunnel_ops tun_linux;
+#endif
 
-extern void tun_inject(tunnel */*t*/, buf */*b*/);
+#ifdef TUN_UNET
+  extern const tunnel_ops tun_unet;
+#endif
 
-/* --- @tun_destroy@ --- *
- *
- * Arguments:  @tunnel *t@ = pointer to tunnel block
- *
- * Returns:    ---
- *
- * Use:                Destroys a tunnel.
- */
+#ifdef TUN_BSD
+  extern const tunnel_ops tun_bsd;
+#endif
 
-extern void tun_destroy(tunnel */*t*/);
+extern const tunnel_ops tun_slip;
 
 /*----- Other handy utilities ---------------------------------------------*/
 
@@ -995,6 +921,15 @@ extern const char *gestr(group */*g*/, ge */*x*/);
 
 extern const char *timestr(time_t /*t*/);
 
+/* --- @mystrieq@ --- *
+ *
+ * Arguments:  @const char *x, *y@ = two strings
+ *
+ * Returns:    True if @x@ and @y are equal, up to case.
+ */
+
+extern int mystrieq(const char */*x*/, const char */*y*/);
+
 /*----- That's all, folks -------------------------------------------------*/
 
 #ifdef __cplusplus
index 620ea987e72b764ef19f4cde933420d4d66f4406..5efe5ef8dc09cabe11730fe0e1a3e08cf9da0113 100644 (file)
--- a/tun-bsd.c
+++ b/tun-bsd.c
 
 /*----- Header files ------------------------------------------------------*/
 
+#define TUN_INTERNALS
+
 #include "tripe.h"
 
 /*----- Main code ---------------------------------------------------------*/
 
-#if TUN_TYPE != TUN_BSD
-#  error "Tunnel type mismatch: fix the Makefile"
-#endif
+#ifdef TUN_BSD
+
+struct tunnel {
+  const tunnel_ops *ops;               /* Pointer to operations */
+  sel_file f;                          /* Selector for tunnel device */
+  struct peer *p;                      /* Pointer to my peer */
+  unsigned n;                          /* Number of my tunnel device */
+};  
+
+/* --- @t_ifname@ --- *
+ *
+ * Arguments:  @tunnel *t@ = pointer to tunnel block
+ *
+ * Returns:    A pointer to the tunnel's interface name.
+ */
+
+static const char *t_ifname(tunnel *t)
+{
+  static char buf[8];
+  sprintf(buf, "tun%u", t->n);
+  return (buf);
+}
 
 /* --- @t_read@ --- *
  *
@@ -47,7 +68,7 @@
  * Use:                Reads data from the tunnel.
  */
 
-void t_read(int fd, unsigned mode, void *v)
+static void t_read(int fd, unsigned mode, void *v)
 {
   tunnel *t = v;
   ssize_t n;
@@ -55,7 +76,7 @@ void t_read(int fd, unsigned mode, void *v)
 
   n = read(fd, buf_i, sizeof(buf_i));
   if (n < 0) {
-    a_warn("TUN %s read-error -- %s", tun_ifname(t), strerror(errno));
+    a_warn("TUN %s read-error -- %s", t_ifname(t), strerror(errno));
     return;
   }
   IF_TRACING(T_TUNNEL, {
@@ -66,7 +87,7 @@ void t_read(int fd, unsigned mode, void *v)
   p_tun(t->p, &b);
 }
 
-/* --- @tun_init@ --- *
+/* --- @t_init@ --- *
  *
  * Arguments:  ---
  *
@@ -76,25 +97,22 @@ void t_read(int fd, unsigned mode, void *v)
  *             opening file descriptors or something.
  */
 
-void tun_init(void)
-{
-  return;
-}
+static void t_init(void) { return; }
 
-/* --- @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)
 {
   int fd;
   unsigned n;
+  tunnel *t;
   char buf[16];
 
   n = 0;
@@ -108,7 +126,7 @@ int tun_create(tunnel *t, peer *p)
        break;
       case ENOENT:
        a_warn("TUN - bsd no-tunnel-devices");
-       return (-1);
+       return (0);
       default:
        a_warn("TUN - open-error %s -- %s", buf, strerror(errno));
        break;
@@ -116,31 +134,19 @@ int tun_create(tunnel *t, peer *p)
     n++;
   }
 
+  t = CREATE(tunnel);
+  t->ops = &tun_bsd;
   fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
   t->p = p;
   t->n = n;
   sel_initfile(&sel, &t->f, fd, SEL_READ, t_read, t);
   sel_addfile(&t->f);
   T( trace(T_TUNNEL, "tunnel: attached interface %s to peer `%s'",
-          tun_ifname(t), p_name(p)); )
-  return (0);
-}
-
-/* --- @tun_ifname@ --- *
- *
- * Arguments:  @tunnel *t@ = pointer to tunnel block
- *
- * Returns:    A pointer to the tunnel's interface name.
- */
-
-const char *tun_ifname(tunnel *t)
-{
-  static char buf[8];
-  sprintf(buf, "tun%u", t->n);
-  return (buf);
+          t_ifname(t), p_name(p)); )
+  return (t);
 }
 
-/* --- @tun_inject@ --- *
+/* --- @t_inject@ --- *
  *
  * Arguments:  @tunnel *t@ = pointer to tunnel block
  *             @buf *b@ = buffer to send
@@ -150,7 +156,7 @@ const char *tun_ifname(tunnel *t)
  * Use:                Injects a packet into the local network stack.
  */
 
-void tun_inject(tunnel *t, buf *b)
+static void t_inject(tunnel *t, buf *b)
 {
   IF_TRACING(T_TUNNEL, {
     trace(T_TUNNEL, "tunnel: inject decrypted packet");
@@ -159,7 +165,7 @@ void tun_inject(tunnel *t, buf *b)
   write(t->f.fd, BBASE(b), BLEN(b));
 }
 
-/* --- @tun_destroy@ --- *
+/* --- @t_destroy@ --- *
  *
  * Arguments:  @tunnel *t@ = pointer to tunnel block
  *
@@ -168,10 +174,22 @@ void tun_inject(tunnel *t, buf *b)
  * Use:                Destroys a tunnel.
  */
 
-void tun_destroy(tunnel *t)
+static void t_destroy(tunnel *t)
 {
   sel_rmfile(&t->f);
   close(t->f.fd);
+  DESTROY(t);
 }
 
+const tunnel_ops tun_bsd = {
+  "bsd",
+  t_init,
+  t_create,
+  t_ifname,
+  t_inject,
+  t_destroy
+};
+
+#endif
+
 /*----- That's all, folks -------------------------------------------------*/
index ff65a5e7b032c4b0dea12456ad8020156a3d93ab..8c7278cebd947dcc21fd7e087e3032acf4317a52 100644 (file)
 
 /*----- Header files ------------------------------------------------------*/
 
+#define TUN_INTERNALS
+
 #include "tripe.h"
 
-#include <sys/ioctl.h>
+#ifdef TUN_LINUX
+#  include <sys/ioctl.h>
+#  include <linux/if.h>
+#  include <linux/if_tun.h>
+#endif
 
 /*----- Main code ---------------------------------------------------------*/
 
-#if TUN_TYPE != TUN_LINUX
-#  error "Tunnel type mismatch: fix the Makefile"
-#endif
+#ifdef TUN_LINUX
+
+struct tunnel {
+  const tunnel_ops *ops;               /* Pointer to operations */
+  sel_file f;                          /* Selector for TUN/TAP device */
+  struct peer *p;                      /* Pointer to my peer */
+  char ifn[IFNAMSIZ];                  /* Interface name buffer */
+};  
 
 /* --- @t_read@ --- *
  *
@@ -68,7 +79,7 @@ static void t_read(int fd, unsigned mode, void *v)
   p_tun(t->p, &b);
 }
 
-/* --- @tun_init@ --- *
+/* --- @t_init@ --- *
  *
  * Arguments:  ---
  *
@@ -78,30 +89,27 @@ static void t_read(int fd, unsigned mode, void *v)
  *             opening file descriptors or something.
  */
 
-void tun_init(void)
-{
-  return;
-}
+static void t_init(void) { return; }
 
-/* --- @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)
 {
   int fd;
   int f;
   struct ifreq iff;
+  tunnel *t;
 
   if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
     a_warn("TUN - open-error /dev/net/tun -- %s", strerror(errno));
-    return (-1);
+    return (0);
   }
   fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
   iff.ifr_name[0] = 0;
@@ -109,8 +117,10 @@ int tun_create(tunnel *t, peer *p)
   if ((f = ioctl(fd, TUNSETIFF, &iff)) < 0) {
     a_warn("TUN - linux config-error -- %s", strerror(errno));
     close(fd);
-    return (-1);
+    return (0);
   }
+  t = CREATE(tunnel);
+  t->ops = &tun_linux;
   t->p = p;
   sel_initfile(&sel, &t->f, fd, SEL_READ, t_read, t);
   sel_addfile(&t->f);
@@ -118,22 +128,19 @@ int tun_create(tunnel *t, peer *p)
   strcpy(t->ifn, iff.ifr_name);
   T( trace(T_TUNNEL, "tunnel: attached interface %s to peer `%s'",
           t->ifn, p_name(p)); )
-  return (0);
+  return (t);
 }
 
-/* --- @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->ifn);
-}
+static const char *t_ifname(tunnel *t) { return (t->ifn); }
 
-/* --- @tun_inject@ --- *
+/* --- @t_inject@ --- *
  *
  * Arguments:  @tunnel *t@ = pointer to tunnel block
  *             @buf *b@ = buffer to send
@@ -143,7 +150,7 @@ const char *tun_ifname(tunnel *t)
  * Use:                Injects a packet into the local network stack.
  */
 
-void tun_inject(tunnel *t, buf *b)
+static void t_inject(tunnel *t, buf *b)
 {
   IF_TRACING(T_TUNNEL, {
     trace(T_TUNNEL, "tunnel: inject decrypted packet");
@@ -152,7 +159,7 @@ void tun_inject(tunnel *t, buf *b)
   write(t->f.fd, BBASE(b), BLEN(b));
 }
 
-/* --- @tun_destroy@ --- *
+/* --- @t_destroy@ --- *
  *
  * Arguments:  @tunnel *t@ = pointer to tunnel block
  *
@@ -161,10 +168,22 @@ void tun_inject(tunnel *t, buf *b)
  * Use:                Destroys a tunnel.
  */
 
-void tun_destroy(tunnel *t)
+static void t_destroy(tunnel *t)
 {
   sel_rmfile(&t->f);
   close(t->f.fd);
+  DESTROY(t);
 }
 
+const tunnel_ops tun_linux = {
+  "linux",
+  t_init,
+  t_create,
+  t_ifname,
+  t_inject,
+  t_destroy
+};
+
+#endif
+
 /*----- That's all, folks -------------------------------------------------*/
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 -------------------------------------------------*/
index 1cbdf2beaa86130f51d5e08402a89dadecfb0674..a6b53eb9ce13912b79cce75ae4493a5e4cdb03dd 100644 (file)
 
 /*----- Header files ------------------------------------------------------*/
 
+#define TUN_INTERNALS
+
 #include "tripe.h"
 
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <unet.h>
+#ifdef TUN_UNET
+#  include <sys/ioctl.h>
+#  include <net/if.h>
+#  include <unet.h>
+#endif
 
 /*----- Main code ---------------------------------------------------------*/
 
-#if TUN_TYPE != TUN_UNET
-#  error "Tunnel type mismatch: fix the Makefile"
-#endif
+#ifdef TUN_UNET
+
+struct tunnel {
+  const tunnel_ops *ops;               /* Pointer to operations */
+  sel_file f;                          /* Selector for Usernet device */
+  struct peer *p;                      /* Pointer to my peer */
+};
+
+/* --- @t_ifname@ --- *
+ *
+ * Arguments:  @tunnel *t@ = pointer to tunnel block
+ *
+ * Returns:    A pointer to the tunnel's interface name.
+ */
+
+static const char *t_ifname(tunnel *t)
+{
+  static char b[UNET_NAMEMAX];
+  struct unet_info uni;
+  if (ioctl(t->f.fd, UNIOCGINFO, &uni)) {
+    a_warn("TUN - unet getinfo-error -- %s", strerror(errno));
+    return ("<error>");
+  }
+  if (strlen(uni.uni_ifname) + 1 > sizeof(b)) {
+    a_warn("TUN - unet ifname-too-long");
+    return ("<error>");
+  }
+  strcpy(b, uni.uni_ifname);
+  return (b);
+}
 
 /* --- @t_read@ --- *
  *
@@ -59,7 +90,7 @@ static void t_read(int fd, unsigned mode, void *v)
 
   n = read(fd, buf_i, sizeof(buf_i));
   if (n < 0) {
-    a_warn("TUN %s read-error -- %s", tun_ifname(t), strerror(errno));
+    a_warn("TUN %s read-error -- %s", t_ifname(t), strerror(errno));
     return;
   }
   IF_TRACING(T_TUNNEL, {
@@ -70,7 +101,7 @@ static void t_read(int fd, unsigned mode, void *v)
   p_tun(t->p, &b);
 }
 
-/* --- @tun_init@ --- *
+/* --- @t_init@ --- *
  *
  * Arguments:  ---
  *
@@ -80,69 +111,46 @@ static void t_read(int fd, unsigned mode, void *v)
  *             opening file descriptors or something.
  */
 
-void tun_init(void)
-{
-  return;
-}
+static void t_init(void) { return; }
 
-/* --- @tun_create@ --- *
+/* --- @t_create@ --- *
  *
  * Arguments:  @tunnel *t@ = pointer to tunnel block
  *             @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)
 {
   int fd;
+  tunnel *t;
   int f;
 
   if ((fd = open("/dev/unet", O_RDWR)) < 0) {
     a_warn("TUN - open-error /dev/unet -- %s", strerror(errno));
-    return (-1);
+    return (0);
   }
   fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
   if ((f = ioctl(fd, UNIOCGIFFLAGS)) < 0 ||
       ioctl(fd, UNIOCSIFFLAGS, f | IFF_POINTOPOINT)) {
     a_warn("TUN - unet config-error -- %s", strerror(errno));
     close(fd);
-    return (-1);
+    return (0);
   }
+  t = CREATE(tunnel);
+  t->ops = &tun_unet;
   t->p = p;
   sel_initfile(&sel, &t->f, fd, SEL_READ, t_read, t);
   sel_addfile(&t->f);
   T( trace(T_TUNNEL, "tunnel: attached interface %s to peer `%s'",
-          tun_ifname(t), p_name(p)); )
-  return (0);
+          t_ifname(t), p_name(p)); )
+  return (t);
 }
 
-/* --- @tun_ifname@ --- *
- *
- * Arguments:  @tunnel *t@ = pointer to tunnel block
- *
- * Returns:    A pointer to the tunnel's interface name.
- */
-
-const char *tun_ifname(tunnel *t)
-{
-  static char b[UNET_NAMEMAX];
-  struct unet_info uni;
-  if (ioctl(t->f.fd, UNIOCGINFO, &uni)) {
-    a_warn("TUN - unet getinfo-error -- %s", strerror(errno));
-    return ("<error>");
-  }
-  if (strlen(uni.uni_ifname) + 1 > sizeof(b)) {
-    a_warn("TUN - unet ifname-too-long");
-    return ("<error>");
-  }
-  strcpy(b, uni.uni_ifname);
-  return (b);
-}
-
-/* --- @tun_inject@ --- *
+/* --- @t_inject@ --- *
  *
  * Arguments:  @tunnel *t@ = pointer to tunnel block
  *             @buf *b@ = buffer to send
@@ -152,7 +160,7 @@ const char *tun_ifname(tunnel *t)
  * Use:                Injects a packet into the local network stack.
  */
 
-void tun_inject(tunnel *t, buf *b)
+static void t_inject(tunnel *t, buf *b)
 {
   IF_TRACING(T_TUNNEL, {
     trace(T_TUNNEL, "tunnel: inject decrypted packet");
@@ -161,7 +169,7 @@ void tun_inject(tunnel *t, buf *b)
   write(t->f.fd, BBASE(b), BLEN(b));
 }
 
-/* --- @tun_destroy@ --- *
+/* --- @t_destroy@ --- *
  *
  * Arguments:  @tunnel *t@ = pointer to tunnel block
  *
@@ -170,10 +178,22 @@ void tun_inject(tunnel *t, buf *b)
  * Use:                Destroys a tunnel.
  */
 
-void tun_destroy(tunnel *t)
+static void t_destroy(tunnel *t)
 {
   sel_rmfile(&t->f);
   close(t->f.fd);
+  DESTROY(t);
 }
 
+const tunnel_ops tun_unet = {
+  "unet",
+  t_init,
+  t_create,
+  t_ifname,
+  t_inject,
+  t_destroy
+};
+
+#endif
+
 /*----- That's all, folks -------------------------------------------------*/