1 /*
2 * Copyright (C) 2013 Nikos Mavrogiannopoulos
3 *
4 * This file is part of ocserv.
5 *
6 * ocserv is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * ocserv is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <config.h>
21
22 #include <fcntl.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <arpa/inet.h>
26 #include <sys/socket.h>
27 #include <net/if.h>
28 #include <netinet/in.h>
29 #include <netinet/ip.h>
30 #include <sys/ioctl.h>
31 #include <sys/uio.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <cloexec.h>
37 #include <ip-lease.h>
38 #include <minmax.h>
39
40 #if defined(HAVE_LINUX_IF_TUN_H)
41 # include <linux/if_tun.h>
42 #elif defined(HAVE_NET_IF_TUN_H)
43 # include <net/if_tun.h>
44 #endif
45
46 #include <netdb.h>
47 #include <vpn.h>
48 #include <tun.h>
49 #include <main.h>
50 #include <ccan/list/list.h>
51 #include "vhost.h"
52
53 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
54 # include <net/if_var.h>
55 # include <netinet/in_var.h>
56 #endif
57 #if defined(__OpenBSD__)
58 # include <netinet6/in6_var.h>
59 #endif
60 #if defined(__DragonFly__)
61 # include <net/tun/if_tun.h>
62 #endif
63
64 #ifdef __linux__
65
66 #include <net/route.h>
67 #include <linux/types.h>
68
69 struct in6_ifreq {
70 struct in6_addr ifr6_addr;
71 __u32 ifr6_prefixlen;
72 unsigned int ifr6_ifindex;
73 };
74
75 static
os_set_ipv6_addr(main_server_st * s,struct proc_st * proc)76 int os_set_ipv6_addr(main_server_st * s, struct proc_st *proc)
77 {
78 int fd, e, ret;
79 struct in6_ifreq ifr6;
80 struct in6_rtmsg rt6;
81 struct ifreq ifr;
82 unsigned idx;
83
84 fd = socket(AF_INET6, SOCK_STREAM, 0);
85 if (fd == -1) {
86 e = errno;
87 mslog(s, NULL, LOG_ERR, "%s: Error socket(AF_INET6): %s\n",
88 proc->tun_lease.name, strerror(e));
89 return -1;
90 }
91
92 memset(&ifr, 0, sizeof(ifr));
93 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
94
95 ret = ioctl(fd, SIOGIFINDEX, &ifr);
96 if (ret != 0) {
97 e = errno;
98 mslog(s, NULL, LOG_ERR, "%s: Error in SIOGIFINDEX: %s\n",
99 proc->tun_lease.name, strerror(e));
100 ret = -1;
101 goto cleanup;
102 }
103
104 idx = ifr.ifr_ifindex;
105
106 memset(&ifr6, 0, sizeof(ifr6));
107 memcpy(&ifr6.ifr6_addr, SA_IN6_P(&proc->ipv6->lip),
108 SA_IN_SIZE(proc->ipv6->lip_len));
109 ifr6.ifr6_ifindex = idx;
110 ifr6.ifr6_prefixlen = 128;
111
112 ret = ioctl(fd, SIOCSIFADDR, &ifr6);
113 if (ret != 0) {
114 e = errno;
115 mslog(s, NULL, LOG_ERR, "%s: Error setting IPv6: %s\n",
116 proc->tun_lease.name, strerror(e));
117 ret = -1;
118 goto cleanup;
119 }
120
121 memset(&ifr, 0, sizeof(ifr));
122 ifr.ifr_addr.sa_family = AF_INET6;
123 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
124 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
125
126 ret = ioctl(fd, SIOCSIFFLAGS, &ifr);
127 if (ret != 0) {
128 e = errno;
129 mslog(s, NULL, LOG_ERR,
130 "%s: Could not bring up IPv6 interface: %s\n",
131 proc->tun_lease.name, strerror(e));
132 ret = -1;
133 goto cleanup;
134 }
135
136 /* route to our remote address */
137 memset(&rt6, 0, sizeof(rt6));
138 memcpy(&rt6.rtmsg_dst, SA_IN6_P(&proc->ipv6->rip),
139 SA_IN_SIZE(proc->ipv6->rip_len));
140 rt6.rtmsg_ifindex = idx;
141 rt6.rtmsg_dst_len = proc->ipv6->prefix;
142 rt6.rtmsg_metric = 1;
143
144 /* the ioctl() parameters in linux for ipv6 are
145 * well hidden. For that one we use SIOCADDRT as
146 * in busybox. */
147 ret = ioctl(fd, SIOCADDRT, &rt6);
148 if (ret != 0) {
149 e = errno;
150 mslog(s, NULL, LOG_ERR, "%s: Error setting route to remote IPv6: %s\n",
151 proc->tun_lease.name, strerror(e));
152 ret = -1;
153 goto cleanup;
154 }
155
156 ret = 0;
157 cleanup:
158 close(fd);
159
160 return ret;
161 }
162
os_reset_ipv6_addr(struct proc_st * proc)163 static void os_reset_ipv6_addr(struct proc_st *proc)
164 {
165 int fd, ret;
166 struct in6_ifreq ifr6;
167 struct in6_rtmsg rt6;
168 struct ifreq ifr;
169 unsigned idx;
170
171 if (proc->ipv6 == NULL || proc->ipv6->lip_len == 0)
172 return;
173
174 fd = socket(AF_INET6, SOCK_STREAM, 0);
175 if (fd == -1) {
176 return;
177 }
178
179 memset(&ifr, 0, sizeof(ifr));
180 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
181
182 ret = ioctl(fd, SIOGIFINDEX, &ifr);
183 if (ret != 0) {
184 goto cleanup;
185 }
186
187 idx = ifr.ifr_ifindex;
188
189 memset(&ifr6, 0, sizeof(ifr6));
190 memcpy(&ifr6.ifr6_addr, SA_IN6_P(&proc->ipv6->lip),
191 SA_IN_SIZE(proc->ipv6->lip_len));
192 ifr6.ifr6_ifindex = idx;
193 ifr6.ifr6_prefixlen = 128;
194
195 ret = ioctl(fd, SIOCDIFADDR, &ifr6);
196 if (ret != 0) {
197 goto cleanup;
198 }
199
200 /* route to our remote address */
201 memset(&rt6, 0, sizeof(rt6));
202 memcpy(&rt6.rtmsg_dst, SA_IN6_P(&proc->ipv6->rip),
203 SA_IN_SIZE(proc->ipv6->rip_len));
204 rt6.rtmsg_ifindex = idx;
205 rt6.rtmsg_dst_len = 128;
206 rt6.rtmsg_metric = 1;
207
208 ret = ioctl(fd, SIOCDELRT, &rt6);
209 if (ret != 0) {
210 goto cleanup;
211 }
212
213 cleanup:
214 close(fd);
215 }
216
217 #elif defined(SIOCAIFADDR_IN6)
218
219 #include <netinet6/nd6.h>
220
221 static
os_set_ipv6_addr(main_server_st * s,struct proc_st * proc)222 int os_set_ipv6_addr(main_server_st * s, struct proc_st *proc)
223 {
224 int fd, e, ret;
225 struct in6_aliasreq ifr6;
226 struct ifreq ifr;
227
228 fd = socket(AF_INET6, SOCK_STREAM, 0);
229 if (fd == -1) {
230 e = errno;
231 mslog(s, NULL, LOG_ERR, "%s: Error socket(AF_INET6): %s\n",
232 proc->tun_lease.name, strerror(e));
233 return -1;
234 }
235
236 memset(&ifr6, 0, sizeof(ifr6));
237 strlcpy(ifr6.ifra_name, proc->tun_lease.name, IFNAMSIZ);
238
239 memcpy(&ifr6.ifra_addr.sin6_addr, SA_IN6_P(&proc->ipv6->lip),
240 SA_IN_SIZE(proc->ipv6->lip_len));
241 ifr6.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
242 ifr6.ifra_addr.sin6_family = AF_INET6;
243
244 memcpy(&ifr6.ifra_dstaddr.sin6_addr, SA_IN6_P(&proc->ipv6->rip),
245 SA_IN_SIZE(proc->ipv6->rip_len));
246 ifr6.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
247 ifr6.ifra_dstaddr.sin6_family = AF_INET6;
248
249 ret = ipv6_prefix_to_mask(&ifr6.ifra_prefixmask.sin6_addr, proc->ipv6->prefix);
250 if (ret == 0) {
251 memset(&ifr6.ifra_prefixmask.sin6_addr, 0xff, sizeof(struct in6_addr));
252 }
253 ifr6.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
254 ifr6.ifra_prefixmask.sin6_family = AF_INET6;
255
256 ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
257 ifr6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
258
259 ret = ioctl(fd, SIOCAIFADDR_IN6, &ifr6);
260 if (ret != 0) {
261 e = errno;
262 mslog(s, NULL, LOG_ERR, "%s: Error setting IPv6: %s\n",
263 proc->tun_lease.name, strerror(e));
264 ret = -1;
265 goto cleanup;
266 }
267
268 memset(&ifr, 0, sizeof(ifr));
269 ifr.ifr_addr.sa_family = AF_INET6;
270 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
271 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
272
273 ret = ioctl(fd, SIOCSIFFLAGS, &ifr);
274 if (ret != 0) {
275 e = errno;
276 mslog(s, NULL, LOG_ERR,
277 "%s: Could not bring up IPv6 interface: %s\n",
278 proc->tun_lease.name, strerror(e));
279 ret = -1;
280 goto cleanup;
281 }
282
283 ret = 0;
284 cleanup:
285 close(fd);
286
287 return ret;
288 }
289
os_reset_ipv6_addr(struct proc_st * proc)290 static void os_reset_ipv6_addr(struct proc_st *proc)
291 {
292 struct in6_ifreq ifr6;
293 int fd;
294
295 if (proc->ipv6 == NULL || proc->ipv6->lip_len == 0)
296 return;
297
298 fd = socket(AF_INET6, SOCK_DGRAM, 0);
299
300 if (fd >= 0) {
301 memset(&ifr6, 0, sizeof(ifr6));
302 strlcpy(ifr6.ifr_name, proc->tun_lease.name, IFNAMSIZ);
303
304 memcpy(&ifr6.ifr_addr.sin6_addr, SA_IN6_P(&proc->ipv6->lip),
305 SA_IN_SIZE(proc->ipv6->lip_len));
306 ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
307 ifr6.ifr_addr.sin6_family = AF_INET6;
308
309 (void)ioctl(fd, SIOCDIFADDR_IN6, &ifr6);
310 close(fd);
311 }
312 }
313
314 #else
315 #warning "No IPv6 support on this platform"
os_set_ipv6_addr(main_server_st * s,struct proc_st * proc)316 static int os_set_ipv6_addr(main_server_st * s, struct proc_st *proc)
317 {
318 return -1;
319 }
320
os_reset_ipv6_addr(struct proc_st * proc)321 static void os_reset_ipv6_addr(struct proc_st *proc)
322 {
323 return;
324 }
325
326 #endif
327
set_network_info(main_server_st * s,struct proc_st * proc)328 static int set_network_info(main_server_st * s, struct proc_st *proc)
329 {
330 int fd = -1, ret, e;
331 #ifdef SIOCAIFADDR
332 struct in_aliasreq ifr;
333 #else
334 struct ifreq ifr;
335 #endif
336
337 if (proc->ipv4 && proc->ipv4->lip_len > 0 && proc->ipv4->rip_len > 0) {
338 memset(&ifr, 0, sizeof(ifr));
339
340 fd = socket(AF_INET, SOCK_STREAM, 0);
341 if (fd == -1)
342 return -1;
343
344 #ifdef SIOCAIFADDR
345 strlcpy(ifr.ifra_name, proc->tun_lease.name, IFNAMSIZ);
346
347 memcpy(&ifr.ifra_addr, &proc->ipv4->lip, proc->ipv4->lip_len);
348 ifr.ifra_addr.sin_len = sizeof(struct sockaddr_in);
349 ifr.ifra_addr.sin_family = AF_INET;
350
351 memcpy(&ifr.ifra_dstaddr, &proc->ipv4->rip, proc->ipv4->rip_len);
352 ifr.ifra_dstaddr.sin_len = sizeof(struct sockaddr_in);
353 ifr.ifra_dstaddr.sin_family = AF_INET;
354
355 ifr.ifra_mask.sin_len = sizeof(struct sockaddr_in);
356 ifr.ifra_mask.sin_family = AF_INET;
357 ifr.ifra_mask.sin_addr.s_addr = 0xffffffff;
358 ret = ioctl(fd, SIOCAIFADDR, &ifr);
359 if (ret != 0) {
360 e = errno;
361 mslog(s, NULL, LOG_ERR, "%s: Error setting IPv4: %s\n",
362 proc->tun_lease.name, strerror(e));
363 ret = -1;
364 goto cleanup;
365 }
366 #else
367 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
368 memcpy(&ifr.ifr_addr, &proc->ipv4->lip, proc->ipv4->lip_len);
369 ifr.ifr_addr.sa_family = AF_INET;
370
371 ret = ioctl(fd, SIOCSIFADDR, &ifr);
372 if (ret != 0) {
373 e = errno;
374 mslog(s, NULL, LOG_ERR, "%s: Error setting IPv4: %s\n",
375 proc->tun_lease.name, strerror(e));
376 ret = -1;
377 goto cleanup;
378 }
379
380 memset(&ifr, 0, sizeof(ifr));
381
382 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
383 memcpy(&ifr.ifr_dstaddr, &proc->ipv4->rip, proc->ipv4->rip_len);
384 ifr.ifr_dstaddr.sa_family = AF_INET;
385
386 ret = ioctl(fd, SIOCSIFDSTADDR, &ifr);
387 if (ret != 0) {
388 e = errno;
389 mslog(s, NULL, LOG_ERR,
390 "%s: Error setting DST IPv4: %s\n",
391 proc->tun_lease.name, strerror(e));
392 ret = -1;
393 goto cleanup;
394 }
395
396 /* bring interface up */
397 memset(&ifr, 0, sizeof(ifr));
398 ifr.ifr_addr.sa_family = AF_INET;
399 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
400 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
401
402 ret = ioctl(fd, SIOCSIFFLAGS, &ifr);
403 if (ret != 0) {
404 mslog(s, NULL, LOG_ERR,
405 "%s: Could not bring up IPv4 interface.\n",
406 proc->tun_lease.name);
407 ret = -1;
408 goto cleanup;
409 }
410 #endif
411
412 close(fd);
413 fd = -1;
414 }
415
416 if (proc->ipv6 && proc->ipv6->lip_len > 0 && proc->ipv6->rip_len > 0) {
417 ret = os_set_ipv6_addr(s, proc);
418 if (ret < 0) {
419 remove_ip_lease(s, proc->ipv6);
420 proc->ipv6 = NULL;
421 }
422 }
423
424 if (proc->ipv6 == 0 && proc->ipv4 == 0) {
425 mslog(s, NULL, LOG_ERR, "%s: Could not set any IP.\n",
426 proc->tun_lease.name);
427 ret = -1;
428 goto cleanup;
429 }
430
431 ret = 0;
432
433 cleanup:
434 if (fd != -1)
435 close(fd);
436 return ret;
437 }
438
439 #include <ccan/hash/hash.h>
440
441 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
442
bsd_ifrename(main_server_st * s,struct proc_st * proc)443 static int bsd_ifrename(main_server_st *s, struct proc_st *proc)
444 {
445 #ifdef SIOCSIFNAME
446 int fd = -1;
447 int e, ret;
448 struct ifreq ifr;
449 uint8_t ctr;
450 unsigned i;
451 char tun_name[IFNAMSIZ];
452 static unsigned next_tun_nr = 0;
453 unsigned renamed = 0;
454
455 fd = socket(AF_INET, SOCK_DGRAM, 0);
456 if (fd == -1)
457 return -1;
458
459 memset(&ifr, 0, sizeof(struct ifreq));
460 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
461
462 ret = snprintf(tun_name, sizeof(tun_name), "%s%u",
463 GETCONFIG(s)->network.name, next_tun_nr+1024);
464 if (ret >= sizeof(tun_name))
465 next_tun_nr = 0;
466
467 ctr = next_tun_nr;
468
469 for (i=ctr;i<ctr+1024;i++) {
470 ret = snprintf(tun_name, sizeof(tun_name), "%s%u",
471 GETCONFIG(s)->network.name, i);
472 if (ret != strlen(tun_name)) {
473 mslog(s, NULL, LOG_ERR, "Truncation error in tun name: %s; adjust 'device' option\n",
474 proc->tun_lease.name);
475 return -1;
476 }
477
478 ifr.ifr_data = tun_name;
479
480 ret = ioctl(fd, SIOCSIFNAME, &ifr);
481 if (ret != 0) {
482 e = errno;
483 if (e == EEXIST)
484 continue;
485
486 mslog(s, NULL, LOG_ERR, "%s: Error renaming interface: %s\n",
487 proc->tun_lease.name, strerror(e));
488 goto fail;
489 }
490
491 renamed = 1;
492 break;
493 }
494
495
496 /* set new name */
497 next_tun_nr = ctr+1;
498
499 if (renamed) {
500 strlcpy(proc->tun_lease.name, tun_name, sizeof(proc->tun_lease.name));
501 ret = 0;
502 } else {
503 e = errno;
504 mslog(s, NULL, LOG_WARNING, "Error renaming interface: %s to %s: %s\n",
505 proc->tun_lease.name, tun_name, strerror(e));
506 ret = -1;
507 }
508
509 fail:
510 close(fd);
511
512 return ret;
513 #endif
514 }
515
516 /* BSD version */
os_open_tun(main_server_st * s,struct proc_st * proc)517 static int os_open_tun(main_server_st * s, struct proc_st *proc)
518 {
519 int fd, e, ret;
520 int sock;
521 struct ifreq ifr;
522 int unit_nr = 0;
523 struct stat st;
524
525 fd = open("/dev/tun", O_RDWR);
526 if (fd == -1) {
527 /* try iterating */
528 e = errno;
529 mslog(s, NULL, LOG_DEBUG, "cannot open /dev/tun; falling back to iteration: %s", strerror(e));
530 for (unit_nr = 0; unit_nr < 255; unit_nr++) {
531 snprintf(proc->tun_lease.name, sizeof(proc->tun_lease.name), "/dev/tun%d", unit_nr);
532 fd = open(proc->tun_lease.name, O_RDWR);
533 #ifdef SIOCIFCREATE
534 if (fd == -1) {
535 /* cannot open tunXX, try creating it */
536 sock = socket(AF_INET, SOCK_DGRAM, 0);
537 if (sock < 0) {
538 e = errno;
539 mslog(s, NULL, LOG_ERR, "cannot create tun socket: %s", strerror(e));
540 return -1;
541 }
542
543 memset(&ifr, 0, sizeof(ifr));
544 strncpy(ifr.ifr_name, proc->tun_lease.name + 5, sizeof(ifr.ifr_name) - 1);
545 if (!ioctl(sock, SIOCIFCREATE, &ifr))
546 fd = open(proc->tun_lease.name, O_RDWR);
547 close(sock);
548 }
549 #endif
550 if (fd >= 0)
551 break;
552 }
553 }
554
555 if (fd < 0)
556 return fd;
557
558 #if defined(__OpenBSD__)
559 /* OpenBSD's devname does not return the correct name if unit_nr>=4.
560 * See https://gitlab.com/openconnect/ocserv/-/issues/399
561 */
562 snprintf(proc->tun_lease.name, sizeof(proc->tun_lease.name), "tun%d", unit_nr);
563 #else
564 /* get tun name */
565 ret = fstat(fd, &st);
566 if (ret < 0) {
567 e = errno;
568 mslog(s, NULL, LOG_ERR, "tun fd %d: stat: %s\n", fd, strerror(e));
569 close(fd);
570 return -1;
571 }
572 strlcpy(proc->tun_lease.name, devname(st.st_rdev, S_IFCHR), sizeof(proc->tun_lease.name));
573 #endif
574
575 if (fd >= 0) {
576 int i, e, ret;
577 #if defined(__OpenBSD__)
578 /* enable multicast for tun interface (OpenBSD) */
579 struct tuninfo inf;
580 ret = ioctl(fd, TUNGIFINFO, &inf);
581 if (ret < 0) {
582 e = errno;
583 mslog(s, NULL, LOG_ERR, "%s: TUNGIFINFO: %s\n",
584 proc->tun_lease.name, strerror(e));
585 } else {
586 inf.flags |= IFF_MULTICAST;
587
588 ret = ioctl(fd, TUNSIFINFO, &inf);
589 if (ret < 0) {
590 e = errno;
591 mslog(s, NULL, LOG_ERR, "%s: TUNSIFINFO: %s\n",
592 proc->tun_lease.name, strerror(e));
593 }
594 }
595 #else /* FreeBSD + NetBSD */
596 i = IFF_POINTOPOINT | IFF_MULTICAST;
597 ret = ioctl(fd, TUNSIFMODE, &i);
598 if (ret < 0) {
599 e = errno;
600 mslog(s, NULL, LOG_ERR, "%s: TUNSIFMODE: %s\n",
601 proc->tun_lease.name, strerror(e));
602 }
603
604 /* link layer mode off */
605 i = 0;
606 ret = ioctl(fd, TUNSLMODE, &i);
607 if (ret < 0) {
608 e = errno;
609 mslog(s, NULL, LOG_ERR, "%s: TUNSLMODE: %s\n",
610 proc->tun_lease.name, strerror(e));
611 }
612 #endif
613
614 #ifdef TUNSIFHEAD
615 i = 1;
616
617 ret = ioctl(fd, TUNSIFHEAD, &i);
618 if (ret < 0) {
619 e = errno;
620 mslog(s, NULL, LOG_ERR, "%s: TUNSIFHEAD: %s\n",
621 proc->tun_lease.name, strerror(e));
622 }
623 #endif /* TUNSIFHEAD */
624
625 }
626
627 /* rename the device if possible */
628 if (bsd_ifrename(s, proc) < 0) {
629 close(fd);
630 return -1;
631 }
632
633 return fd;
634 }
635 #elif defined(__linux__)
636 /* Linux version */
os_open_tun(main_server_st * s,struct proc_st * proc)637 static int os_open_tun(main_server_st * s, struct proc_st *proc)
638 {
639 int tunfd, ret, e;
640 struct ifreq ifr;
641 unsigned int t;
642
643 ret = snprintf(proc->tun_lease.name, sizeof(proc->tun_lease.name), "%s%%d",
644 GETCONFIG(s)->network.name);
645 if (ret != strlen(proc->tun_lease.name)) {
646 mslog(s, NULL, LOG_ERR, "Truncation error in tun name: %s; adjust 'device' option\n",
647 proc->tun_lease.name);
648 return -1;
649 }
650
651 /* Obtain a free tun device */
652 tunfd = open("/dev/net/tun", O_RDWR);
653 if (tunfd < 0) {
654 int e = errno;
655 mslog(s, NULL, LOG_ERR, "Can't open /dev/net/tun: %s\n",
656 strerror(e));
657 return -1;
658 }
659
660 memset(&ifr, 0, sizeof(ifr));
661 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
662
663 memcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
664
665 if (ioctl(tunfd, TUNSETIFF, (void *)&ifr) < 0) {
666 e = errno;
667 mslog(s, NULL, LOG_ERR, "%s: TUNSETIFF: %s\n",
668 proc->tun_lease.name, strerror(e));
669 goto fail;
670 }
671 memcpy(proc->tun_lease.name, ifr.ifr_name, IFNAMSIZ);
672 mslog(s, proc, LOG_DEBUG, "assigning tun device %s\n",
673 proc->tun_lease.name);
674
675 /* we no longer use persistent tun */
676 if (ioctl(tunfd, TUNSETPERSIST, (void *)0) < 0) {
677 e = errno;
678 mslog(s, NULL, LOG_ERR, "%s: TUNSETPERSIST: %s\n",
679 proc->tun_lease.name, strerror(e));
680 goto fail;
681 }
682
683 if (GETPCONFIG(s)->uid != -1) {
684 t = GETPCONFIG(s)->uid;
685 ret = ioctl(tunfd, TUNSETOWNER, t);
686 if (ret < 0) {
687 e = errno;
688 mslog(s, NULL, LOG_INFO, "%s: TUNSETOWNER: %s\n",
689 proc->tun_lease.name, strerror(e));
690 goto fail;
691 }
692 }
693 #ifdef TUNSETGROUP
694 if (GETPCONFIG(s)->gid != -1) {
695 t = GETPCONFIG(s)->gid;
696 ret = ioctl(tunfd, TUNSETGROUP, t);
697 if (ret < 0) {
698 e = errno;
699 mslog(s, NULL, LOG_ERR, "%s: TUNSETGROUP: %s\n",
700 proc->tun_lease.name, strerror(e));
701 /* kernels prior to 2.6.23 do not have this ioctl()
702 * and return this error. In that case we ignore the
703 * error. */
704 if (e != EINVAL)
705 goto fail;
706 }
707 }
708 #endif
709
710 return tunfd;
711 fail:
712 close(tunfd);
713 return -1;
714 }
715 #endif /* __linux__ */
716
open_tun(main_server_st * s,struct proc_st * proc)717 int open_tun(main_server_st * s, struct proc_st *proc)
718 {
719 int tunfd, ret;
720
721 ret = get_ip_leases(s, proc);
722 if (ret < 0)
723 return ret;
724
725 /* No need to free the lease after this point.
726 */
727 tunfd = os_open_tun(s, proc);
728 if (tunfd < 0) {
729 int e = errno;
730 mslog(s, NULL, LOG_ERR, "Can't open tun device: %s\n",
731 strerror(e));
732 return -1;
733 }
734
735 set_cloexec_flag(tunfd, 1);
736
737 if (proc->tun_lease.name[0] == 0) {
738 mslog(s, NULL, LOG_ERR, "tun device with no name!");
739 goto fail;
740 }
741
742 /* set IP/mask */
743 ret = set_network_info(s, proc);
744 if (ret < 0) {
745 goto fail;
746 }
747
748 proc->tun_lease.fd = tunfd;
749
750 return 0;
751 fail:
752 close(tunfd);
753 return -1;
754 }
755
close_tun(main_server_st * s,struct proc_st * proc)756 void close_tun(main_server_st * s, struct proc_st *proc)
757 {
758
759 if (proc->tun_lease.fd >= 0) {
760 close(proc->tun_lease.fd);
761 proc->tun_lease.fd = -1;
762 }
763
764 #ifdef SIOCIFDESTROY
765 int fd = -1;
766 int e, ret;
767 struct ifreq ifr;
768
769 if (proc->tun_lease.name[0] != 0) {
770 fd = socket(AF_INET, SOCK_DGRAM, 0);
771 if (fd == -1)
772 return;
773
774 memset(&ifr, 0, sizeof(struct ifreq));
775 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
776
777 ret = ioctl(fd, SIOCIFDESTROY, &ifr);
778 if (ret != 0) {
779 e = errno;
780 mslog(s, NULL, LOG_ERR, "%s: Error destroying interface: %s\n",
781 proc->tun_lease.name, strerror(e));
782 }
783 }
784
785 if (fd != -1)
786 close(fd);
787 #endif
788
789 return;
790 }
791
reset_ipv4_addr(struct proc_st * proc)792 static void reset_ipv4_addr(struct proc_st *proc)
793 {
794 int fd;
795
796 if (proc->ipv4 == NULL || proc->ipv4->lip_len == 0)
797 return;
798
799 #if defined(SIOCDIFADDR) && !defined(__linux__)
800 fd = socket(AF_INET, SOCK_DGRAM, 0);
801
802 if (fd >= 0) {
803 struct ifreq ifr;
804
805 memset(&ifr, 0, sizeof(ifr));
806 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
807
808 memcpy(&ifr.ifr_addr, &proc->ipv4->lip, proc->ipv4->lip_len);
809 ifr.ifr_addr.sa_len = sizeof(struct sockaddr_in);
810 ifr.ifr_addr.sa_family = AF_INET;
811
812 (void)ioctl(fd, SIOCDIFADDR, &ifr);
813 close(fd);
814 }
815 #elif defined(__linux__)
816 fd = socket(AF_INET, SOCK_STREAM, 0);
817 if (fd >= 0) {
818 struct ifreq ifr;
819
820 strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ);
821 memcpy(&ifr.ifr_addr, &proc->ipv4->lip, proc->ipv4->lip_len);
822 ifr.ifr_addr.sa_family = AF_INET;
823
824 (void)ioctl(fd, SIOCDIFADDR, &ifr);
825
826 close(fd);
827 }
828 #endif
829 }
830
reset_tun(struct proc_st * proc)831 void reset_tun(struct proc_st* proc)
832 {
833 if (proc->tun_lease.name[0] != 0) {
834 reset_ipv4_addr(proc);
835 os_reset_ipv6_addr(proc);
836 }
837 }
838
839 #if defined(__OpenBSD__) || defined(TUNSIFHEAD)
840 # define TUN_AF_PREFIX 1
841 #endif
842
843 #ifdef TUN_AF_PREFIX
tun_write(int sockfd,const void * buf,size_t len)844 ssize_t tun_write(int sockfd, const void *buf, size_t len)
845 {
846 struct ip *iph = (void *)buf;
847 uint32_t head;
848 const uint8_t *data = buf;
849 static int complained = 0;
850 struct iovec iov[2];
851 int ret;
852
853 if (iph->ip_v == 6)
854 head = htonl(AF_INET6);
855 else if (iph->ip_v == 4)
856 head = htonl(AF_INET);
857 else {
858 if (!complained) {
859 complained = 1;
860 syslog(LOG_ERR, "tun_write: Unknown packet (len %d) received %02x %02x %02x %02x...\n",
861 (int)len, data[0], data[1], data[2], data[3]);
862 }
863 return -1;
864 }
865
866 iov[0].iov_base = &head;
867 iov[0].iov_len = sizeof(head);
868 iov[1].iov_base = (void*)buf;
869 iov[1].iov_len = len;
870
871 ret = writev(sockfd, iov, 2);
872 if (ret >= sizeof(uint32_t))
873 ret -= sizeof(uint32_t);
874 return ret;
875 }
876
tun_read(int sockfd,void * buf,size_t len)877 ssize_t tun_read(int sockfd, void *buf, size_t len)
878 {
879 uint32_t head;
880 struct iovec iov[2];
881 int ret;
882
883 iov[0].iov_base = &head;
884 iov[0].iov_len = sizeof(head);
885 iov[1].iov_base = buf;
886 iov[1].iov_len = len;
887
888 ret = readv(sockfd, iov, 2);
889 if (ret >= sizeof(uint32_t))
890 ret -= sizeof(uint32_t);
891 return ret;
892 }
893
894 #else
tun_write(int sockfd,const void * buf,size_t len)895 ssize_t tun_write(int sockfd, const void *buf, size_t len)
896 {
897 return force_write(sockfd, buf, len);
898 }
899
tun_read(int sockfd,void * buf,size_t len)900 ssize_t tun_read(int sockfd, void *buf, size_t len)
901 {
902 return read(sockfd, buf, len);
903 }
904 #endif
905
906 #ifndef __FreeBSD__
tun_claim(int sockfd)907 int tun_claim(int sockfd)
908 {
909
910 return (0);
911 }
912 #else
913 /*
914 * FreeBSD has a mechanism by which a tunnel has a single controlling process,
915 * and only that one process may close it. When the controlling process closes
916 * the tunnel, the state is torn down.
917 */
tun_claim(int sockfd)918 int tun_claim(int sockfd)
919 {
920
921 return (ioctl(sockfd, TUNSIFPID, 0));
922 }
923 #endif /* !__FreeBSD__ */
924