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