stun

simple point to point tunnel
git clone git://git.2f30.org/stun
Log | Files | Refs | README

commit 46117277d3218ec780839f7cb036ff4024eefb14
parent 8ea6d7e3d19a6d3f52ec3e801f2485118c51f8fa
Author: sin <sin@2f30.org>
Date:   Tue, 12 Apr 2016 10:44:33 +0100

reorg

Diffstat:
MMakefile | 7++++---
Mconfig.mk | 2++
Adev_bsd.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adev_linux.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Alog.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mstun.c | 291+------------------------------------------------------------------------------
Astun.h | 41+++++++++++++++++++++++++++++++++++++++++
Autil.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 347 insertions(+), 291 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,8 +1,9 @@ include config.mk DISTFILES = Makefile README WHATSNEW UNLICENSE arg.h \ - config.mk stun.8 stun.c -OBJ = stun.o + config.mk dev_bsd.c dev_linux.c log.c stun.8 stun.c \ + stun.h util.c +OBJ = $(EXTRAOBJ) log.o stun.o util.o BIN = stun all: $(BIN) @@ -10,7 +11,7 @@ all: $(BIN) $(BIN): $(OBJ) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(OBJ) $(LDLIBS) -stun.o: arg.h +$(OBJ): stun.h install: all mkdir -p $(DESTDIR)$(PREFIX)/bin diff --git a/config.mk b/config.mk @@ -9,8 +9,10 @@ LIB = /usr/local/lib # BSD CFLAGS = -std=c99 -Wall -I$(INC) LDLIBS = -L$(LIB) -lcrypto +EXTRAOBJ = dev_bsd.o # Linux #CFLAGS = -std=c99 -Wall -I$(INC) #CPPFLAGS = -D_XOPEN_SOURCE=700 -D_GNU_SOURCE #LDLIBS = -L$(LIB) -lcrypto -lbsd +#EXTRAOBJ = dev_linux.o diff --git a/dev_bsd.c b/dev_bsd.c @@ -0,0 +1,88 @@ +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <net/if.h> +#if defined(__OpenBSD__) || defined(__FreeBSD__) +#include <net/if_tun.h> +#elif defined(__DragonFly__) +#include <net/tun/if_tun.h> +#endif + +#include <fcntl.h> +#include <unistd.h> + +#include "stun.h" + +int +opendev(char *dev) +{ + struct tuninfo ti; + int fd; + + if ((fd = open(dev, O_RDWR)) < 0) + logerr("failed to open %s", dev); + if (ioctl(fd, TUNGIFINFO, &ti) < 0) + logerr("failed to set TUNGIFINFO on %s", dev); + if (devtype == TUNDEV) + ti.mtu = MAXPAYLOADLEN; + else + ti.mtu = MAXPAYLOADLEN - 14; /* make some room for ethernet header */ + if (ioctl(fd, TUNSIFINFO, &ti) < 0) + logerr("failed to set TUNSIFINFO on %s", dev); + if (devtype == TUNDEV) { +#if defined(TUNSIFHEAD) + int one = 1; + if (ioctl(fd, TUNSIFHEAD, &one) < 0) + logerr("failed to set TUNSIFHEAD on %s", dev); +#endif + } + return fd; +} + +int +writedev(int fd, unsigned char *buf, int len) +{ + struct iovec iov[2]; + uint32_t type = htonl(AF_INET); + int n; + + switch (devtype) { + case TAPDEV: + return write(fd, buf, len); + case TUNDEV: + iov[0].iov_base = &type; + iov[0].iov_len = sizeof(type); + iov[1].iov_base = buf; + iov[1].iov_len = len; + n = writev(fd, iov, 2); + if (n > 0) + n -= sizeof(type); + break; + } + return n; +} + +int +readdev(int fd, unsigned char *buf, int len) +{ + struct iovec iov[2]; + uint32_t type; + int n; + + switch (devtype) { + case TAPDEV: + return read(fd, buf, len); + case TUNDEV: + iov[0].iov_base = &type; + iov[0].iov_len = sizeof(type); + iov[1].iov_base = buf; + iov[1].iov_len = len; + n = readv(fd, iov, 2); + if (n > 0) + n -= sizeof(type); + break; + } + return n; +} diff --git a/dev_linux.c b/dev_linux.c @@ -0,0 +1,53 @@ +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <linux/if_tun.h> + +#include <fcntl.h> +#include <string.h> +#include <unistd.h> + +#include "stun.h" + +int +opendev(char *dev) +{ + struct ifreq ifr; + int fd, s; + + if ((fd = open("/dev/net/tun", O_RDWR)) < 0) + logerr("failed to open %s", "/dev/net/tun"); + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = (devtype == TUNDEV ? IFF_TUN : IFF_TAP) | IFF_NO_PI; + strncpy(ifr.ifr_name, dev, IF_NAMESIZE); + ifr.ifr_name[IF_NAMESIZE - 1] = '\0'; + if (ioctl(fd, TUNSETIFF, &ifr) < 0) + logerr("failed to set TUNSETIFF on %s", dev); + + /* dummy socket so we can manipulate the params */ + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) + logerr("failed to create socket"); + if (devtype == TUNDEV) + ifr.ifr_mtu = MAXPAYLOADLEN; + else + ifr.ifr_mtu = MAXPAYLOADLEN - 14; /* make some room for ethernet header */ + if (ioctl(s, SIOCSIFMTU, &ifr) < 0) + logerr("failed to set MTU on %s", dev); + close(s); + + return fd; +} + +int +writedev(int fd, unsigned char *buf, int len) +{ + return write(fd, buf, len); +} + +int +readdev(int fd, unsigned char *buf, int len) +{ + return read(fd, buf, len); +} diff --git a/log.c b/log.c @@ -0,0 +1,57 @@ +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <syslog.h> + +#include "stun.h" + +static void +logmsg(int priority, char *msg, va_list ap) +{ + if (foreground) { + fputs("stun: ", stderr); + vfprintf(stderr, msg, ap); + fputc('\n', stderr); + } else { + vsyslog(priority, msg, ap); + } +} + +void +loginit(char *prog) +{ + openlog(prog, LOG_PID | LOG_NDELAY, LOG_DAEMON); +} + +void +logdbg(char *msg, ...) +{ + va_list ap; + + if (debug) { + va_start(ap, msg); + logmsg(LOG_DAEMON | LOG_DEBUG, msg, ap); + va_end(ap); + } +} + +void +logwarn(char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + logmsg(LOG_DAEMON | LOG_WARNING, msg, ap); + va_end(ap); +} + +void +logerr(char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + logmsg(LOG_DAEMON | LOG_ERR, msg, ap); + va_end(ap); + exit(1); +} diff --git a/stun.c b/stun.c @@ -42,20 +42,9 @@ */ #include <sys/types.h> -#include <sys/uio.h> -#include <sys/ioctl.h> #include <sys/resource.h> #include <sys/socket.h> -#include <net/if.h> -#if defined(__linux__) -#include <linux/if_tun.h> -#include <bsd/stdlib.h> -#elif defined(__OpenBSD__) || defined(__FreeBSD__) -#include <net/if_tun.h> -#elif defined(__DragonFly__) -#include <net/tun/if_tun.h> -#endif #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> @@ -63,41 +52,19 @@ #include <errno.h> #include <fcntl.h> -#include <grp.h> #include <poll.h> -#include <pwd.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> -#include <syslog.h> #include <time.h> #include <unistd.h> #include <openssl/evp.h> -#include "arg.h" - -#if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) -#undef explicit_bzero -#define explicit_bzero bzero -#endif - -#define NOPRIVUSER "nobody" -#define RCVTIMEO 250 /* in milliseconds */ -#define RECONNECTTIMEO 60 /* in seconds */ -#define HDRLEN 2 -#define MAXPAYLOADLEN 1424 -#define BADPKT 0x1000 -#define NROUNDS 100000 -#define DEFCIPHER "chacha20-poly1305" - -enum { - TUNDEV, - TAPDEV -}; +#include "stun.h" EVP_AEAD_CTX ectx, dctx; const EVP_AEAD *aead; @@ -112,258 +79,6 @@ int debug; int foreground; int sflag; -void -logmsg(int priority, char *msg, va_list ap) -{ - if (foreground) { - fputs("stun: ", stderr); - vfprintf(stderr, msg, ap); - fputc('\n', stderr); - } else { - vsyslog(priority, msg, ap); - } -} - -void -logdbg(char *msg, ...) -{ - va_list ap; - - if (debug) { - va_start(ap, msg); - logmsg(LOG_DAEMON | LOG_DEBUG, msg, ap); - va_end(ap); - } -} - -void -logwarn(char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - logmsg(LOG_DAEMON | LOG_WARNING, msg, ap); - va_end(ap); -} - -void -logerr(char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - logmsg(LOG_DAEMON | LOG_ERR, msg, ap); - va_end(ap); - exit(1); -} - -void -pack16(unsigned char *buf, uint16_t n) -{ - buf[0] = n >> 8 & 0xff; - buf[1] = n & 0xff; -} - -uint16_t -unpack16(unsigned char *buf) -{ - return buf[0] << 8 | buf[1]; -} - -void -pack64(unsigned char *buf, uint64_t n) -{ - buf[0] = n >> 56 & 0xff; - buf[1] = n >> 48 & 0xff; - buf[2] = n >> 40 & 0xff; - buf[3] = n >> 32 & 0xff; - buf[4] = n >> 24 & 0xff; - buf[5] = n >> 16 & 0xff; - buf[6] = n >> 8 & 0xff; - buf[7] = n & 0xff; -} - -uint64_t -unpack64(unsigned char *buf) -{ - return (uint64_t)buf[0] << 56 | - (uint64_t)buf[1] << 48 | - (uint64_t)buf[2] << 40 | - (uint64_t)buf[3] << 32 | - (uint64_t)buf[4] << 24 | - (uint64_t)buf[5] << 16 | - (uint64_t)buf[6] << 8 | - (uint64_t)buf[7]; -} - -int -writeall(int fd, void *buf, int len) -{ - unsigned char *p = buf; - int n, total = 0; - - while (len > 0) { - n = write(fd, p + total, len); - if (n <= 0) - break; - total += n; - len -= n; - } - return total; -} - -int -readall(int fd, void *buf, int len) -{ - unsigned char *p = buf; - int n, total = 0; - - while (len > 0) { - n = read(fd, p + total, len); - if (n <= 0) - break; - total += n; - len -= n; - } - return total; -} - -void -ms2tv(struct timeval *tv, long ms) -{ - tv->tv_sec = ms / 1000; - tv->tv_usec = (ms % 1000) * 1000; -} - -void -revokeprivs(void) -{ - struct passwd *pw; - - if (!(pw = getpwnam(NOPRIVUSER))) - logerr("no %s user", NOPRIVUSER); - if (setgroups(1, &pw->pw_gid) < 0 || - setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0 || - setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) - logerr("failed to revoke privs"); -} - -#if defined(__linux__) -int -opendev(char *dev) -{ - struct ifreq ifr; - int fd, s; - - if ((fd = open("/dev/net/tun", O_RDWR)) < 0) - logerr("failed to open %s", "/dev/net/tun"); - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = (devtype == TUNDEV ? IFF_TUN : IFF_TAP) | IFF_NO_PI; - strncpy(ifr.ifr_name, dev, IF_NAMESIZE); - ifr.ifr_name[IF_NAMESIZE - 1] = '\0'; - if (ioctl(fd, TUNSETIFF, &ifr) < 0) - logerr("failed to set TUNSETIFF on %s", dev); - - /* dummy socket so we can manipulate the params */ - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) - logerr("failed to create socket"); - if (devtype == TUNDEV) - ifr.ifr_mtu = MAXPAYLOADLEN; - else - ifr.ifr_mtu = MAXPAYLOADLEN - 14; /* make some room for ethernet header */ - if (ioctl(s, SIOCSIFMTU, &ifr) < 0) - logerr("failed to set MTU on %s", dev); - close(s); - - return fd; -} - -int -writedev(int fd, unsigned char *buf, int len) -{ - return write(fd, buf, len); -} - -int -readdev(int fd, unsigned char *buf, int len) -{ - return read(fd, buf, len); -} -#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) -int -opendev(char *dev) -{ - struct tuninfo ti; - int fd; - - if ((fd = open(dev, O_RDWR)) < 0) - logerr("failed to open %s", dev); - if (ioctl(fd, TUNGIFINFO, &ti) < 0) - logerr("failed to set TUNGIFINFO on %s", dev); - if (devtype == TUNDEV) - ti.mtu = MAXPAYLOADLEN; - else - ti.mtu = MAXPAYLOADLEN - 14; /* make some room for ethernet header */ - if (ioctl(fd, TUNSIFINFO, &ti) < 0) - logerr("failed to set TUNSIFINFO on %s", dev); - if (devtype == TUNDEV) { -#if defined(TUNSIFHEAD) - int one = 1; - if (ioctl(fd, TUNSIFHEAD, &one) < 0) - logerr("failed to set TUNSIFHEAD on %s", dev); -#endif - } - return fd; -} - -int -writedev(int fd, unsigned char *buf, int len) -{ - struct iovec iov[2]; - uint32_t type = htonl(AF_INET); - int n; - - switch (devtype) { - case TAPDEV: - return write(fd, buf, len); - case TUNDEV: - iov[0].iov_base = &type; - iov[0].iov_len = sizeof(type); - iov[1].iov_base = buf; - iov[1].iov_len = len; - n = writev(fd, iov, 2); - if (n > 0) - n -= sizeof(type); - break; - } - return n; -} - -int -readdev(int fd, unsigned char *buf, int len) -{ - struct iovec iov[2]; - uint32_t type; - int n; - - switch (devtype) { - case TAPDEV: - return read(fd, buf, len); - case TUNDEV: - iov[0].iov_base = &type; - iov[0].iov_len = sizeof(type); - iov[1].iov_base = buf; - iov[1].iov_len = len; - n = readv(fd, iov, 2); - if (n > 0) - n -= sizeof(type); - break; - } - return n; -} -#endif - int writenet(int fd, unsigned char *pt, int ptlen) { @@ -755,7 +470,7 @@ main(int argc, char *argv[]) signal(SIGPIPE, SIG_IGN); if (!foreground) { daemon(0, 0); - openlog("stun", LOG_PID | LOG_NDELAY, LOG_DAEMON); + loginit("stun"); } devfd = opendev(argv[0]); @@ -767,7 +482,7 @@ main(int argc, char *argv[]) if (!(pw = getenv("STUNPW"))) logerr("STUNPW is not set"); aeadinit(pw); - explicit_bzero(pw, strlen(pw)); + bzero(pw, strlen(pw)); if (sflag) return serversetup(devfd); diff --git a/stun.h b/stun.h @@ -0,0 +1,41 @@ +#include "arg.h" + +#define NOPRIVUSER "nobody" +#define RCVTIMEO 250 /* in milliseconds */ +#define RECONNECTTIMEO 60 /* in seconds */ +#define HDRLEN 2 +#define MAXPAYLOADLEN 1424 +#define BADPKT 0x1000 +#define NROUNDS 100000 +#define DEFCIPHER "chacha20-poly1305" + +enum { + TUNDEV, + TAPDEV +}; + +/* stun.c */ +extern int devtype; +extern int debug; +extern int foreground; + +/* dev_*.c */ +int opendev(char *); +int writedev(int, unsigned char *, int); +int readdev(int, unsigned char *, int); + +/* log.c */ +void loginit(char *); +void logdbg(char *, ...); +void logwarn(char *, ...); +void logerr(char *, ...); + +/* util.c */ +void pack16(unsigned char *, uint16_t); +uint16_t unpack16(unsigned char *); +void pack64(unsigned char *, uint64_t); +uint64_t unpack64(unsigned char *); +int writeall(int, void *, int); +int readall(int, void *, int); +void ms2tv(struct timeval *, long); +void revokeprivs(void); diff --git a/util.c b/util.c @@ -0,0 +1,99 @@ +#include <sys/types.h> + +#include <grp.h> +#include <pwd.h> +#include <stdint.h> +#include <unistd.h> + +#include "stun.h" + +void +pack16(unsigned char *buf, uint16_t n) +{ + buf[0] = n >> 8 & 0xff; + buf[1] = n & 0xff; +} + +uint16_t +unpack16(unsigned char *buf) +{ + return buf[0] << 8 | buf[1]; +} + +void +pack64(unsigned char *buf, uint64_t n) +{ + buf[0] = n >> 56 & 0xff; + buf[1] = n >> 48 & 0xff; + buf[2] = n >> 40 & 0xff; + buf[3] = n >> 32 & 0xff; + buf[4] = n >> 24 & 0xff; + buf[5] = n >> 16 & 0xff; + buf[6] = n >> 8 & 0xff; + buf[7] = n & 0xff; +} + +uint64_t +unpack64(unsigned char *buf) +{ + return (uint64_t)buf[0] << 56 | + (uint64_t)buf[1] << 48 | + (uint64_t)buf[2] << 40 | + (uint64_t)buf[3] << 32 | + (uint64_t)buf[4] << 24 | + (uint64_t)buf[5] << 16 | + (uint64_t)buf[6] << 8 | + (uint64_t)buf[7]; +} + +int +writeall(int fd, void *buf, int len) +{ + unsigned char *p = buf; + int n, total = 0; + + while (len > 0) { + n = write(fd, p + total, len); + if (n <= 0) + break; + total += n; + len -= n; + } + return total; +} + +int +readall(int fd, void *buf, int len) +{ + unsigned char *p = buf; + int n, total = 0; + + while (len > 0) { + n = read(fd, p + total, len); + if (n <= 0) + break; + total += n; + len -= n; + } + return total; +} + +void +ms2tv(struct timeval *tv, long ms) +{ + tv->tv_sec = ms / 1000; + tv->tv_usec = (ms % 1000) * 1000; +} + +void +revokeprivs(void) +{ + struct passwd *pw; + + if (!(pw = getpwnam(NOPRIVUSER))) + logerr("no %s user", NOPRIVUSER); + if (setgroups(1, &pw->pw_gid) < 0 || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0 || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) + logerr("failed to revoke privs"); +}