From 42da2a58637902f3bba731a83538804e57e340bf Mon Sep 17 00:00:00 2001 Message-Id: <42da2a58637902f3bba731a83538804e57e340bf.1714099350.git.mdw@distorted.org.uk> From: Mark Wooding Date: Mon, 12 Sep 2005 14:00:00 +0000 Subject: [PATCH] General overhaul of tunnelling: allow multiple tunnel drivers in one daemon, running at the same time. Organization: Straylight/Edgeware From: mdw --- Makefile.am | 5 +- admin.c | 77 +++++++++++++++++-------- configure.in | 35 +++++++----- debian/control | 5 +- debian/rules | 1 + doc/tripe-admin.5 | 67 ++++++++++++++-------- doc/tripe.8 | 11 +++- peer.c | 34 ++++++++--- tripe-init.in | 3 +- tripe.c | 84 ++++++++++++++++++--------- tripe.conf | 4 ++ tripe.h | 141 +++++++++++++--------------------------------- tun-bsd.c | 90 +++++++++++++++++------------ tun-linux.c | 71 ++++++++++++++--------- tun-slip.c | 128 +++++++++++++++++++++++++---------------- tun-unet.c | 112 +++++++++++++++++++++--------------- 16 files changed, 506 insertions(+), 362 deletions(-) diff --git a/Makefile.am b/Makefile.am index bbf743ea..f5f5a255 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 57d9ccfa..24d86c64 100644 --- 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 } }; diff --git a/configure.in b/configure.in index c6d702e7..d0c2dbd7 100644 --- a/configure.in +++ b/configure.in @@ -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"]) diff --git a/debian/control b/debian/control index 337580a5..4386a9a3 100644 --- a/debian/control +++ b/debian/control @@ -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 diff --git a/debian/rules b/debian/rules index e164a834..6a52d030 100755 --- a/debian/rules +++ b/debian/rules @@ -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 \ diff --git a/doc/tripe-admin.5 b/doc/tripe-admin.5 index 1b101e6a..79874e91 100644 --- a/doc/tripe-admin.5 +++ b/doc/tripe-admin.5 @@ -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 diff --git a/doc/tripe.8 b/doc/tripe.8 index 7ff497c3..40a5b657 100644 --- a/doc/tripe.8 +++ b/doc/tripe.8 @@ -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 15243b71..402d08b5 100644 --- a/peer.c +++ b/peer.c @@ -35,6 +35,22 @@ 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; diff --git a/tripe-init.in b/tripe-init.in index 82ada434..b4c5e6d7 100755 --- a/tripe-init.in +++ b/tripe-init.in @@ -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 180177ee..202a843a 100644 --- 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(); } } } diff --git a/tripe.conf b/tripe.conf index dd2de57e..8105a2a1 100644 --- a/tripe.conf +++ b/tripe.conf @@ -25,6 +25,10 @@ # 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 6dbfbad3..9cf7abf3 100644 --- a/tripe.h +++ b/tripe.h @@ -106,14 +106,6 @@ /*----- 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 -# include -#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 diff --git a/tun-bsd.c b/tun-bsd.c index 620ea987..5efe5ef8 100644 --- a/tun-bsd.c +++ b/tun-bsd.c @@ -28,13 +28,34 @@ /*----- 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 -------------------------------------------------*/ diff --git a/tun-linux.c b/tun-linux.c index ff65a5e7..8c7278ce 100644 --- a/tun-linux.c +++ b/tun-linux.c @@ -28,15 +28,26 @@ /*----- Header files ------------------------------------------------------*/ +#define TUN_INTERNALS + #include "tripe.h" -#include +#ifdef TUN_LINUX +# include +# include +# include +#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 -------------------------------------------------*/ diff --git a/tun-slip.c b/tun-slip.c index b9914e43..2d94033b 100644 --- a/tun-slip.c +++ b/tun-slip.c @@ -28,8 +28,35 @@ /*----- 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 -------------------------------------------------*/ diff --git a/tun-unet.c b/tun-unet.c index 1cbdf2be..a6b53eb9 100644 --- a/tun-unet.c +++ b/tun-unet.c @@ -28,17 +28,48 @@ /*----- Header files ------------------------------------------------------*/ +#define TUN_INTERNALS + #include "tripe.h" -#include -#include -#include +#ifdef TUN_UNET +# include +# include +# include +#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 (""); + } + if (strlen(uni.uni_ifname) + 1 > sizeof(b)) { + a_warn("TUN - unet ifname-too-long"); + return (""); + } + 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 (""); - } - if (strlen(uni.uni_ifname) + 1 > sizeof(b)) { - a_warn("TUN - unet ifname-too-long"); - return (""); - } - 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 -------------------------------------------------*/ -- [mdw]