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