stun

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

commit d12c68144ff41349151b939a6884bd79ca37c522
parent 3b1d275c0075b0c9e2c72ef98db9bff196051b7e
Author: sin <sin@2f30.org>
Date:   Thu Apr 14 11:01:52 +0100

rework ipv6/ipv4 support by inspecting the version field in the ip header

Diffstat:
README | 4++--
client.c | 3+--
dev_bsd.c | 10+++++++---
dev_linux.c | 10+++++-----
server.c | 3+--
stun.8 | 8++++++--
stun.h | 3++-
tunnel.c | 17+++++++++++++----
util.c | 20++++++++++++++++++++
9 files changed, 57 insertions(+), 21 deletions(-)
diff --git a/README b/README @@ -16,13 +16,13 @@ On the server: ifconfig tun0 create ifconfig tun0 10.0.0.1 10.0.0.2 - STUNPW=pass stun -s /dev/tun0 + STUNPW=pass stun -s tun0 On the client: ifconfig tun0 create ifconfig tun0 10.0.0.2 10.0.0.1 - STUNPW=pass stun -h hostname /dev/tun0 + STUNPW=pass stun -h hostname tun0 TCP port 12080 must be opened on the server side. diff --git a/client.c b/client.c @@ -24,8 +24,7 @@ clientconnect(char *host, char *port) logerr("getaddrinfo: %s", gai_strerror(ret)); for (p = ai; p; p = p->ai_next) { - if (p->ai_family != AF_INET && - p->ai_family != AF_INET6) + if (p->ai_family != aftype) continue; if ((netfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) diff --git a/dev_bsd.c b/dev_bsd.c @@ -12,16 +12,20 @@ #include <netinet/in.h> #include <fcntl.h> +#include <limits.h> +#include <stdio.h> #include <unistd.h> #include "stun.h" int -devopen(char *dev) +devopen(char *ifname) { + char dev[PATH_MAX]; struct tuninfo ti; int fd; + snprintf(dev, sizeof(dev), "/dev/%s", ifname); if ((fd = open(dev, O_RDWR)) < 0) logerr("failed to open %s", dev); if (ioctl(fd, TUNGIFINFO, &ti) < 0) @@ -43,10 +47,10 @@ devopen(char *dev) } int -devwrite(int fd, unsigned char *buf, int len) +devwrite(int fd, unsigned char *buf, int len, int af) { struct iovec iov[2]; - uint32_t type = htonl(aftype); + uint32_t type = htonl(af); int n; switch (devtype) { diff --git a/dev_linux.c b/dev_linux.c @@ -12,7 +12,7 @@ #include "stun.h" int -devopen(char *dev) +devopen(char *ifname) { struct ifreq ifr; int fd, s; @@ -22,10 +22,10 @@ devopen(char *dev) memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = (devtype == TUNDEV ? IFF_TUN : IFF_TAP) | IFF_NO_PI; - strncpy(ifr.ifr_name, dev, IF_NAMESIZE); + strncpy(ifr.ifr_name, ifname, IF_NAMESIZE); ifr.ifr_name[IF_NAMESIZE - 1] = '\0'; if (ioctl(fd, TUNSETIFF, &ifr) < 0) - logerr("failed to set TUNSETIFF on %s", dev); + logerr("failed to set TUNSETIFF on %s", ifname); /* dummy socket so we can manipulate the params */ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) @@ -35,14 +35,14 @@ devopen(char *dev) 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); + logerr("failed to set MTU on %s", ifname); close(s); return fd; } int -devwrite(int fd, unsigned char *buf, int len) +devwrite(int fd, unsigned char *buf, int len, int af) { return write(fd, buf, len); } diff --git a/server.c b/server.c @@ -28,8 +28,7 @@ serverinit(char *host, char *port) logerr("getaddrinfo: %s", gai_strerror(ret)); for (p = ai; p; p = p->ai_next) { - if (p->ai_family != AF_INET && - p->ai_family != AF_INET6) + if (p->ai_family != aftype) continue; if ((listenfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) diff --git a/stun.8 b/stun.8 @@ -30,9 +30,13 @@ stack on the server side. .Sh OPTIONS .Bl -tag -width "-b address" .It Fl 4 -Set the tunnel address family to IPv4. +Force +.Nm +to use IPv4 addresses only. .It Fl 6 -Set the tunnel address family to IPv6. +Force +.Nm +to use IPv6 addresses only. .It Fl d Enable debug output. This will make .Nm diff --git a/stun.h b/stun.h @@ -51,7 +51,7 @@ int cryptoopen(unsigned char *, size_t *, size_t, const unsigned char *, /* dev_*.c */ int devopen(char *); -int devwrite(int, unsigned char *, int); +int devwrite(int, unsigned char *, int, int); int devread(int, unsigned char *, int); /* log.c */ @@ -82,3 +82,4 @@ void revokeprivs(void); int setnonblock(int, int); char *saddr_ntop(struct sockaddr *, socklen_t); char *peer_ntop(int); +int ipversion(unsigned char *); diff --git a/tunnel.c b/tunnel.c @@ -6,9 +6,10 @@ int tunnel(int netfd, int devfd) { unsigned char buf[MAXPAYLOADLEN]; + struct ip *ip; size_t outlen; struct pollfd pfd[2]; - int n; + int n, af; pfd[0].fd = netfd; pfd[0].events = POLLIN; @@ -22,10 +23,18 @@ tunnel(int netfd, int devfd) if (pfd[0].revents & (POLLIN | POLLHUP)) { n = netread(netfd, buf, sizeof(buf), &outlen); - if (n == PKTFAILED) + if (n == PKTFAILED) { return -1; - else if (n == PKTCOMPLETE) - devwrite(devfd, buf, outlen); + } else if (n == PKTCOMPLETE) { + if (devtype == TUNDEV) { + if ((af = ipversion(buf)) > 0) + devwrite(devfd, buf, outlen, af); + } else { + /* address family does not need to be specified + * for TAP devices */ + devwrite(devfd, buf, outlen, -1); + } + } } if (pfd[1].revents & (POLLIN | POLLHUP)) { diff --git a/util.c b/util.c @@ -1,5 +1,7 @@ #include <sys/types.h> +#include <netinet/in.h> +#include <netinet/ip.h> #include <netdb.h> #include <fcntl.h> @@ -111,3 +113,21 @@ peer_ntop(int fd) } return saddr_ntop((struct sockaddr *)&ss, sslen); } + +int +ipversion(unsigned char *pkt) +{ + struct ip *ip; + + ip = (struct ip *)pkt; + switch (ip->ip_v) { + case 4: + return AF_INET; + case 6: + return AF_INET6; + default: + logwarn("unknown protocol version: %d", ip->ip_v); + break; + } + return -1; +}