Added utility class to create TUN devices
[strongswan.git] / src / libstrongswan / utils / 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 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <netinet/in.h>
21 #include <string.h>
22 #include <sys/ioctl.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <linux/if.h>
28 #include <linux/if_tun.h>
29
30 #include "tun_device.h"
31
32 #include <library.h>
33 #include <debug.h>
34 #include <threading/thread.h>
35
36 #define TUN_DEFAULT_MTU 1500
37
38 typedef struct private_tun_device_t private_tun_device_t;
39
40 struct private_tun_device_t {
41
42 /**
43 * Public interface
44 */
45 tun_device_t public;
46
47 /**
48 * The TUN device's file descriptor
49 */
50 int tunfd;
51
52 /**
53 * Name of the TUN device
54 */
55 char if_name[IFNAMSIZ];
56
57 /**
58 * Socket used for ioctl() to set interface addr, ...
59 */
60 int sock;
61
62 /**
63 * The current MTU
64 */
65 int mtu;
66 };
67
68 /**
69 * Set the sockaddr_t from the given netmask
70 */
71 static void set_netmask(struct ifreq *ifr, int family, u_int8_t netmask)
72 {
73 int len, bytes, bits;
74 char *target;
75
76 switch (family)
77 {
78 case AF_INET:
79 {
80 struct sockaddr_in *addr = (struct sockaddr_in*)&ifr->ifr_addr;
81 addr->sin_family = AF_INET;
82 target = (char*)&addr->sin_addr;
83 len = 4;
84 break;
85 }
86 case AF_INET6:
87 {
88 struct sockaddr_in6 *addr = (struct sockaddr_in6*)&ifr->ifr_addr;
89 addr->sin6_family = AF_INET6;
90 target = (char*)&addr->sin6_addr;
91 len = 16;
92 break;
93 }
94 default:
95 return;
96 }
97
98 bytes = (netmask + 7) / 8;
99 bits = (bytes * 8) - netmask;
100
101 memset(target, 0xff, bytes);
102 memset(target + bytes, 0x00, len - bytes);
103 target[bytes - 1] = bits ? (u_int8_t)(0xff << bits) : 0xff;
104 }
105
106 METHOD(tun_device_t, set_address, bool,
107 private_tun_device_t *this, host_t *addr, u_int8_t netmask)
108 {
109 struct ifreq ifr;
110 int family;
111
112 family = addr->get_family(addr);
113 if ((netmask > 32 && family == AF_INET) || netmask > 128)
114 {
115 DBG1(DBG_LIB, "failed to set address on %s: invalid netmask",
116 this->if_name);
117 return FALSE;
118 }
119
120 memset(&ifr, 0, sizeof(ifr));
121 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
122 memcpy(&ifr.ifr_addr, addr->get_sockaddr(addr), sizeof(sockaddr_t));
123
124 if (ioctl(this->sock, SIOCSIFADDR, &ifr) < 0)
125 {
126 DBG1(DBG_LIB, "failed to set address on %s: %s",
127 this->if_name, strerror(errno));
128 return FALSE;
129 }
130
131 set_netmask(&ifr, family, netmask);
132
133 if (ioctl(this->sock, SIOCSIFNETMASK, &ifr) < 0)
134 {
135 DBG1(DBG_LIB, "failed to set netmask on %s: %s",
136 this->if_name, strerror(errno));
137 return FALSE;
138 }
139 return TRUE;
140 }
141
142 METHOD(tun_device_t, up, bool,
143 private_tun_device_t *this)
144 {
145 struct ifreq ifr;
146
147 memset(&ifr, 0, sizeof(ifr));
148 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
149
150 if (ioctl(this->sock, SIOCGIFFLAGS, &ifr) < 0)
151 {
152 DBG1(DBG_LIB, "failed to get interface flags for %s: %s", this->if_name,
153 strerror(errno));
154 return FALSE;
155 }
156
157 ifr.ifr_flags |= IFF_RUNNING | IFF_UP;
158
159 if (ioctl(this->sock, SIOCSIFFLAGS, &ifr) < 0)
160 {
161 DBG1(DBG_LIB, "failed to set interface flags on %s: %s", this->if_name,
162 strerror(errno));
163 return FALSE;
164 }
165 return TRUE;
166 }
167
168 METHOD(tun_device_t, set_mtu, bool,
169 private_tun_device_t *this, int mtu)
170 {
171 struct ifreq ifr;
172
173 memset(&ifr, 0, sizeof(ifr));
174 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
175 ifr.ifr_mtu = mtu;
176
177 if (ioctl(this->sock, SIOCSIFMTU, &ifr) < 0)
178 {
179 return FALSE;
180 }
181 this->mtu = mtu;
182 return TRUE;
183 }
184
185 METHOD(tun_device_t, get_mtu, int,
186 private_tun_device_t *this)
187 {
188 struct ifreq ifr;
189
190 if (this->mtu > 0)
191 {
192 return this->mtu;
193 }
194
195 memset(&ifr, 0, sizeof(ifr));
196 strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
197 this->mtu = TUN_DEFAULT_MTU;
198
199 if (ioctl(this->sock, SIOCGIFMTU, &ifr) == 0)
200 {
201 this->mtu = ifr.ifr_mtu;
202 }
203 return this->mtu;
204 }
205
206 METHOD(tun_device_t, get_name, char*,
207 private_tun_device_t *this)
208 {
209 return this->if_name;
210 }
211
212 METHOD(tun_device_t, write_packet, bool,
213 private_tun_device_t *this, chunk_t packet)
214 {
215 ssize_t s;
216
217 s = write(this->tunfd, packet.ptr, packet.len);
218 if (s < 0)
219 {
220 DBG1(DBG_LIB, "failed to write packet to TUN device %s: %s",
221 this->if_name, strerror(errno));
222 return FALSE;
223 }
224 else if (s != packet.len)
225 {
226 return FALSE;
227 }
228 return TRUE;
229 }
230
231 METHOD(tun_device_t, read_packet, bool,
232 private_tun_device_t *this, chunk_t *packet)
233 {
234 ssize_t len;
235 fd_set set;
236 bool old;
237
238 FD_ZERO(&set);
239 FD_SET(this->tunfd, &set);
240
241 old = thread_cancelability(TRUE);
242 len = select(this->tunfd + 1, &set, NULL, NULL, NULL);
243 thread_cancelability(old);
244
245 if (len < 0)
246 {
247 DBG1(DBG_LIB, "select on TUN device %s failed: %s", this->if_name,
248 strerror(errno));
249 return FALSE;
250 }
251 /* FIXME: this is quite expensive for lots of small packets, copy from
252 * local buffer instead? */
253 *packet = chunk_alloc(get_mtu(this));
254 len = read(this->tunfd, packet->ptr, packet->len);
255 if (len < 0)
256 {
257 DBG1(DBG_LIB, "reading from TUN device %s failed: %s", this->if_name,
258 strerror(errno));
259 chunk_free(packet);
260 return FALSE;
261 }
262 packet->len = len;
263 return TRUE;
264 }
265
266 METHOD(tun_device_t, destroy, void,
267 private_tun_device_t *this)
268 {
269 if (this->tunfd > 0)
270 {
271 close(this->tunfd);
272 }
273 if (this->sock > 0)
274 {
275 close(this->sock);
276 }
277 free(this);
278 }
279
280 /**
281 * Allocate a TUN device
282 */
283 static int tun_alloc(char dev[IFNAMSIZ])
284 {
285 struct ifreq ifr;
286 int fd;
287
288 fd = open("/dev/net/tun", O_RDWR);
289 if (fd < 0)
290 {
291 DBG1(DBG_LIB, "failed to open /dev/net/tun: %s", strerror(errno));
292 return fd;
293 }
294
295 memset(&ifr, 0, sizeof(ifr));
296
297 /* TUN device, no packet info */
298 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
299
300 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
301
302 if (ioctl(fd, TUNSETIFF, (void*)&ifr) < 0)
303 {
304 DBG1(DBG_LIB, "failed to configure TUN device: %s", strerror(errno));
305 close(fd);
306 return -1;
307 }
308 strncpy(dev, ifr.ifr_name, IFNAMSIZ);
309 return fd;
310 }
311
312 /*
313 * Described in header
314 */
315 tun_device_t *tun_device_create(const char *name_tmpl)
316 {
317 private_tun_device_t *this;
318
319 INIT(this,
320 .public = {
321 .read_packet = _read_packet,
322 .write_packet = _write_packet,
323 .get_mtu = _get_mtu,
324 .set_mtu = _set_mtu,
325 .get_name = _get_name,
326 .set_address = _set_address,
327 .up = _up,
328 .destroy = _destroy,
329 },
330 .tunfd = -1,
331 .sock = -1,
332 );
333
334 strncpy(this->if_name, name_tmpl ?: "tun%d", IFNAMSIZ);
335 this->if_name[IFNAMSIZ-1] = '\0';
336
337 this->tunfd = tun_alloc(this->if_name);
338 if (this->tunfd < 0)
339 {
340 destroy(this);
341 return NULL;
342 }
343 DBG1(DBG_LIB, "created TUN device: %s", this->if_name);
344
345 this->sock = socket(AF_INET, SOCK_DGRAM, 0);
346 if (this->sock < 0)
347 {
348 DBG1(DBG_LIB, "failed to open socket to configure TUN device");
349 destroy(this);
350 return NULL;
351 }
352 return &this->public;
353 }