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