tun-device: Remove the superfluous use of select() before read()
[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 bool old;
351
352 *packet = chunk_alloc(get_mtu(this));
353
354 thread_cleanup_push(free, packet->ptr);
355 old = thread_cancelability(TRUE);
356 len = read(this->tunfd, packet->ptr, packet->len);
357 thread_cancelability(old);
358 thread_cleanup_pop(FALSE);
359 if (len < 0)
360 {
361 DBG1(DBG_LIB, "reading from TUN device %s failed: %s", this->if_name,
362 strerror(errno));
363 free(packet->ptr);
364 return FALSE;
365 }
366 packet->len = len;
367 #ifdef __APPLE__
368 /* UTUN's prepend packets with a 32-bit protocol number */
369 packet->len -= sizeof(u_int32_t);
370 memmove(packet->ptr, packet->ptr + sizeof(u_int32_t), packet->len);
371 #endif
372 return TRUE;
373 }
374
375 METHOD(tun_device_t, destroy, void,
376 private_tun_device_t *this)
377 {
378 if (this->tunfd > 0)
379 {
380 close(this->tunfd);
381 #ifdef __FreeBSD__
382 /* tun(4) says the following: "These network interfaces persist until
383 * the if_tun.ko module is unloaded, or until removed with the
384 * ifconfig(8) command." So simply closing the FD is not enough. */
385 struct ifreq ifr;
386
387 memset(&ifr, 0, sizeof(ifr));
388 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
389 if (ioctl(this->sock, SIOCIFDESTROY, &ifr) < 0)
390 {
391 DBG1(DBG_LIB, "failed to destroy %s: %s", this->if_name,
392 strerror(errno));
393 }
394 #endif /* __FreeBSD__ */
395 }
396 if (this->sock > 0)
397 {
398 close(this->sock);
399 }
400 DESTROY_IF(this->address);
401 free(this);
402 }
403
404 /**
405 * Initialize the tun device
406 */
407 static bool init_tun(private_tun_device_t *this, const char *name_tmpl)
408 {
409 #ifdef __APPLE__
410
411 struct ctl_info info;
412 struct sockaddr_ctl addr;
413 socklen_t size = IFNAMSIZ;
414
415 memset(&info, 0, sizeof(info));
416 memset(&addr, 0, sizeof(addr));
417
418 this->tunfd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
419 if (this->tunfd < 0)
420 {
421 DBG1(DBG_LIB, "failed to open tundevice PF_SYSTEM socket: %s",
422 strerror(errno));
423 return FALSE;
424 }
425
426 /* get a control identifier for the utun kernel extension */
427 strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
428 if (ioctl(this->tunfd, CTLIOCGINFO, &info) < 0)
429 {
430 DBG1(DBG_LIB, "failed to ioctl tundevice: %s", strerror(errno));
431 close(this->tunfd);
432 return FALSE;
433 }
434
435 addr.sc_id = info.ctl_id;
436 addr.sc_len = sizeof(addr);
437 addr.sc_family = AF_SYSTEM;
438 addr.ss_sysaddr = AF_SYS_CONTROL;
439 /* allocate identifier dynamically */
440 addr.sc_unit = 0;
441
442 if (connect(this->tunfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
443 {
444 DBG1(DBG_LIB, "failed to connect tundevice: %s", strerror(errno));
445 close(this->tunfd);
446 return FALSE;
447 }
448 if (getsockopt(this->tunfd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME,
449 this->if_name, &size) < 0)
450 {
451 DBG1(DBG_LIB, "getting tundevice name failed: %s", strerror(errno));
452 close(this->tunfd);
453 return FALSE;
454 }
455 return TRUE;
456
457 #elif defined(IFF_TUN)
458
459 struct ifreq ifr;
460
461 strncpy(this->if_name, name_tmpl ?: "tun%d", IFNAMSIZ);
462 this->if_name[IFNAMSIZ-1] = '\0';
463
464 this->tunfd = open("/dev/net/tun", O_RDWR);
465 if (this->tunfd < 0)
466 {
467 DBG1(DBG_LIB, "failed to open /dev/net/tun: %s", strerror(errno));
468 return FALSE;
469 }
470
471 memset(&ifr, 0, sizeof(ifr));
472
473 /* TUN device, no packet info */
474 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
475
476 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
477 if (ioctl(this->tunfd, TUNSETIFF, (void*)&ifr) < 0)
478 {
479 DBG1(DBG_LIB, "failed to configure TUN device: %s", strerror(errno));
480 close(this->tunfd);
481 return FALSE;
482 }
483 strncpy(this->if_name, ifr.ifr_name, IFNAMSIZ);
484 return TRUE;
485
486 #else /* !IFF_TUN */
487
488 /* this works on FreeBSD and might also work on Linux with older TUN
489 * driver versions (no IFF_TUN) */
490 char devname[IFNAMSIZ];
491 /* the same process is allowed to open a device again, but that's not what
492 * we want (unless we previously closed a device, which we don't know at
493 * this point). therefore, this counter is static so we don't accidentally
494 * open a device twice */
495 static int i = -1;
496
497 if (name_tmpl)
498 {
499 DBG1(DBG_LIB, "arbitrary naming of TUN devices is not supported");
500 }
501
502 for (; ++i < 256; )
503 {
504 snprintf(devname, IFNAMSIZ, "/dev/tun%d", i);
505 this->tunfd = open(devname, O_RDWR);
506 if (this->tunfd > 0)
507 { /* for ioctl(2) calls only the interface name is used */
508 snprintf(this->if_name, IFNAMSIZ, "tun%d", i);
509 break;
510 }
511 DBG1(DBG_LIB, "failed to open %s: %s", this->if_name, strerror(errno));
512 }
513 return this->tunfd > 0;
514
515 #endif /* !__APPLE__ */
516 }
517
518 /*
519 * Described in header
520 */
521 tun_device_t *tun_device_create(const char *name_tmpl)
522 {
523 private_tun_device_t *this;
524
525 INIT(this,
526 .public = {
527 .read_packet = _read_packet,
528 .write_packet = _write_packet,
529 .get_mtu = _get_mtu,
530 .set_mtu = _set_mtu,
531 .get_name = _get_name,
532 .get_fd = _get_fd,
533 .set_address = _set_address,
534 .get_address = _get_address,
535 .up = _up,
536 .destroy = _destroy,
537 },
538 .tunfd = -1,
539 .sock = -1,
540 );
541
542 if (!init_tun(this, name_tmpl))
543 {
544 free(this);
545 return NULL;
546 }
547 DBG1(DBG_LIB, "created TUN device: %s", this->if_name);
548
549 this->sock = socket(AF_INET, SOCK_DGRAM, 0);
550 if (this->sock < 0)
551 {
552 DBG1(DBG_LIB, "failed to open socket to configure TUN device");
553 destroy(this);
554 return NULL;
555 }
556 return &this->public;
557 }
558
559 #endif /* TUN devices supported */