Version bump to 5.8.2dr1
[strongswan.git] / src / libstrongswan / networking / tun_device.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * HSR Hochschule fuer Technik Rapperswil
6 * Copyright (C) 2012 Martin Willi
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "tun_device.h"
20
21 #include <utils/debug.h>
22 #include <threading/thread.h>
23
24 #if defined(__APPLE__)
25 #include "TargetConditionals.h"
26 #if !TARGET_OS_OSX
27 #define TUN_DEVICE_NOT_SUPPORTED
28 #endif
29 #elif !defined(__linux__) && !defined(HAVE_NET_IF_TUN_H)
30 #define TUN_DEVICE_NOT_SUPPORTED
31 #endif
32
33 #ifdef TUN_DEVICE_NOT_SUPPORTED
34
35 tun_device_t *tun_device_create(const char *name_tmpl)
36 {
37 DBG1(DBG_LIB, "TUN devices are not supported");
38 return NULL;
39 }
40
41 #else /* TUN devices supported */
42
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <netinet/in.h>
46 #include <string.h>
47 #include <sys/ioctl.h>
48 #include <sys/types.h>
49 #include <sys/socket.h>
50 #include <sys/stat.h>
51 #include <unistd.h>
52 #include <net/if.h>
53
54 #ifdef __APPLE__
55 #include <net/if_utun.h>
56 #include <netinet/in_var.h>
57 #include <sys/kern_control.h>
58 #elif defined(__linux__)
59 #include <linux/types.h>
60 #include <linux/if_tun.h>
61 #elif __FreeBSD__ >= 10
62 #include <net/if_tun.h>
63 #include <net/if_var.h>
64 #include <netinet/in_var.h>
65 #else
66 #include <net/if_tun.h>
67 #endif
68
69 #define TUN_DEFAULT_MTU 1500
70
71 typedef struct private_tun_device_t private_tun_device_t;
72
73 struct private_tun_device_t {
74
75 /**
76 * Public interface
77 */
78 tun_device_t public;
79
80 /**
81 * The TUN device's file descriptor
82 */
83 int tunfd;
84
85 /**
86 * Name of the TUN device
87 */
88 char if_name[IFNAMSIZ];
89
90 /**
91 * Socket used for ioctl() to set interface addr, ...
92 */
93 int sock;
94
95 /**
96 * The current MTU
97 */
98 int mtu;
99
100 /**
101 * Associated address
102 */
103 host_t *address;
104
105 /**
106 * Netmask for address
107 */
108 uint8_t netmask;
109 };
110
111 /**
112 * FreeBSD 10 deprecated the SIOCSIFADDR etc. commands.
113 */
114 #if __FreeBSD__ >= 10
115
116 static bool set_address_and_mask(struct in_aliasreq *ifra, host_t *addr,
117 uint8_t netmask)
118 {
119 host_t *mask;
120
121 memcpy(&ifra->ifra_addr, addr->get_sockaddr(addr),
122 *addr->get_sockaddr_len(addr));
123 /* set the same address as destination address */
124 memcpy(&ifra->ifra_dstaddr, addr->get_sockaddr(addr),
125 *addr->get_sockaddr_len(addr));
126
127 mask = host_create_netmask(addr->get_family(addr), netmask);
128 if (!mask)
129 {
130 DBG1(DBG_LIB, "invalid netmask: %d", netmask);
131 return FALSE;
132 }
133 memcpy(&ifra->ifra_mask, mask->get_sockaddr(mask),
134 *mask->get_sockaddr_len(mask));
135 mask->destroy(mask);
136 return TRUE;
137 }
138
139 /**
140 * Set the address using the more flexible SIOCAIFADDR/SIOCDIFADDR commands
141 * on FreeBSD 10 an newer.
142 */
143 static bool set_address_impl(private_tun_device_t *this, host_t *addr,
144 uint8_t netmask)
145 {
146 struct in_aliasreq ifra;
147
148 memset(&ifra, 0, sizeof(ifra));
149 strncpy(ifra.ifra_name, this->if_name, IFNAMSIZ);
150
151 if (this->address)
152 { /* remove the existing address first */
153 if (!set_address_and_mask(&ifra, this->address, this->netmask))
154 {
155 return FALSE;
156 }
157 if (ioctl(this->sock, SIOCDIFADDR, &ifra) < 0)
158 {
159 DBG1(DBG_LIB, "failed to remove existing address on %s: %s",
160 this->if_name, strerror(errno));
161 return FALSE;
162 }
163 }
164 if (!set_address_and_mask(&ifra, addr, netmask))
165 {
166 return FALSE;
167 }
168 if (ioctl(this->sock, SIOCAIFADDR, &ifra) < 0)
169 {
170 DBG1(DBG_LIB, "failed to add address on %s: %s",
171 this->if_name, strerror(errno));
172 return FALSE;
173 }
174 return TRUE;
175 }
176
177 #else /* __FreeBSD__ */
178
179 /**
180 * Set the address using the classic SIOCSIFADDR etc. commands on other systems.
181 */
182 static bool set_address_impl(private_tun_device_t *this, host_t *addr,
183 uint8_t netmask)
184 {
185 struct ifreq ifr;
186 host_t *mask;
187
188 memset(&ifr, 0, sizeof(ifr));
189 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
190 memcpy(&ifr.ifr_addr, addr->get_sockaddr(addr),
191 *addr->get_sockaddr_len(addr));
192
193 if (ioctl(this->sock, SIOCSIFADDR, &ifr) < 0)
194 {
195 DBG1(DBG_LIB, "failed to set address on %s: %s",
196 this->if_name, strerror(errno));
197 return FALSE;
198 }
199 #ifdef __APPLE__
200 if (ioctl(this->sock, SIOCSIFDSTADDR, &ifr) < 0)
201 {
202 DBG1(DBG_LIB, "failed to set dest address on %s: %s",
203 this->if_name, strerror(errno));
204 return FALSE;
205 }
206 #endif /* __APPLE__ */
207
208 mask = host_create_netmask(addr->get_family(addr), netmask);
209 if (!mask)
210 {
211 DBG1(DBG_LIB, "invalid netmask: %d", netmask);
212 return FALSE;
213 }
214 memcpy(&ifr.ifr_addr, mask->get_sockaddr(mask),
215 *mask->get_sockaddr_len(mask));
216 mask->destroy(mask);
217
218 if (ioctl(this->sock, SIOCSIFNETMASK, &ifr) < 0)
219 {
220 DBG1(DBG_LIB, "failed to set netmask on %s: %s",
221 this->if_name, strerror(errno));
222 return FALSE;
223 }
224 return TRUE;
225 }
226
227 #endif /* __FreeBSD__ */
228
229 METHOD(tun_device_t, set_address, bool,
230 private_tun_device_t *this, host_t *addr, uint8_t netmask)
231 {
232 if (!set_address_impl(this, addr, netmask))
233 {
234 return FALSE;
235 }
236 DESTROY_IF(this->address);
237 this->address = addr->clone(addr);
238 this->netmask = netmask;
239 return TRUE;
240 }
241
242 METHOD(tun_device_t, get_address, host_t*,
243 private_tun_device_t *this, uint8_t *netmask)
244 {
245 if (netmask && this->address)
246 {
247 *netmask = this->netmask;
248 }
249 return this->address;
250 }
251
252 METHOD(tun_device_t, up, bool,
253 private_tun_device_t *this)
254 {
255 struct ifreq ifr;
256
257 memset(&ifr, 0, sizeof(ifr));
258 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
259
260 if (ioctl(this->sock, SIOCGIFFLAGS, &ifr) < 0)
261 {
262 DBG1(DBG_LIB, "failed to get interface flags for %s: %s", this->if_name,
263 strerror(errno));
264 return FALSE;
265 }
266
267 ifr.ifr_flags |= IFF_RUNNING | IFF_UP;
268
269 if (ioctl(this->sock, SIOCSIFFLAGS, &ifr) < 0)
270 {
271 DBG1(DBG_LIB, "failed to set interface flags on %s: %s", this->if_name,
272 strerror(errno));
273 return FALSE;
274 }
275 return TRUE;
276 }
277
278 METHOD(tun_device_t, set_mtu, bool,
279 private_tun_device_t *this, int mtu)
280 {
281 struct ifreq ifr;
282
283 memset(&ifr, 0, sizeof(ifr));
284 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
285 ifr.ifr_mtu = mtu;
286
287 if (ioctl(this->sock, SIOCSIFMTU, &ifr) < 0)
288 {
289 DBG1(DBG_LIB, "failed to set MTU on %s: %s", this->if_name,
290 strerror(errno));
291 return FALSE;
292 }
293 this->mtu = mtu;
294 return TRUE;
295 }
296
297 METHOD(tun_device_t, get_mtu, int,
298 private_tun_device_t *this)
299 {
300 struct ifreq ifr;
301
302 if (this->mtu > 0)
303 {
304 return this->mtu;
305 }
306
307 memset(&ifr, 0, sizeof(ifr));
308 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
309 this->mtu = TUN_DEFAULT_MTU;
310
311 if (ioctl(this->sock, SIOCGIFMTU, &ifr) == 0)
312 {
313 this->mtu = ifr.ifr_mtu;
314 }
315 return this->mtu;
316 }
317
318 METHOD(tun_device_t, get_name, char*,
319 private_tun_device_t *this)
320 {
321 return this->if_name;
322 }
323
324 METHOD(tun_device_t, get_fd, int,
325 private_tun_device_t *this)
326 {
327 return this->tunfd;
328 }
329
330 METHOD(tun_device_t, write_packet, bool,
331 private_tun_device_t *this, chunk_t packet)
332 {
333 ssize_t s;
334
335 #ifdef __APPLE__
336 /* UTUN's expect the packets to be prepended by a 32-bit protocol number
337 * instead of parsing the packet again, we assume IPv4 for now */
338 uint32_t proto = htonl(AF_INET);
339 packet = chunk_cata("cc", chunk_from_thing(proto), packet);
340 #endif
341 s = write(this->tunfd, packet.ptr, packet.len);
342 if (s < 0)
343 {
344 DBG1(DBG_LIB, "failed to write packet to TUN device %s: %s",
345 this->if_name, strerror(errno));
346 return FALSE;
347 }
348 else if (s != packet.len)
349 {
350 return FALSE;
351 }
352 return TRUE;
353 }
354
355 METHOD(tun_device_t, read_packet, bool,
356 private_tun_device_t *this, chunk_t *packet)
357 {
358 chunk_t data;
359 ssize_t len;
360 bool old;
361
362 data = chunk_alloca(get_mtu(this));
363
364 old = thread_cancelability(TRUE);
365 len = read(this->tunfd, data.ptr, data.len);
366 thread_cancelability(old);
367 if (len < 0)
368 {
369 DBG1(DBG_LIB, "reading from TUN device %s failed: %s", this->if_name,
370 strerror(errno));
371 return FALSE;
372 }
373 data.len = len;
374 #ifdef __APPLE__
375 /* UTUN's prepend packets with a 32-bit protocol number */
376 data = chunk_skip(data, sizeof(uint32_t));
377 #endif
378 *packet = chunk_clone(data);
379 return TRUE;
380 }
381
382 METHOD(tun_device_t, destroy, void,
383 private_tun_device_t *this)
384 {
385 if (this->tunfd > 0)
386 {
387 close(this->tunfd);
388 #ifdef __FreeBSD__
389 /* tun(4) says the following: "These network interfaces persist until
390 * the if_tun.ko module is unloaded, or until removed with the
391 * ifconfig(8) command." So simply closing the FD is not enough. */
392 struct ifreq ifr;
393
394 memset(&ifr, 0, sizeof(ifr));
395 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
396 if (ioctl(this->sock, SIOCIFDESTROY, &ifr) < 0)
397 {
398 DBG1(DBG_LIB, "failed to destroy %s: %s", this->if_name,
399 strerror(errno));
400 }
401 #endif /* __FreeBSD__ */
402 }
403 if (this->sock > 0)
404 {
405 close(this->sock);
406 }
407 DESTROY_IF(this->address);
408 free(this);
409 }
410
411 /**
412 * Initialize the tun device
413 */
414 static bool init_tun(private_tun_device_t *this, const char *name_tmpl)
415 {
416 #ifdef __APPLE__
417
418 struct ctl_info info;
419 struct sockaddr_ctl addr;
420 socklen_t size = IFNAMSIZ;
421
422 memset(&info, 0, sizeof(info));
423 memset(&addr, 0, sizeof(addr));
424
425 this->tunfd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
426 if (this->tunfd < 0)
427 {
428 DBG1(DBG_LIB, "failed to open tundevice PF_SYSTEM socket: %s",
429 strerror(errno));
430 return FALSE;
431 }
432
433 /* get a control identifier for the utun kernel extension */
434 strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
435 if (ioctl(this->tunfd, CTLIOCGINFO, &info) < 0)
436 {
437 DBG1(DBG_LIB, "failed to ioctl tundevice: %s", strerror(errno));
438 close(this->tunfd);
439 return FALSE;
440 }
441
442 addr.sc_id = info.ctl_id;
443 addr.sc_len = sizeof(addr);
444 addr.sc_family = AF_SYSTEM;
445 addr.ss_sysaddr = AF_SYS_CONTROL;
446 /* allocate identifier dynamically */
447 addr.sc_unit = 0;
448
449 if (connect(this->tunfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
450 {
451 DBG1(DBG_LIB, "failed to connect tundevice: %s", strerror(errno));
452 close(this->tunfd);
453 return FALSE;
454 }
455 if (getsockopt(this->tunfd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME,
456 this->if_name, &size) < 0)
457 {
458 DBG1(DBG_LIB, "getting tundevice name failed: %s", strerror(errno));
459 close(this->tunfd);
460 return FALSE;
461 }
462 return TRUE;
463
464 #elif defined(IFF_TUN)
465
466 struct ifreq ifr;
467
468 strncpy(this->if_name, name_tmpl ?: "tun%d", IFNAMSIZ);
469 this->if_name[IFNAMSIZ-1] = '\0';
470
471 this->tunfd = open("/dev/net/tun", O_RDWR);
472 if (this->tunfd < 0)
473 {
474 DBG1(DBG_LIB, "failed to open /dev/net/tun: %s", strerror(errno));
475 return FALSE;
476 }
477
478 memset(&ifr, 0, sizeof(ifr));
479
480 /* TUN device, no packet info */
481 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
482
483 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
484 if (ioctl(this->tunfd, TUNSETIFF, (void*)&ifr) < 0)
485 {
486 DBG1(DBG_LIB, "failed to configure TUN device: %s", strerror(errno));
487 close(this->tunfd);
488 return FALSE;
489 }
490 strncpy(this->if_name, ifr.ifr_name, IFNAMSIZ);
491 return TRUE;
492
493 #elif defined(__FreeBSD__)
494
495 if (name_tmpl)
496 {
497 DBG1(DBG_LIB, "arbitrary naming of TUN devices is not supported");
498 }
499
500 this->tunfd = open("/dev/tun", O_RDWR);
501 if (this->tunfd < 0)
502 {
503 DBG1(DBG_LIB, "failed to open /dev/tun: %s", strerror(errno));
504 return FALSE;
505 }
506 fdevname_r(this->tunfd, this->if_name, IFNAMSIZ);
507 return TRUE;
508
509 #else /* !__FreeBSD__ */
510
511 /* this might work on Linux with older TUN driver versions (no IFF_TUN) */
512 char devname[IFNAMSIZ];
513 /* the same process is allowed to open a device again, but that's not what
514 * we want (unless we previously closed a device, which we don't know at
515 * this point). therefore, this counter is static so we don't accidentally
516 * open a device twice */
517 static int i = -1;
518
519 if (name_tmpl)
520 {
521 DBG1(DBG_LIB, "arbitrary naming of TUN devices is not supported");
522 }
523
524 for (; ++i < 256; )
525 {
526 snprintf(devname, IFNAMSIZ, "/dev/tun%d", i);
527 this->tunfd = open(devname, O_RDWR);
528 if (this->tunfd > 0)
529 { /* for ioctl(2) calls only the interface name is used */
530 snprintf(this->if_name, IFNAMSIZ, "tun%d", i);
531 break;
532 }
533 DBG1(DBG_LIB, "failed to open %s: %s", this->if_name, strerror(errno));
534 }
535 return this->tunfd > 0;
536
537 #endif /* !__APPLE__ */
538 }
539
540 /*
541 * Described in header
542 */
543 tun_device_t *tun_device_create(const char *name_tmpl)
544 {
545 private_tun_device_t *this;
546
547 INIT(this,
548 .public = {
549 .read_packet = _read_packet,
550 .write_packet = _write_packet,
551 .get_mtu = _get_mtu,
552 .set_mtu = _set_mtu,
553 .get_name = _get_name,
554 .get_fd = _get_fd,
555 .set_address = _set_address,
556 .get_address = _get_address,
557 .up = _up,
558 .destroy = _destroy,
559 },
560 .tunfd = -1,
561 .sock = -1,
562 );
563
564 if (!init_tun(this, name_tmpl))
565 {
566 free(this);
567 return NULL;
568 }
569 DBG1(DBG_LIB, "created TUN device: %s", this->if_name);
570
571 this->sock = socket(AF_INET, SOCK_DGRAM, 0);
572 if (this->sock < 0)
573 {
574 DBG1(DBG_LIB, "failed to open socket to configure TUN device");
575 destroy(this);
576 return NULL;
577 }
578 return &this->public;
579 }
580
581 #endif /* TUN devices supported */