diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2013-08-07 18:39:52 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2013-08-07 18:39:52 +0200 |
commit | 86e480042887f18f0ac2a73a49da33b5625cf9b3 (patch) | |
tree | 054ed2d4e0f28887be0869aff3d2540b49cb4181 | |
parent | 1150b8a7bf3dbeaa766fccac946ce831e187c6b2 (diff) | |
download | fastd-86e480042887f18f0ac2a73a49da33b5625cf9b3.tar fastd-86e480042887f18f0ac2a73a49da33b5625cf9b3.zip |
Add FreeBSD implementation of fastd_tuntap_open()
-rw-r--r-- | src/tuntap.c | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/src/tuntap.c b/src/tuntap.c index 6d809c0..e94be05 100644 --- a/src/tuntap.c +++ b/src/tuntap.c @@ -30,8 +30,10 @@ #include <net/if.h> #include <sys/ioctl.h> -#include <linux/if_tun.h> +#if defined(__linux__) + +#include <linux/if_tun.h> void fastd_tuntap_open(fastd_context_t *ctx) { struct ifreq ifr = {}; @@ -82,6 +84,103 @@ 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 void get_tap_name(fastd_context_t *ctx) { + struct ifreq ifr = {}; + + if (ioctl(ctx->tunfd, TAPGIFNAME, &ifr) < 0) + exit_errno(ctx, "TAPGIFNAME ioctl failed"); + + free(ctx->ifname); + ctx->ifname = strndup(ifr.ifr_name, IFNAMSIZ-1); +} + +static void set_tap_mtu(fastd_context_t *ctx) { + struct tapinfo tapinfo; + + if (ioctl(ctx->tunfd, TAPGIFINFO, &tapinfo) < 0) + exit_errno(ctx, "TAPGIFINFO ioctl failed"); + + tapinfo.mtu = ctx->conf->mtu; + + if (ioctl(ctx->tunfd, TAPSIFINFO, &tapinfo) < 0) + exit_errno(ctx, "TAPSIFINFO ioctl failed"); +} + +static void set_tun_mtu(fastd_context_t *ctx) { + struct tuninfo tuninfo; + + if (ioctl(ctx->tunfd, TUNGIFINFO, &tuninfo) < 0) + exit_errno(ctx, "TUNGIFINFO ioctl failed"); + + tuninfo.mtu = ctx->conf->mtu; + + if (ioctl(ctx->tunfd, TUNSIFINFO, &tuninfo) < 0) + exit_errno(ctx, "TUNSIFINFO ioctl failed"); +} + +void fastd_tuntap_open(fastd_context_t *ctx) { + pr_debug(ctx, "initializing tun/tap device..."); + + char ifname[5+IFNAMSIZ] = "/dev/"; + if (ctx->conf->ifname) { + strncat(ifname, ctx->conf->ifname, IFNAMSIZ-1); + } + else { + switch (ctx->conf->mode) { + case MODE_TAP: + strncat(ifname, "tap", IFNAMSIZ-1); + break; + + case MODE_TUN: + strncat(ifname, "tun", IFNAMSIZ-1); + break; + + default: + exit_bug(ctx, "invalid mode"); + } + } + + if ((ctx->tunfd = open(ifname, O_RDWR|O_CLOEXEC|O_NONBLOCK)) < 0) + exit_errno(ctx, "could not open tun/tap device file"); + + if (!(ctx->ifname = fdevname_r(ctx->tunfd, malloc(IFNAMSIZ), IFNAMSIZ))) + exit_errno(ctx, "could not get tun/tap interface name"); + + 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"); + + get_tap_name(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"); + + set_tun_mtu(ctx); + break; + + default: + exit_bug(ctx, "invalid mode"); + } + + pr_debug(ctx, "tun/tap device initialized."); +} + +#else + +#error unknown tun/tap implementation + +#endif + + void fastd_tuntap_close(fastd_context_t *ctx) { if (close(ctx->tunfd)) pr_warn_errno(ctx, "closing tun/tap: close"); |