summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/tuntap.c143
1 files changed, 113 insertions, 30 deletions
diff --git a/src/tuntap.c b/src/tuntap.c
index fb7026f..bf0c49c 100644
--- a/src/tuntap.c
+++ b/src/tuntap.c
@@ -31,14 +31,30 @@
#include <sys/ioctl.h>
-#if defined(__linux__)
+#ifdef __linux__
#include <linux/if_tun.h>
+#else
+
+#include <net/if_tun.h>
+
+#ifdef __FreeBSD__
+#include <net/if_tap.h>
+#endif
+
+#endif
+
+#ifdef __linux__
static const bool multiaf_tun = false;
+#else
+static const bool multiaf_tun = true;
+#endif
+#if defined(__linux__)
+
void fastd_tuntap_open(fastd_context_t *ctx) {
struct ifreq ifr = {};
@@ -88,30 +104,22 @@ void fastd_tuntap_open(fastd_context_t *ctx) {
pr_debug(ctx, "tun/tap device initialized.");
}
-#elif defined(__FreeBSD__)
-
-#include <net/if_tun.h>
-#include <net/if_tap.h>
-
-
-static const bool multiaf_tun = true;
+#elif defined(__FreeBSD__) || defined(__OpenBSD__)
+static void set_tun_mtu(fastd_context_t *ctx) {
+ struct tuninfo tuninfo;
-static void setup_tap(fastd_context_t *ctx) {
- struct ifreq ifr = {};
+ if (ioctl(ctx->tunfd, TUNGIFINFO, &tuninfo) < 0)
+ exit_errno(ctx, "TUNGIFINFO ioctl failed");
- if (ioctl(ctx->tunfd, TAPGIFNAME, &ifr) < 0)
- exit_errno(ctx, "TAPGIFNAME ioctl failed");
+ tuninfo.mtu = ctx->conf->mtu;
- free(ctx->ifname);
- ctx->ifname = strndup(ifr.ifr_name, IFNAMSIZ-1);
+ if (ioctl(ctx->tunfd, TUNSIFINFO, &tuninfo) < 0)
+ exit_errno(ctx, "TUNSIFINFO ioctl failed");
}
-static void setup_tun(fastd_context_t *ctx) {
- int one = 1;
- if (ioctl(ctx->tunfd, TUNSIFHEAD, &one) < 0)
- exit_errno(ctx, "TUNSIFHEAD ioctl failed");
-}
+
+#ifdef __FreeBSD__
static void set_tap_mtu(fastd_context_t *ctx) {
struct tapinfo tapinfo;
@@ -125,16 +133,24 @@ static void set_tap_mtu(fastd_context_t *ctx) {
exit_errno(ctx, "TAPSIFINFO ioctl failed");
}
-static void set_tun_mtu(fastd_context_t *ctx) {
- struct tuninfo tuninfo;
+static void setup_tun(fastd_context_t *ctx) {
+ int one = 1;
+ if (ioctl(ctx->tunfd, TUNSIFHEAD, &one) < 0)
+ exit_errno(ctx, "TUNSIFHEAD ioctl failed");
- if (ioctl(ctx->tunfd, TUNGIFINFO, &tuninfo) < 0)
- exit_errno(ctx, "TUNGIFINFO ioctl failed");
+ set_tun_mtu(ctx);
+}
- tuninfo.mtu = ctx->conf->mtu;
+static void setup_tap(fastd_context_t *ctx) {
+ struct ifreq ifr = {};
- if (ioctl(ctx->tunfd, TUNSIFINFO, &tuninfo) < 0)
- exit_errno(ctx, "TUNSIFINFO ioctl failed");
+ if (ioctl(ctx->tunfd, TAPGIFNAME, &ifr) < 0)
+ exit_errno(ctx, "TAPGIFNAME ioctl failed");
+
+ free(ctx->ifname);
+ ctx->ifname = strndup(ifr.ifr_name, IFNAMSIZ-1);
+
+ set_tap_mtu(ctx);
}
void fastd_tuntap_open(fastd_context_t *ctx) {
@@ -168,18 +184,16 @@ void fastd_tuntap_open(fastd_context_t *ctx) {
switch (ctx->conf->mode) {
case MODE_TAP:
if (strncmp(ctx->ifname, "tap", 3) != 0)
- exit_error(ctx, "opened device doesn't to be a tap device");
+ exit_error(ctx, "opened device doesn't seem to be a tap device");
setup_tap(ctx);
- set_tap_mtu(ctx);
break;
case MODE_TUN:
if (strncmp(ctx->ifname, "tun", 3) != 0)
- exit_error(ctx, "opened device doesn't to be a tun device");
+ exit_error(ctx, "opened device doesn't seem to be a tun device");
setup_tun(ctx);
- set_tun_mtu(ctx);
break;
default:
@@ -189,6 +203,75 @@ void fastd_tuntap_open(fastd_context_t *ctx) {
pr_debug(ctx, "tun/tap device initialized.");
}
+#else /* __OpenBSD__ */
+
+static void set_link0(fastd_context_t *ctx, bool set) {
+ struct ifreq ifr = {};
+
+ int ctl_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (ctl_sock < 0)
+ exit_errno(ctx, "socket");
+
+ strncpy(ifr.ifr_name, ctx->ifname, IFNAMSIZ-1);
+ if (ioctl(ctl_sock, SIOCGIFFLAGS, &ifr) < 0)
+ exit_errno(ctx, "SIOCGIFFLAGS ioctl failed");
+
+ if (set)
+ ifr.ifr_flags |= IFF_LINK0;
+ else
+ ifr.ifr_flags &= ~IFF_LINK0;
+
+ if (ioctl(ctl_sock, SIOCSIFFLAGS, &ifr) < 0)
+ exit_errno(ctx, "SIOCSIFFLAGS ioctl failed");
+
+ if (close(ctl_sock))
+ pr_error_errno(ctx, "close");
+}
+
+static void setup_tun(fastd_context_t *ctx) {
+ set_link0(ctx, false);
+ set_tun_mtu(ctx);
+}
+
+static void setup_tap(fastd_context_t *ctx) {
+ set_link0(ctx, true);
+ set_tun_mtu(ctx);
+}
+
+void fastd_tuntap_open(fastd_context_t *ctx) {
+ char ifname[5+IFNAMSIZ] = "/dev/";
+ if (!ctx->conf->ifname)
+ exit_error(ctx, "config error: no interface name given.");
+ else if (strncmp(ctx->conf->ifname, "tun", 3) != 0)
+ exit_error(ctx, "config error: `%s' doesn't seem to be a tun device", ctx->conf->ifname);
+ else
+ strncat(ifname, ctx->conf->ifname, IFNAMSIZ-1);
+
+ pr_debug(ctx, "initializing tun device...");
+
+ if ((ctx->tunfd = open(ifname, O_RDWR|O_CLOEXEC|O_NONBLOCK)) < 0)
+ exit_errno(ctx, "could not open tun device file");
+
+ ctx->ifname = strndup(ctx->conf->ifname, IFNAMSIZ-1);
+
+ switch (ctx->conf->mode) {
+ case MODE_TAP:
+ setup_tap(ctx);
+ break;
+
+ case MODE_TUN:
+ setup_tun(ctx);
+ break;
+
+ default:
+ exit_bug(ctx, "invalid mode");
+ }
+
+ pr_debug(ctx, "tun device initialized.");
+}
+
+#endif
+
#else
#error unknown tun/tap implementation