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