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