Annotation of embedaddon/strongswan/src/libstrongswan/networking/tun_device.c, revision 1.1.1.1
1.1 misho 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 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>