2 device.c -- Interaction BSD tun/tap device
3 Copyright (C) 2001-2005 Ivo Timmermans,
4 2001-2017 Guus Sliepen <guus@tinc-vpn.org>
5 2009 Grzegorz Dymarek <gregd72002@googlemail.com>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "../system.h"
25 #include "../device.h"
26 #include "../logger.h"
31 #include "../xalloc.h"
34 #include "bsd/tunemu.h"
37 #ifdef HAVE_NET_IF_UTUN_H
38 #include <sys/sys_domain.h>
39 #include <sys/kern_control.h>
40 #include <net/if_utun.h>
43 #if defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
44 #define DEFAULT_TUN_DEVICE "/dev/tun" // Use the autoclone device
45 #define DEFAULT_TAP_DEVICE "/dev/tap"
47 #define DEFAULT_TUN_DEVICE "/dev/tun0"
48 #define DEFAULT_TAP_DEVICE "/dev/tap0"
51 typedef enum device_type {
53 DEVICE_TYPE_TUNIFHEAD,
64 static const char *device_info = "OS X utun device";
65 #if defined(ENABLE_TUNEMU)
66 static device_type_t device_type = DEVICE_TYPE_TUNEMU;
67 #elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
68 static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD;
70 static device_type_t device_type = DEVICE_TYPE_TUN;
73 #ifdef HAVE_NET_IF_UTUN_H
74 static bool setup_utun(void) {
75 device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
78 logger(DEBUG_ALWAYS, LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno));
82 struct ctl_info info = {};
84 strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name));
86 if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) {
87 logger(DEBUG_ALWAYS, LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno));
92 char *p = strstr(device, "utun"), *e = NULL;
95 unit = strtol(p + 4, &e, 10);
102 struct sockaddr_ctl sc = {
103 .sc_id = info.ctl_id,
104 .sc_len = sizeof(sc),
105 .sc_family = AF_SYSTEM,
106 .ss_sysaddr = AF_SYS_CONTROL,
110 if(connect(device_fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) {
111 logger(DEBUG_ALWAYS, LOG_ERR, "Could not connect utun socket: %s\n", strerror(errno));
116 socklen_t len = sizeof(name);
118 if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) {
119 iface = xstrdup(device);
121 iface = xstrdup(name);
124 logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
130 static bool setup_device(void) {
131 get_config_string(lookup_config(config_tree, "Device"), &device);
133 // Find out if it's supposed to be a tun or a tap device
137 if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
138 if(!strcasecmp(type, "tun"))
142 else if(!strcasecmp(type, "tunemu")) {
143 device_type = DEVICE_TYPE_TUNEMU;
147 #ifdef HAVE_NET_IF_UTUN_H
148 else if(!strcasecmp(type, "utun")) {
149 device_type = DEVICE_TYPE_UTUN;
153 else if(!strcasecmp(type, "tunnohead")) {
154 device_type = DEVICE_TYPE_TUN;
155 } else if(!strcasecmp(type, "tunifhead")) {
156 device_type = DEVICE_TYPE_TUNIFHEAD;
157 } else if(!strcasecmp(type, "tap")) {
158 device_type = DEVICE_TYPE_TAP;
160 logger(DEBUG_ALWAYS, LOG_ERR, "Unknown device type %s!", type);
164 #ifdef HAVE_NET_IF_UTUN_H
166 if(device && (strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0)) {
167 device_type = DEVICE_TYPE_UTUN;
170 if((device && strstr(device, "tap")) || routing_mode != RMODE_ROUTER) {
171 device_type = DEVICE_TYPE_TAP;
175 if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) {
176 logger(DEBUG_ALWAYS, LOG_ERR, "Only tap devices support switch mode!");
180 // Find out which device file to open
183 if(device_type == DEVICE_TYPE_TAP) {
184 device = xstrdup(DEFAULT_TAP_DEVICE);
186 device = xstrdup(DEFAULT_TUN_DEVICE);
192 switch(device_type) {
195 case DEVICE_TYPE_TUNEMU: {
196 char dynamic_name[256] = "";
197 device_fd = tunemu_open(dynamic_name);
201 #ifdef HAVE_NET_IF_UTUN_H
203 case DEVICE_TYPE_UTUN:
208 device_fd = open(device, O_RDWR | O_NONBLOCK);
212 logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", device, strerror(errno));
217 fcntl(device_fd, F_SETFD, FD_CLOEXEC);
220 // Guess what the corresponding interface is called
222 char *realname = NULL;
224 #if defined(HAVE_FDEVNAME)
225 realname = fdevname(device_fd);
226 #elif defined(HAVE_DEVNAME)
229 if(!fstat(device_fd, &buf)) {
230 realname = devname(buf.st_rdev, S_IFCHR);
239 if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) {
240 iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname);
241 } else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) {
242 logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly.");
245 // Configure the device as best as we can
247 switch(device_type) {
249 device_type = DEVICE_TYPE_TUN;
251 case DEVICE_TYPE_TUN:
256 if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof(zero)) == -1) {
257 logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
263 #if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
265 const int mode = IFF_BROADCAST | IFF_MULTICAST;
266 ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
270 device_info = "Generic BSD tun device";
273 case DEVICE_TYPE_TUNIFHEAD:
278 if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof(one)) == -1) {
279 logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
285 #if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
287 const int mode = IFF_BROADCAST | IFF_MULTICAST;
288 ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
292 device_info = "Generic BSD tun device";
295 case DEVICE_TYPE_TAP:
296 if(routing_mode == RMODE_ROUTER) {
297 overwrite_mac = true;
300 device_info = "Generic BSD tap device";
305 if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) {
307 iface = xstrdup(ifr.ifr_name);
315 case DEVICE_TYPE_TUNEMU:
316 device_info = "BSD tunemu device";
324 ioctl(device_fd, SIOCGIFADDR, mymac.x);
329 logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
334 static void close_device(void) {
335 switch(device_type) {
338 case DEVICE_TYPE_TUNEMU:
339 tunemu_close(device_fd);
356 static bool read_packet(vpn_packet_t *packet) {
359 switch(device_type) {
360 case DEVICE_TYPE_TUN:
362 case DEVICE_TYPE_TUNEMU:
363 if(device_type == DEVICE_TYPE_TUNEMU) {
364 inlen = tunemu_read(device_fd, DATA(packet) + 14, MTU - 14);
367 inlen = read(device_fd, DATA(packet) + 14, MTU - 14);
370 logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
371 device, strerror(errno));
375 switch(DATA(packet)[14] >> 4) {
377 DATA(packet)[12] = 0x08;
378 DATA(packet)[13] = 0x00;
382 DATA(packet)[12] = 0x86;
383 DATA(packet)[13] = 0xDD;
387 logger(DEBUG_TRAFFIC, LOG_ERR,
388 "Unknown IP version %d while reading packet from %s %s",
389 DATA(packet)[14] >> 4, device_info, device);
393 memset(DATA(packet), 0, 12);
394 packet->len = inlen + 14;
397 case DEVICE_TYPE_UTUN:
398 case DEVICE_TYPE_TUNIFHEAD: {
399 if((inlen = read(device_fd, DATA(packet) + 10, MTU - 10)) <= 0) {
400 logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
401 device, strerror(errno));
405 switch(DATA(packet)[14] >> 4) {
407 DATA(packet)[12] = 0x08;
408 DATA(packet)[13] = 0x00;
412 DATA(packet)[12] = 0x86;
413 DATA(packet)[13] = 0xDD;
417 logger(DEBUG_TRAFFIC, LOG_ERR,
418 "Unknown IP version %d while reading packet from %s %s",
419 DATA(packet)[14] >> 4, device_info, device);
423 memset(DATA(packet), 0, 12);
424 packet->len = inlen + 10;
428 case DEVICE_TYPE_TAP:
429 if((inlen = read(device_fd, DATA(packet), MTU)) <= 0) {
430 logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
431 device, strerror(errno));
442 logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s",
443 packet->len, device_info);
448 static bool write_packet(vpn_packet_t *packet) {
449 logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
450 packet->len, device_info);
452 switch(device_type) {
453 case DEVICE_TYPE_TUN:
454 if(write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
455 logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
456 device, strerror(errno));
462 case DEVICE_TYPE_UTUN:
463 case DEVICE_TYPE_TUNIFHEAD: {
464 int af = (DATA(packet)[12] << 8) + DATA(packet)[13];
469 type = htonl(AF_INET);
473 type = htonl(AF_INET6);
477 logger(DEBUG_TRAFFIC, LOG_ERR,
478 "Unknown address family %x while writing packet to %s %s",
479 af, device_info, device);
483 memcpy(DATA(packet) + 10, &type, sizeof(type));
485 if(write(device_fd, DATA(packet) + 10, packet->len - 10) < 0) {
486 logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
494 case DEVICE_TYPE_TAP:
495 if(write(device_fd, DATA(packet), packet->len) < 0) {
496 logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
497 device, strerror(errno));
505 case DEVICE_TYPE_TUNEMU:
506 if(tunemu_write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
507 logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
508 device, strerror(errno));
522 const devops_t os_devops = {
523 .setup = setup_device,
524 .close = close_device,
526 .write = write_packet,