1 /*
2  * tun6.c - IPv6 tunnel interface definition
3  */
4 
5 /***********************************************************************
6  *  Copyright © 2004-2009 Rémi Denis-Courmont.                         *
7  *  This program is free software; you can redistribute and/or modify  *
8  *  it under the terms of the GNU General Public License as published  *
9  *  by the Free Software Foundation; version 2 of the license, or (at  *
10  *  your option) any later version.                                    *
11  *                                                                     *
12  *  This program is distributed in the hope that it will be useful,    *
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of     *
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               *
15  *  See the GNU General Public License for more details.               *
16  *                                                                     *
17  *  You should have received a copy of the GNU General Public License  *
18  *  along with this program; if not, you can get it from:              *
19  *  http://www.gnu.org/copyleft/gpl.html                               *
20  ***********************************************************************/
21 
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25 
26 #include <gettext.h>
27 
28 #include <assert.h>
29 
30 #include <stdio.h> // snprintf() for BSD drivers
31 #include <string.h>
32 #include <stdlib.h> // free()
33 #include <inttypes.h>
34 
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <sys/ioctl.h>
39 #include <unistd.h>
40 #include <sys/uio.h> // readv() & writev()
41 #include <syslog.h>
42 #include <errno.h>
43 #include <netinet/in.h> // htons(), struct in6_addr
44 
45 #include <sys/socket.h> // socket(AF_INET6, SOCK_DGRAM, 0)
46 
47 #include <net/if.h> // struct ifreq, if_nametoindex(), if_indextoname()
48 
49 #if defined (__linux__)
50 /*
51  * Linux tunneling driver
52  */
53 const char os_driver[] = "Linux";
54 # define USE_LINUX 1
55 
56 # include <linux/if_tun.h> // TUNSETIFF - Linux tunnel driver
57 /*
58  * <linux/ipv6.h> conflicts with <netinet/in.h> and <arpa/inet.h>,
59  * so we've got to declare this structure by hand.
60  */
61 struct in6_ifreq {
62 	struct in6_addr ifr6_addr;
63 	uint32_t ifr6_prefixlen;
64 	int ifr6_ifindex;
65 };
66 
67 # include <net/route.h> // struct in6_rtmsg
68 # include <netinet/if_ether.h> // ETH_P_IPV6
69 
70 typedef struct
71 {
72 	uint16_t flags;
73 	uint16_t proto;
74 } tun_head_t;
75 
76 # define TUN_HEAD_IPV6_INITIALIZER { 0, htons (ETH_P_IPV6) }
77 # define tun_head_is_ipv6( h ) (h.proto == htons (ETH_P_IPV6))
78 
79 #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || \
80       defined (__NetBSD__)  || defined (__NetBSD_kernel__)  || \
81       defined (__OpenBSD__) || defined (__OpenBSD_kernel__) || \
82       defined (__DragonFly__) || \
83       defined (__APPLE__) /* Darwin */
84 #include <ifaddrs.h>
85 /*
86  * BSD tunneling driver
87  * NOTE: the driver is NOT tested on Darwin (Mac OS X).
88  */
89 const char os_driver[] = "BSD";
90 # define USE_BSD 1
91 
92 // Auto-loading
93 # ifdef HAVE_KLDLOAD
94 #  include <sys/param.h>
95 #  include <sys/linker.h>
96 # endif
97 
98 // TUNSIFHEAD or TUNSLMODE
99 # if defined (HAVE_NET_IF_TUN_H)
100 #  include <net/if_tun.h>
101 # elif defined (HAVE_NET_TUN_IF_TUN_H)
102 #  include <net/tun/if_tun.h>
103 # elif defined (__APPLE__)
104 #  define TUNSIFHEAD  _IOW('t', 96, int)
105 # endif
106 
107 # ifdef HAVE_NET_IF_VAR_H
108 #  include <net/if_var.h>
109 # endif
110 
111 # include <net/if_dl.h> // struct sockaddr_dl
112 # include <net/route.h> // AF_ROUTE things
113 # include <netinet6/in6_var.h> // struct in6_aliasreq
114 # include <netinet6/nd6.h> // ND6_INFINITE_LIFETIME
115 
116 # include <pthread.h>
117 
118 typedef uint32_t tun_head_t;
119 
120 # define TUN_HEAD_IPV6_INITIALIZER htonl (AF_INET6)
121 # define tun_head_is_ipv6( h ) (h == htonl (AF_INET6))
122 
123 #else
124 const char os_driver[] = "Generic";
125 
126 # warning Unknown host OS. The driver will probably not work.
127 #endif
128 
129 #include <libtun6/tun6.h>
130 
131 #define safe_strcpy( tgt, src ) \
132 	((strlcpy (tgt, src, sizeof (tgt)) >= sizeof (tgt)) ? -1 : 0)
133 
134 struct tun6
135 {
136 	int  id, fd, reqfd;
137 #if defined (USE_BSD)
138 	char orig_name[IFNAMSIZ];
139 #endif
140 };
141 
142 /**
143  * Tries to allocate a tunnel interface from the kernel.
144  *
145  * @param req_name may be an interface name for the virtual network device
146  * (it might be ignored on some OSes).
147  * If NULL, an internal default will be used.
148  *
149  * @return NULL on error.
150  */
tun6_create(const char * req_name)151 tun6 *tun6_create (const char *req_name)
152 {
153 	(void)bindtextdomain (PACKAGE_NAME, LOCALEDIR);
154 	tun6 *t = (tun6 *)malloc (sizeof (*t));
155 	if (t == NULL)
156 		return NULL;
157 	memset (t, 0, sizeof (*t));
158 
159 	int reqfd = t->reqfd = socket (AF_INET6, SOCK_DGRAM, 0);
160 	if (reqfd == -1)
161 	{
162 		free (t);
163 		return NULL;
164 	}
165 
166 	fcntl (reqfd, F_SETFD, FD_CLOEXEC);
167 
168 #if defined (USE_LINUX)
169 	/*
170 	 * TUNTAP (Linux) tunnel driver initialization
171 	 */
172 	static const char tundev[] = "/dev/net/tun";
173 	struct ifreq req =
174 	{
175 		.ifr_flags = IFF_TUN
176 	};
177 
178 	if ((req_name != NULL) && safe_strcpy (req.ifr_name, req_name))
179 	{
180 		free (t);
181 		return NULL;
182 	}
183 
184 	int fd = open (tundev, O_RDWR);
185 	if (fd == -1)
186 	{
187 		syslog (LOG_ERR, _("Tunneling driver error (%s): %m"), tundev);
188 		(void)close (reqfd);
189 		free (t);
190 		return NULL;
191 	}
192 
193 	// Allocates the tunneling virtual network interface
194 	if (ioctl (fd, TUNSETIFF, (void *)&req))
195 	{
196 		syslog (LOG_ERR, _("Tunneling driver error (%s): %m"), "TUNSETIFF");
197 		if (errno == EBUSY)
198 			syslog (LOG_INFO,
199 			        _("Please make sure another instance of the program is "
200 	        	          "not already running."));
201 		goto error;
202 	}
203 
204 	int id = if_nametoindex (req.ifr_name);
205 	if (id == 0)
206 		goto error;
207 #elif defined (USE_BSD)
208 # ifdef HAVE_KLDLOAD
209 	kldload ("if_tun");
210 # endif
211 	/*
212 	 * BSD tunnel driver initialization
213 	 * (see BSD src/sys/net/if_tun.{c,h})
214 	 */
215 	int fd = open ("/dev/tun", O_RDWR);
216 	if ((fd == -1) && (errno == ENOENT))
217 	{
218 		/*
219 		 * Some BSD variants or older kernel versions do not support /dev/tun,
220 		 * so fallback to the old scheme.
221 		 */
222 		int saved_errno = 0;
223 		for (unsigned i = 0; fd == -1; i++)
224 		{
225 			char tundev[5 + IFNAMSIZ];
226 			snprintf (tundev, sizeof (tundev), "/dev/tun%u", i);
227 
228 			fd = open (tundev, O_RDWR);
229 			if ((fd == -1) && (errno == ENOENT))
230 				// If /dev/tun<i> does not exist,
231 				// /dev/tun<i+1> won't exist either
232 				break;
233 
234 			saved_errno = errno;
235 		}
236 		errno = saved_errno;
237 	}
238 
239 	if (fd == -1)
240 	{
241 		syslog (LOG_ERR, _("Tunneling driver error (%s): %m"), "/dev/tun*");
242 		goto error;
243 	}
244 	else
245 	{
246 		struct stat st;
247 		fstat (fd, &st);
248 # ifdef HAVE_DEVNAME_R
249 		devname_r (st.st_rdev, S_IFCHR, t->orig_name, sizeof (t->orig_name));
250 # else
251 		const char *name = devname (st.st_rdev, S_IFCHR);
252 		if (safe_strcpy (t->orig_name, name))
253 			goto error;
254 # endif
255 	}
256 
257 	int id = if_nametoindex (t->orig_name);
258 	if (id == 0)
259 	{
260 		syslog (LOG_ERR, _("Tunneling driver error (%s): %m"),
261 		        t->orig_name);
262 		goto error;
263 	}
264 
265 # ifdef TUNSIFMODE
266 	/* Sets sensible tunnel type (broadcast rather than point-to-point) */
267 	(void)ioctl (fd, TUNSIFMODE, &(int){ IFF_BROADCAST });
268 # endif
269 
270 # if defined (TUNSIFHEAD)
271 	/* Enables TUNSIFHEAD */
272 	if (ioctl (fd, TUNSIFHEAD, &(int){ 1 }))
273 	{
274 		syslog (LOG_ERR, _("Tunneling driver error (%s): %m"),
275 		        "TUNSIFHEAD");
276 #  if defined (__APPLE__)
277 		if (errno == EINVAL)
278 			syslog (LOG_NOTICE,
279 			        "*** Ignoring tun-tap-osx spurious error ***");
280 		else
281 #  endif
282 		goto error;
283 	}
284 # elif defined (TUNSLMODE)
285 	/* Disables TUNSLMODE (deprecated opposite of TUNSIFHEAD) */
286 	if (ioctl (fd, TUNSLMODE, &(int){ 0 }))
287 	{
288 		syslog (LOG_ERR, _("Tunneling driver error (%s): %m"),
289 		        "TUNSLMODE");
290 		goto error;
291 	}
292 #endif
293 
294 	/* Customizes interface name */
295 	if (req_name != NULL)
296 	{
297 		struct ifreq req;
298 		memset (&req, 0, sizeof (req));
299 
300 		if (if_indextoname (id, req.ifr_name) == NULL)
301 		{
302 			syslog (LOG_ERR, _("Tunneling driver error (%s): %m"),
303 			        "if_indextoname");
304 			goto error;
305 		}
306 		else
307 		if (strcmp (req.ifr_name, req_name))
308 		{
309 #ifdef SIOCSIFNAME
310 			char ifname[IFNAMSIZ];
311 			req.ifr_data = ifname;
312 
313 			errno = ENAMETOOLONG;
314 			if (safe_strcpy (ifname, req_name)
315 			 || ioctl (reqfd, SIOCSIFNAME, &req))
316 #else
317 			syslog (LOG_DEBUG,
318 "Tunnel interface renaming is not supported on your operating system.\n"
319 "To run miredo properly, you need to remove the InterfaceName directive\n"
320 "from its configuration file.\n");
321 			errno = ENOSYS;
322 #endif
323 			{
324 				syslog (LOG_ERR, _("Tunneling driver error (%s): %m"),
325 				        "SIOCSIFNAME");
326 				goto error;
327 			}
328 		}
329 	}
330 #else
331 # error No tunneling driver implemented on your platform!
332 #endif /* HAVE_os */
333 
334 	fcntl (fd, F_SETFD, FD_CLOEXEC);
335 	/*int val = fcntl (fd, F_GETFL);
336 	fcntl (fd, F_SETFL, ((val != -1) ? val : 0) | O_NONBLOCK);*/
337 
338 	t->id = id;
339 	t->fd = fd;
340 	return t;
341 
342 error:
343 	(void)close (reqfd);
344 	if (fd != -1)
345 		(void)close (fd);
346 	syslog (LOG_ERR, _("%s tunneling interface creation failure"), os_driver);
347 	free (t);
348 	return NULL;
349 }
350 
351 
352 /**
353  * Removes a tunnel from the kernel.
354  * BEWARE: if you fork, child processes must call tun6_destroy() too.
355  *
356  * The kernel will destroy the tunnel interface once all processes called
357  * tun6_destroy and/or were terminated.
358  */
tun6_destroy(tun6 * t)359 void tun6_destroy (tun6* t)
360 {
361 	assert (t != NULL);
362 	assert (t->fd != -1);
363 	assert (t->reqfd != -1);
364 	assert (t->id != 0);
365 
366 	(void)tun6_setState (t, false);
367 
368 #ifdef USE_BSD
369 # ifdef SIOCSIFNAME
370 	/*
371 	 * SIOCSIFDESTROY doesn't work for tunnels (see FreeBSD PR/73673).
372 	 * We rename the tunnel to its canonical name to ease the life of other
373 	 * programs that may re-open the tunnel after us.
374 	 */
375 	struct ifreq req;
376 	memset (&req, 0, sizeof (req));
377 	if (if_indextoname (t->id, req.ifr_name) != NULL)
378 	{
379 		if (ioctl (t->reqfd, SIOCIFDESTROY, &req))
380 		{
381 			if ((if_indextoname (t->id, req.ifr_name) != NULL)
382 			 && strcmp (t->orig_name, req.ifr_name))
383 			{
384 				req.ifr_data = t->orig_name;
385 				(void)ioctl (t->reqfd, SIOCSIFNAME, &req);
386 			}
387 		}
388 	}
389 # endif
390 #endif
391 
392 	(void)close (t->fd);
393 	(void)close (t->reqfd);
394 	free (t);
395 }
396 
397 
398 /*
399  * Unless otherwise stated, all the methods thereafter should return -1 on
400  * error, and 0 on success. Similarly, they should require root privileges.
401  */
402 
403 /**
404  * @return the scope id of the tunnel device
405  */
tun6_getId(const tun6 * t)406 int tun6_getId (const tun6 *t)
407 {
408 	assert (t != NULL);
409 	assert (t-> id != 0);
410 
411 	return t->id;
412 }
413 
414 
415 #if defined (USE_LINUX)
416 static int
proc_write_zero(const char * path)417 proc_write_zero (const char *path)
418 {
419 	int fd = open (path, O_WRONLY);
420 	if (fd == -1)
421 		return -1;
422 
423 	int retval = 0;
424 
425 	if (write (fd, "0", 1) != 1)
426 		retval = -1;
427 	if (close (fd))
428 		retval = -1;
429 
430 	return retval;
431 }
432 #endif
433 
434 
435 /**
436  * Brings a tunnel interface up or down.
437  *
438  * @return 0 on success, -1 on error (see errno).
439  */
440 int
tun6_setState(tun6 * t,bool up)441 tun6_setState (tun6 *t, bool up)
442 {
443 	assert (t != NULL);
444 	assert (t-> id != 0);
445 
446 	struct ifreq req;
447 	memset (&req, 0, sizeof (req));
448 	if ((if_indextoname (t->id, req.ifr_name) == NULL)
449 	 || ioctl (t->reqfd, SIOCGIFFLAGS, &req))
450 		return -1;
451 
452 	/* settings we want/don't want: */
453 	req.ifr_flags |= IFF_NOARP;
454 	req.ifr_flags &= ~(IFF_MULTICAST | IFF_BROADCAST);
455 	if (up)
456 		req.ifr_flags |= IFF_UP | IFF_RUNNING;
457 	else
458 		req.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
459 
460 	/* Sets up the interface */
461 	if ((if_indextoname (t->id, req.ifr_name) == NULL)
462 	 || ioctl (t->reqfd, SIOCSIFFLAGS, &req))
463 		return -1;
464 
465 	return 0;
466 }
467 
468 
469 #if defined (USE_BSD)
470 /**
471  * Converts a prefix length to a netmask (used for the BSD routing)
472  */
473 static void
plen_to_mask(unsigned plen,struct in6_addr * mask)474 plen_to_mask (unsigned plen, struct in6_addr *mask)
475 {
476 	assert (plen <= 128);
477 
478 	div_t d = div (plen, 8);
479 	int i = 0;
480 
481 	while (i < d.quot)
482 		mask->s6_addr[i++] = 0xff;
483 
484 	if (d.rem)
485 		mask->s6_addr[i++] = 0xff << (8 - d.rem);
486 
487 	while (i < 16)
488 		mask->s6_addr[i++] = 0;
489 }
490 
491 
492 static void
plen_to_sin6(unsigned plen,struct sockaddr_in6 * sin6)493 plen_to_sin6 (unsigned plen, struct sockaddr_in6 *sin6)
494 {
495 	memset (sin6, 0, sizeof (struct sockaddr_in6));
496 
497 	sin6->sin6_family = AF_INET6;
498 # ifdef HAVE_SA_LEN
499 	sin6->sin6_len = sizeof (struct sockaddr_in6);
500 # endif
501 	plen_to_mask (plen, &sin6->sin6_addr);
502 }
503 #endif /* ifdef SOCAIFADDR_IN6 */
504 
505 
506 static int
_iface_addr(int reqfd,int id,bool add,const struct in6_addr * addr,unsigned prefix_len)507 _iface_addr (int reqfd, int id, bool add,
508              const struct in6_addr *addr, unsigned prefix_len)
509 {
510 	void *req = NULL;
511 	long cmd = 0;
512 
513 	assert (reqfd != -1);
514 	assert (id != 0);
515 
516 	if ((prefix_len > 128) || (addr == NULL))
517 		return -1;
518 
519 #if defined (USE_LINUX)
520 	/*
521 	 * Linux ioctl interface
522 	 */
523 	union
524 	{
525 		struct in6_ifreq req6;
526 		struct ifreq req;
527 	} r;
528 
529 	memset (&r, 0, sizeof (r));
530 	r.req6.ifr6_ifindex = id;
531 	memcpy (&r.req6.ifr6_addr, addr, sizeof (r.req6.ifr6_addr));
532 	r.req6.ifr6_prefixlen = prefix_len;
533 
534 	cmd = add ? SIOCSIFADDR : SIOCDIFADDR;
535 	req = &r;
536 #elif defined (USE_BSD)
537 	/*
538 	 * BSD ioctl interface
539 	 */
540 	union
541 	{
542 		struct in6_aliasreq addreq6;
543 		struct in6_ifreq delreq6;
544 	} r;
545 
546 	if (add)
547 	{
548 		memset (&r.addreq6, 0, sizeof (r.addreq6));
549 		if (if_indextoname (id, r.addreq6.ifra_name) == NULL)
550 			return -1;
551 		r.addreq6.ifra_addr.sin6_family = AF_INET6;
552 		r.addreq6.ifra_addr.sin6_len = sizeof (r.addreq6.ifra_addr);
553 		memcpy (&r.addreq6.ifra_addr.sin6_addr, addr,
554 		        sizeof (r.addreq6.ifra_addr.sin6_addr));
555 
556 		plen_to_sin6 (prefix_len, &r.addreq6.ifra_prefixmask);
557 
558 		r.addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
559 		r.addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
560 
561 		cmd = SIOCAIFADDR_IN6;
562 		req = &r.addreq6;
563 	}
564 	else
565 	{
566 		memset (&r.delreq6, 0, sizeof (r.delreq6));
567 		if (if_indextoname (id, r.delreq6.ifr_name) == NULL)
568 			return -1;
569 		r.delreq6.ifr_addr.sin6_family = AF_INET6;
570 		r.delreq6.ifr_addr.sin6_len = sizeof (r.delreq6.ifr_addr);
571 		memcpy (&r.delreq6.ifr_addr.sin6_addr, addr,
572 		        sizeof (r.delreq6.ifr_addr.sin6_addr));
573 
574 		cmd = SIOCDIFADDR_IN6;
575 		req = &r.delreq6;
576 	}
577 #else
578 # error FIXME tunnel address setup not implemented
579 #endif
580 
581 	return ioctl (reqfd, cmd, req) >= 0 ? 0 : -1;
582 }
583 
584 
585 static int
_iface_route(int reqfd,int id,bool add,const struct in6_addr * addr,unsigned prefix_len,int rel_metric)586 _iface_route (int reqfd, int id, bool add, const struct in6_addr *addr,
587               unsigned prefix_len, int rel_metric)
588 {
589 	assert (reqfd != -1);
590 	assert (id != 0);
591 
592 	if ((prefix_len > 128) || (addr == NULL))
593 		return -1;
594 
595 	int retval = -1;
596 
597 #if defined (USE_LINUX)
598 	/*
599 	 * Linux ioctl interface
600 	 */
601 	struct in6_rtmsg req6 =
602 	{
603 		.rtmsg_flags = RTF_UP,
604 		.rtmsg_ifindex = id,
605 		.rtmsg_dst_len = (unsigned short)prefix_len,
606 		/* By default, the Linux kernel's metric is 256 for subnets,
607 		 * and 1024 for gatewayed route. */
608 		.rtmsg_metric = 1024 + rel_metric
609 	};
610 
611 	/* Adds/deletes route */
612 	memcpy (&req6.rtmsg_dst, addr, sizeof (req6.rtmsg_dst));
613 	if (prefix_len == 128)
614 		req6.rtmsg_flags |= RTF_HOST;
615 	/* no gateway */
616 
617 	if (ioctl (reqfd, add ? SIOCADDRT : SIOCDELRT, &req6) == 0)
618 		retval = 0;
619 #elif defined (USE_BSD)
620 	/*
621 	 * BSD routing socket interface
622 	 * FIXME: metric unimplemented
623 	 */
624 	(void)rel_metric;
625 
626 	int s = socket (AF_ROUTE, SOCK_RAW, AF_INET6);
627 	if (s == -1)
628 	{
629 		syslog (LOG_ERR, _("Error (%s): %m"), "socket (AF_ROUTE)");
630 		return -1;
631 	}
632 
633 	static int rtm_seq = 0;
634 	static pthread_mutex_t rtm_seq_mutex = PTHREAD_MUTEX_INITIALIZER;
635 	struct
636 	{
637 		struct rt_msghdr hdr;
638 		struct sockaddr_in6 dst;
639 		struct sockaddr_storage gw;
640 		struct sockaddr_storage dummy; /* allocate space for netmask */
641 	} msg;
642 
643 	shutdown (s, 0);
644 
645 	memset (&msg, 0, sizeof (msg));
646 	msg.hdr.rtm_msglen = sizeof (msg);
647 	msg.hdr.rtm_version = RTM_VERSION;
648 	msg.hdr.rtm_type = add ? RTM_ADD : RTM_DELETE;
649 	msg.hdr.rtm_index = id;
650 	msg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
651 	msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
652 	if (prefix_len == 128)
653 		msg.hdr.rtm_flags |= RTF_HOST;
654 	msg.hdr.rtm_pid = getpid ();
655 
656 	pthread_mutex_lock (&rtm_seq_mutex);
657 	msg.hdr.rtm_seq = ++rtm_seq;
658 	pthread_mutex_unlock (&rtm_seq_mutex);
659 
660 	msg.dst.sin6_family = AF_INET6;
661 	msg.dst.sin6_len = sizeof (msg.dst);
662 	memcpy (&msg.dst.sin6_addr, addr, sizeof (msg.dst.sin6_addr));
663 
664 	struct ifaddrs *ifap, *ifa;
665 	struct sockaddr_dl *sdl = NULL;
666 
667 	if (getifaddrs(&ifap))
668 	{
669 		syslog (LOG_ERR, _("Error (%s): %m"), "getifaddrs");
670 		return -1;
671 	}
672 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
673 		if (ifa->ifa_addr == NULL)
674 			continue;
675 		if (ifa->ifa_addr->sa_family != AF_LINK)
676 			continue;
677 		if (id == ((struct sockaddr_dl *)ifa->ifa_addr)->sdl_index)
678 			sdl = (struct sockaddr_dl *)ifa->ifa_addr;
679 	}
680 	if (sdl == NULL) {
681 		syslog (LOG_ERR, "no sdl found");
682 		freeifaddrs(ifap);
683 		return -1;
684 	}
685 	memcpy(&msg.gw, sdl, sdl->sdl_len);
686 	freeifaddrs(ifap);
687 
688 	struct sockaddr_in6 *mask = (struct sockaddr_in6 *)((u_char *)&msg.gw + sdl->sdl_len);
689 	plen_to_sin6 (prefix_len, mask);
690 
691 	errno = 0;
692 
693 	if ((write (s, &msg, sizeof (msg)) == sizeof (msg))
694 	 && (errno == 0))
695 		retval = 0;
696     	else if (errno == EEXIST)
697 		syslog (LOG_NOTICE,
698 "Miredo could not configure its network tunnel device properly.\n"
699 "There is probably another tunnel with a conflicting route present\n"
700 "(see also FreeBSD PR kern/100080).\n"
701 "Please upgrade to FreeBSD 6.3 or more recent to fix this.\n");
702 	else
703 		syslog (LOG_NOTICE, "Error creating a route: %m");
704 
705 	(void)close (s);
706 #else
707 # error FIXME route setup not implemented
708 #endif
709 
710 	return retval;
711 }
712 
713 
714 /**
715  * Adds an address with a netmask to a tunnel.
716  * Requires CAP_NET_ADMIN or root privileges.
717  *
718  * @return 0 on success, -1 in case error.
719  */
720 int
tun6_addAddress(tun6 * t,const struct in6_addr * addr,unsigned prefixlen)721 tun6_addAddress (tun6 *t, const struct in6_addr *addr, unsigned prefixlen)
722 {
723 	assert (t != NULL);
724 
725 	int res = _iface_addr (t->reqfd, t->id, true, addr, prefixlen);
726 
727 #if defined (USE_LINUX)
728 	char ifname[IFNAMSIZ];
729 	if ((res == 0)
730 	 && (if_indextoname (t->id, ifname) != NULL))
731 	{
732 
733 		char proc_path[24 + IFNAMSIZ + 16 + 1] = "/proc/sys/net/ipv6/conf/";
734 # if 0
735 		/* Disable Autoconfiguration */
736 		snprintf (proc_path + 24, sizeof (proc_path) - 24,
737 		          "%s/accept_ra", ifname);
738 		proc_write_zero (proc_path);
739 
740 		snprintf (proc_path + 24, sizeof (proc_path) - 24,
741 		          "%s/autoconf", ifname);
742 		proc_write_zero (proc_path);
743 #endif
744 		/* Disable ICMPv6 Redirects. */
745 		snprintf (proc_path + 24, sizeof (proc_path) - 24,
746 		          "%s/accept_redirects", ifname);
747 		proc_write_zero (proc_path);
748 
749 	}
750 #endif
751 
752 	return res;
753 }
754 
755 /**
756  * Deletes an address from a tunnel.
757  * Requires CAP_NET_ADMIN or root privileges.
758  *
759  * @return 0 on success, -1 in case error.
760  */
761 int
tun6_delAddress(tun6 * t,const struct in6_addr * addr,unsigned prefixlen)762 tun6_delAddress (tun6 *t, const struct in6_addr *addr, unsigned prefixlen)
763 {
764 	assert (t != NULL);
765 
766 	return _iface_addr (t->reqfd, t->id, false, addr, prefixlen);
767 }
768 
769 
770 /**
771  * Inserts a route through a tunnel into the IPv6 routing table.
772  * Requires CAP_NET_ADMIN or root privileges.
773  *
774  * @param rel_metric difference between the system's default metric
775  * for route with the speficied prefix length (positive = higher priority,
776  * negative = lower priority).
777  *
778  * @return 0 on success, -1 in case error.
779  */
780 int
tun6_addRoute(tun6 * t,const struct in6_addr * addr,unsigned prefix_len,int rel_metric)781 tun6_addRoute (tun6 *t, const struct in6_addr *addr, unsigned prefix_len,
782                int rel_metric)
783 {
784 	assert (t != NULL);
785 
786 	return _iface_route (t->reqfd, t->id, true, addr, prefix_len, rel_metric);
787 }
788 
789 
790 /**
791  * Removes a route through a tunnel from the IPv6 routing table.
792  * Requires CAP_NET_ADMIN or root privileges.
793  *
794  * @return 0 on success, -1 in case error.
795  */
796 int
tun6_delRoute(tun6 * t,const struct in6_addr * addr,unsigned prefix_len,int rel_metric)797 tun6_delRoute (tun6 *t, const struct in6_addr *addr, unsigned prefix_len,
798                int rel_metric)
799 {
800 	assert (t != NULL);
801 
802 	return _iface_route (t->reqfd, t->id, false, addr, prefix_len,
803 	                     rel_metric);
804 }
805 
806 
807 /**
808  * Defines the tunnel interface Max Transmission Unit (bytes).
809  *
810  * @return 0 on success, -1 in case of error.
811  */
812 int
tun6_setMTU(tun6 * t,unsigned mtu)813 tun6_setMTU (tun6 *t, unsigned mtu)
814 {
815 	assert (t != NULL);
816 
817 	if ((mtu < 1280) || (mtu > 65535))
818 		return -1;
819 
820 	struct ifreq req =
821 	{
822 		.ifr_mtu = mtu
823 	};
824 	if (if_indextoname (t->id, req.ifr_name) == NULL)
825 		return -1;
826 
827 	return ioctl (t->reqfd, SIOCSIFMTU, &req) ? -1 : 0;
828 }
829 
830 
831 /**
832  * Registers file descriptors in an fd_set for use with select().
833  * If any of the file descriptors is out of range (>= FD_SETSIZE), it
834  * will not be registered.
835  *
836  * @param readset a fd_set (with FD_SETSIZE no smaller than the default
837  * libc value libtun6 was compiled with).
838  *
839  * @return the "biggest" file descriptor registered (useful as the
840  * first parameter to select()). -1 if any of the file descriptors was
841  * bigger than FD_SETSIZE - 1.
842  */
843 int
tun6_registerReadSet(const tun6 * t,fd_set * readset)844 tun6_registerReadSet (const tun6 *t, fd_set *readset)
845 {
846 	assert (t != NULL);
847 
848 	if (t->fd >= (int)FD_SETSIZE)
849 		return -1;
850 
851 	FD_SET (t->fd, readset);
852 	return t->fd;
853 }
854 
855 
856 /**
857  * Receives a packet from a tunnel device.
858  * @param buffer address to store packet
859  * @param maxlen buffer length in bytes (should be 65535)
860  *
861  * This function will block if there is no input.
862  *
863  * @return the packet length on success, -1 if no packet were to be received.
864  */
865 static inline int
tun6_recv_inner(int fd,void * buffer,size_t maxlen)866 tun6_recv_inner (int fd, void *buffer, size_t maxlen)
867 {
868 	struct iovec vect[2];
869 	tun_head_t head;
870 
871 	vect[0].iov_base = (char *)&head;
872 	vect[0].iov_len = sizeof (head);
873 	vect[1].iov_base = (char *)buffer;
874 	vect[1].iov_len = maxlen;
875 
876 	int len = readv (fd, vect, 2);
877 	if ((len < (int)sizeof (head))
878 	 || !tun_head_is_ipv6 (head))
879 		return -1; /* only accept IPv6 packets */
880 
881 	return len - sizeof (head);
882 }
883 
884 
885 /**
886  * Checks an fd_set, and receives a packet if available.
887  * @param buffer address to store packet
888  * @param maxlen buffer length in bytes (should be 65535)
889  *
890  * This function will not block if there is no input.
891  * Use tun6_wait_recv() if you want to wait until a packet arrives.
892  *
893  * @return the packet length on success, -1 if no packet were to be received.
894  */
895 int
tun6_recv(tun6 * t,const fd_set * readset,void * buffer,size_t maxlen)896 tun6_recv (tun6 *t, const fd_set *readset, void *buffer, size_t maxlen)
897 {
898 	assert (t != NULL);
899 
900 	int fd = t->fd;
901 	if ((fd < (int)FD_SETSIZE) && !FD_ISSET (fd, readset))
902 	{
903 		errno = EAGAIN;
904 		return -1;
905 	}
906 	return tun6_recv_inner (fd, buffer, maxlen);
907 }
908 
909 
910 /**
911  * Waits for a packet, and receives it.
912  * @param buffer address to store packet
913  * @param maxlen buffer length in bytes (should be 65535)
914  *
915  * This function will block until a packet arrives or an error occurs.
916  *
917  * @return the packet length on success, -1 if no packet were to be received.
918  */
919 int
tun6_wait_recv(tun6 * t,void * buffer,size_t maxlen)920 tun6_wait_recv (tun6 *t, void *buffer, size_t maxlen)
921 {
922 	return tun6_recv_inner (t->fd, buffer, maxlen);
923 }
924 
925 
926 /**
927  * Sends an IPv6 packet.
928  * @param packet pointer to packet
929  * @param len packet length (bytes)
930  *
931  * @return the number of bytes succesfully transmitted on success,
932  * -1 on error.
933  */
934 int
tun6_send(tun6 * t,const void * packet,size_t len)935 tun6_send (tun6 *t, const void *packet, size_t len)
936 {
937 	assert (t != NULL);
938 
939 	if (len > 65535)
940 		return -1;
941 
942 	tun_head_t head = TUN_HEAD_IPV6_INITIALIZER;
943 	struct iovec vect[2];
944 	vect[0].iov_base = (char *)&head;
945 	vect[0].iov_len = sizeof (head);
946 	vect[1].iov_base = (char *)packet; /* necessary cast to non-const */
947 	vect[1].iov_len = len;
948 
949 	int val = writev (t->fd, vect, 2);
950 	if (val == -1)
951 		return -1;
952 
953 	val -= sizeof (head);
954 	if (val < 0)
955 		return -1;
956 
957 	return val;
958 }
959 
960