commit d12c68144ff41349151b939a6884bd79ca37c522
parent 3b1d275c0075b0c9e2c72ef98db9bff196051b7e
Author: sin <sin@2f30.org>
Date: Thu, 14 Apr 2016 11:01:52 +0100
rework ipv6/ipv4 support by inspecting the version field in the ip header
Diffstat:
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;
+}