Const correctness.
[tinc] / src / bsd / device.c
1 /*
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>
6
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.
11
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.
16
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.
20 */
21
22 #include "../system.h"
23
24 #include "../conf.h"
25 #include "../device.h"
26 #include "../logger.h"
27 #include "../names.h"
28 #include "../net.h"
29 #include "../route.h"
30 #include "../utils.h"
31 #include "../xalloc.h"
32
33 #ifdef ENABLE_TUNEMU
34 #include "bsd/tunemu.h"
35 #endif
36
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>
41 #endif
42
43 #define DEFAULT_TUN_DEVICE "/dev/tun0"
44 #define DEFAULT_TAP_DEVICE "/dev/tap0"
45
46 typedef enum device_type {
47         DEVICE_TYPE_TUN,
48         DEVICE_TYPE_TUNIFHEAD,
49         DEVICE_TYPE_TAP,
50 #ifdef ENABLE_TUNEMU
51         DEVICE_TYPE_TUNEMU,
52 #endif
53         DEVICE_TYPE_UTUN,
54 } device_type_t;
55
56 int device_fd = -1;
57 char *device = NULL;
58 char *iface = NULL;
59 static const char *device_info = "OS X utun device";
60 #if defined(ENABLE_TUNEMU)
61 static device_type_t device_type = DEVICE_TYPE_TUNEMU;
62 #elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
63 static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD;
64 #else
65 static device_type_t device_type = DEVICE_TYPE_TUN;
66 #endif
67
68 #ifdef HAVE_NET_IF_UTUN_H
69 static bool setup_utun(void) {
70         device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
71
72         if(device_fd == -1) {
73                 logger(DEBUG_ALWAYS, LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno));
74                 return false;
75         }
76
77         struct ctl_info info = {};
78
79         strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name));
80
81         if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) {
82                 logger(DEBUG_ALWAYS, LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno));
83                 return false;
84         }
85
86         int unit = -1;
87         char *p = strstr(device, "utun"), *e = NULL;
88
89         if(p) {
90                 unit = strtol(p + 4, &e, 10);
91
92                 if(!e) {
93                         unit = -1;
94                 }
95         }
96
97         struct sockaddr_ctl sc = {
98                 .sc_id = info.ctl_id,
99                 .sc_len = sizeof(sc),
100                 .sc_family = AF_SYSTEM,
101                 .ss_sysaddr = AF_SYS_CONTROL,
102                 .sc_unit = unit + 1,
103         };
104
105         if(connect(device_fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) {
106                 logger(DEBUG_ALWAYS, LOG_ERR, "Could not connect utun socket: %s\n", strerror(errno));
107                 return false;
108         }
109
110         char name[64] = "";
111         socklen_t len = sizeof(name);
112
113         if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) {
114                 iface = xstrdup(device);
115         } else {
116                 iface = xstrdup(name);
117         }
118
119         logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
120
121         return true;
122 }
123 #endif
124
125 static bool setup_device(void) {
126         get_config_string(lookup_config(config_tree, "Device"), &device);
127
128         // Find out if it's supposed to be a tun or a tap device
129
130         char *type;
131
132         if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
133                 if(!strcasecmp(type, "tun"))
134                         /* use default */;
135
136 #ifdef ENABLE_TUNEMU
137                 else if(!strcasecmp(type, "tunemu")) {
138                         device_type = DEVICE_TYPE_TUNEMU;
139                 }
140
141 #endif
142 #ifdef HAVE_NET_IF_UTUN_H
143                 else if(!strcasecmp(type, "utun")) {
144                         device_type = DEVICE_TYPE_UTUN;
145                 }
146
147 #endif
148                 else if(!strcasecmp(type, "tunnohead")) {
149                         device_type = DEVICE_TYPE_TUN;
150                 } else if(!strcasecmp(type, "tunifhead")) {
151                         device_type = DEVICE_TYPE_TUNIFHEAD;
152                 } else if(!strcasecmp(type, "tap")) {
153                         device_type = DEVICE_TYPE_TAP;
154                 } else {
155                         logger(DEBUG_ALWAYS, LOG_ERR, "Unknown device type %s!", type);
156                         return false;
157                 }
158         } else {
159 #ifdef HAVE_NET_IF_UTUN_H
160
161                 if(device && (strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0)) {
162                         device_type = DEVICE_TYPE_UTUN;
163                 } else
164 #endif
165                         if((device && strstr(device, "tap")) || routing_mode != RMODE_ROUTER) {
166                                 device_type = DEVICE_TYPE_TAP;
167                         }
168         }
169
170         if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) {
171                 logger(DEBUG_ALWAYS, LOG_ERR, "Only tap devices support switch mode!");
172                 return false;
173         }
174
175         // Find out which device file to open
176
177         if(!device) {
178                 if(device_type == DEVICE_TYPE_TAP) {
179                         device = xstrdup(DEFAULT_TAP_DEVICE);
180                 } else {
181                         device = xstrdup(DEFAULT_TUN_DEVICE);
182                 }
183         }
184
185         // Open the device
186
187         switch(device_type) {
188 #ifdef ENABLE_TUNEMU
189
190         case DEVICE_TYPE_TUNEMU: {
191                 char dynamic_name[256] = "";
192                 device_fd = tunemu_open(dynamic_name);
193         }
194         break;
195 #endif
196 #ifdef HAVE_NET_IF_UTUN_H
197
198         case DEVICE_TYPE_UTUN:
199                 return setup_utun();
200 #endif
201
202         default:
203                 device_fd = open(device, O_RDWR | O_NONBLOCK);
204         }
205
206         if(device_fd < 0) {
207                 logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", device, strerror(errno));
208                 return false;
209         }
210
211 #ifdef FD_CLOEXEC
212         fcntl(device_fd, F_SETFD, FD_CLOEXEC);
213 #endif
214
215         // Guess what the corresponding interface is called
216
217         char *realname = NULL;
218
219 #if defined(HAVE_FDEVNAME)
220         realname = fdevname(device_fd);
221 #elif defined(HAVE_DEVNAME)
222         struct stat buf;
223
224         if(!fstat(device_fd, &buf)) {
225                 realname = devname(buf.st_rdev, S_IFCHR);
226         }
227
228 #endif
229
230         if(!realname) {
231                 realname = device;
232         }
233
234         if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) {
235                 iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname);
236         } else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) {
237                 logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly.");
238         }
239
240         // Configure the device as best as we can
241
242         switch(device_type) {
243         default:
244                 device_type = DEVICE_TYPE_TUN;
245
246         case DEVICE_TYPE_TUN:
247 #ifdef TUNSIFHEAD
248                 {
249                         const int zero = 0;
250
251                         if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof(zero)) == -1) {
252                                 logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
253                                 return false;
254                         }
255                 }
256
257 #endif
258 #if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
259                 {
260                         const int mode = IFF_BROADCAST | IFF_MULTICAST;
261                         ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
262                 }
263 #endif
264
265                 device_info = "Generic BSD tun device";
266                 break;
267
268         case DEVICE_TYPE_TUNIFHEAD:
269 #ifdef TUNSIFHEAD
270                 {
271                         const int one = 1;
272
273                         if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof(one)) == -1) {
274                                 logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
275                                 return false;
276                         }
277                 }
278
279 #endif
280 #if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
281                 {
282                         const int mode = IFF_BROADCAST | IFF_MULTICAST;
283                         ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
284                 }
285 #endif
286
287                 device_info = "Generic BSD tun device";
288                 break;
289
290         case DEVICE_TYPE_TAP:
291                 if(routing_mode == RMODE_ROUTER) {
292                         overwrite_mac = true;
293                 }
294
295                 device_info = "Generic BSD tap device";
296 #ifdef TAPGIFNAME
297                 {
298                         struct ifreq ifr;
299
300                         if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) {
301                                 if(iface) {
302                                         free(iface);
303                                 }
304
305                                 iface = xstrdup(ifr.ifr_name);
306                         }
307                 }
308
309 #endif
310                 break;
311 #ifdef ENABLE_TUNEMU
312
313         case DEVICE_TYPE_TUNEMU:
314                 device_info = "BSD tunemu device";
315                 break;
316 #endif
317         }
318
319 #ifdef SIOCGIFADDR
320
321         if(overwrite_mac) {
322                 ioctl(device_fd, SIOCGIFADDR, mymac.x);
323         }
324
325 #endif
326
327         logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
328
329         return true;
330 }
331
332 static void close_device(void) {
333         switch(device_type) {
334 #ifdef ENABLE_TUNEMU
335
336         case DEVICE_TYPE_TUNEMU:
337                 tunemu_close(device_fd);
338                 break;
339 #endif
340
341         default:
342                 close(device_fd);
343         }
344
345         device_fd = -1;
346
347         free(device);
348         device = NULL;
349         free(iface);
350         iface = NULL;
351         device_info = NULL;
352 }
353
354 static bool read_packet(vpn_packet_t *packet) {
355         int inlen;
356
357         switch(device_type) {
358         case DEVICE_TYPE_TUN:
359 #ifdef ENABLE_TUNEMU
360         case DEVICE_TYPE_TUNEMU:
361                 if(device_type == DEVICE_TYPE_TUNEMU) {
362                         inlen = tunemu_read(device_fd, DATA(packet) + 14, MTU - 14);
363                 } else
364 #endif
365                         inlen = read(device_fd, DATA(packet) + 14, MTU - 14);
366
367                 if(inlen <= 0) {
368                         logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
369                                device, strerror(errno));
370                         return false;
371                 }
372
373                 switch(DATA(packet)[14] >> 4) {
374                 case 4:
375                         DATA(packet)[12] = 0x08;
376                         DATA(packet)[13] = 0x00;
377                         break;
378
379                 case 6:
380                         DATA(packet)[12] = 0x86;
381                         DATA(packet)[13] = 0xDD;
382                         break;
383
384                 default:
385                         logger(DEBUG_TRAFFIC, LOG_ERR,
386                                "Unknown IP version %d while reading packet from %s %s",
387                                DATA(packet)[14] >> 4, device_info, device);
388                         return false;
389                 }
390
391                 memset(DATA(packet), 0, 12);
392                 packet->len = inlen + 14;
393                 break;
394
395         case DEVICE_TYPE_UTUN:
396         case DEVICE_TYPE_TUNIFHEAD: {
397                 if((inlen = read(device_fd, DATA(packet) + 10, MTU - 10)) <= 0) {
398                         logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
399                                device, strerror(errno));
400                         return false;
401                 }
402
403                 switch(DATA(packet)[14] >> 4) {
404                 case 4:
405                         DATA(packet)[12] = 0x08;
406                         DATA(packet)[13] = 0x00;
407                         break;
408
409                 case 6:
410                         DATA(packet)[12] = 0x86;
411                         DATA(packet)[13] = 0xDD;
412                         break;
413
414                 default:
415                         logger(DEBUG_TRAFFIC, LOG_ERR,
416                                "Unknown IP version %d while reading packet from %s %s",
417                                DATA(packet)[14] >> 4, device_info, device);
418                         return false;
419                 }
420
421                 memset(DATA(packet), 0, 12);
422                 packet->len = inlen + 10;
423                 break;
424         }
425
426         case DEVICE_TYPE_TAP:
427                 if((inlen = read(device_fd, DATA(packet), MTU)) <= 0) {
428                         logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
429                                device, strerror(errno));
430                         return false;
431                 }
432
433                 packet->len = inlen;
434                 break;
435
436         default:
437                 return false;
438         }
439
440         logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s",
441                packet->len, device_info);
442
443         return true;
444 }
445
446 static bool write_packet(vpn_packet_t *packet) {
447         logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
448                packet->len, device_info);
449
450         switch(device_type) {
451         case DEVICE_TYPE_TUN:
452                 if(write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
453                         logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
454                                device, strerror(errno));
455                         return false;
456                 }
457
458                 break;
459
460         case DEVICE_TYPE_UTUN:
461         case DEVICE_TYPE_TUNIFHEAD: {
462                 int af = (DATA(packet)[12] << 8) + DATA(packet)[13];
463                 uint32_t type;
464
465                 switch(af) {
466                 case 0x0800:
467                         type = htonl(AF_INET);
468                         break;
469
470                 case 0x86DD:
471                         type = htonl(AF_INET6);
472                         break;
473
474                 default:
475                         logger(DEBUG_TRAFFIC, LOG_ERR,
476                                "Unknown address family %x while writing packet to %s %s",
477                                af, device_info, device);
478                         return false;
479                 }
480
481                 memcpy(DATA(packet) + 10, &type, sizeof(type));
482
483                 if(write(device_fd, DATA(packet) + 10, packet->len - 10) < 0) {
484                         logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
485                                strerror(errno));
486                         return false;
487                 }
488
489                 break;
490         }
491
492         case DEVICE_TYPE_TAP:
493                 if(write(device_fd, DATA(packet), packet->len) < 0) {
494                         logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
495                                device, strerror(errno));
496                         return false;
497                 }
498
499                 break;
500
501 #ifdef ENABLE_TUNEMU
502
503         case DEVICE_TYPE_TUNEMU:
504                 if(tunemu_write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
505                         logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
506                                device, strerror(errno));
507                         return false;
508                 }
509
510                 break;
511 #endif
512
513         default:
514                 return false;
515         }
516
517         return true;
518 }
519
520 const devops_t os_devops = {
521         .setup = setup_device,
522         .close = close_device,
523         .read = read_packet,
524         .write = write_packet,
525 };