1 /*
2  * relayd.c - Miredo: binding between libtun6 and libteredo
3  */
4 
5 /***********************************************************************
6  *  Copyright © 2004-2007 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 <assert.h>
27 #include <gettext.h>
28 
29 #include <inttypes.h>
30 #include <stdlib.h> // free()
31 #include <stdio.h> // fputs()
32 #include <sys/types.h>
33 #include <string.h> // strcasecmp()
34 #include <errno.h>
35 #include <unistd.h> // close()
36 #include <fcntl.h>
37 #include <sys/wait.h> // wait()
38 #include <signal.h> // sigemptyset()
39 #include <syslog.h>
40 #include <pthread.h>
41 
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <netinet/ip6.h>
45 #include <netinet/icmp6.h>
46 #include <arpa/inet.h> // inet_ntop()
47 #include <netdb.h> // NI_MAXHOST
48 #ifdef HAVE_SYS_CAPABILITY_H
49 # include <sys/capability.h>
50 #endif
51 #ifndef SOL_IPV6
52 # define SOL_IPV6 IPPROTO_IPV6
53 #endif
54 #ifndef SOL_ICMPV6
55 # define SOL_ICMPV6 IPPROTO_ICMPV6
56 #endif
57 #ifndef PF_LOCAL
58 # define PF_LOCAL PF_UNIX
59 #endif
60 
61 #include <libtun6/tun6.h>
62 
63 #include <libteredo/teredo.h>
64 #include <libteredo/tunnel.h>
65 
66 #include "privproc.h"
67 #include "miredo.h"
68 #include "conf.h"
69 
70 static void miredo_setup_fd (int fd);
71 static void miredo_setup_nonblock_fd (int fd);
72 
relay_diagnose(void)73 static int relay_diagnose (void)
74 {
75 	char errbuf[LIBTUN6_ERRBUF_SIZE];
76 	if (tun6_driver_diagnose (errbuf))
77 	{
78 		fputs (errbuf, stderr);
79 		return -1;
80 	}
81 
82 	return 0;
83 }
84 
85 
86 typedef struct miredo_tunnel
87 {
88 	tun6 *tunnel;
89 	int priv_fd;
90 	teredo_tunnel *relay;
91 } miredo_tunnel;
92 
93 static int icmp6_fd = -1;
94 
miredo_init(bool client)95 static int miredo_init (bool client)
96 {
97 	if (teredo_startup (client))
98 		return -1;
99 
100 	assert (icmp6_fd == -1);
101 
102 	icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
103 	if (icmp6_fd == -1)
104 		return -1;
105 
106 	miredo_setup_nonblock_fd (icmp6_fd);
107 
108 	setsockopt (icmp6_fd, SOL_IPV6, IPV6_CHECKSUM, &(int){2}, sizeof (int));
109 
110 	/* We don't use the socket for receive -> block all */
111 	struct icmp6_filter filt;
112 	ICMP6_FILTER_SETBLOCKALL (&filt);
113 	setsockopt (icmp6_fd, SOL_ICMPV6, ICMP6_FILTER, &filt, sizeof (filt));
114 	return 0;
115 }
116 
117 
miredo_deinit(bool client)118 static void miredo_deinit (bool client)
119 {
120 	assert (icmp6_fd != -1);
121 	close (icmp6_fd);
122 	teredo_cleanup (client);
123 }
124 
125 
126 /**
127  * Callback to transmit decapsulated Teredo IPv6 packets to the kernel.
128  */
129 static void
miredo_recv_callback(void * data,const void * packet,size_t length)130 miredo_recv_callback (void *data, const void *packet, size_t length)
131 {
132 	assert (data != NULL);
133 
134 	(void)tun6_send (((miredo_tunnel *)data)->tunnel, packet, length);
135 }
136 
137 
138 /**
139  * Callback to emit an ICMPv6 error message through a raw ICMPv6 socket.
140  */
141 static void
miredo_icmp6_callback(void * data,const void * packet,size_t length,const struct in6_addr * dst)142 miredo_icmp6_callback (void *data, const void *packet, size_t length,
143                         const struct in6_addr *dst)
144 {
145 	(void)data;
146 	assert (icmp6_fd != -1);
147 
148 	struct sockaddr_in6 addr =
149 	{
150 		.sin6_family = AF_INET6,
151 #ifdef HAVE_SA_LEN
152 		.sin6_len = sizeof (struct sockaddr_in6),
153 #endif
154 		.sin6_addr = *dst
155 	};
156 
157 	/* TODO: use sendmsg and don't memcpy in BuildICMPv6Error */
158 	(void)sendto (icmp6_fd, packet, length, 0,
159 	              (struct sockaddr *)&addr, sizeof (addr));
160 }
161 
162 
163 #define TEREDO_CONE     0
164 #define TEREDO_RESTRICT 1
165 #define TEREDO_CLIENT   2
166 
167 static bool
ParseRelayType(miredo_conf * conf,const char * name,int * type)168 ParseRelayType (miredo_conf *conf, const char *name, int *type)
169 {
170 	unsigned line;
171 	char *val = miredo_conf_get (conf, name, &line);
172 
173 	if (val == NULL)
174 		return true;
175 
176 	if ((strcasecmp (val, "client") == 0)
177 	 || (strcasecmp (val, "autoclient") == 0))
178 		*type = TEREDO_CLIENT;
179 	else
180 	if (strcasecmp (val, "restricted") == 0)
181 	{
182 		syslog (LOG_WARNING, _("Using deprecated \"restricted\" relay type "
183 		        "which is STRONGLY DISCOURAGED (at line %u)."), line);
184 		*type = TEREDO_RESTRICT;
185 	}
186 	else
187 	if ((strcasecmp (val, "relay") == 0)
188 	 || (strcasecmp (val, "cone") == 0))
189 		*type = TEREDO_CONE;
190 	else
191 	{
192 		syslog (LOG_ERR, _("Invalid relay type \"%s\" at line %u"),
193 		        val, line);
194 		free (val);
195 		return false;
196 	}
197 	free (val);
198 	return true;
199 }
200 
201 
202 #ifdef MIREDO_TEREDO_CLIENT
203 static tun6 *
create_dynamic_tunnel(const char * ifname,int * pfd)204 create_dynamic_tunnel (const char *ifname, int *pfd)
205 {
206 	tun6 *tunnel = tun6_create (ifname);
207 	if (tunnel == NULL)
208 		return NULL;
209 
210 	int fd[2];
211 	if (socketpair (PF_LOCAL, SOCK_STREAM, 0, fd))
212 		goto error;
213 
214 	miredo_setup_fd (fd[0]);
215 	miredo_setup_fd (fd[1]);
216 
217 	char ifindex[2 * sizeof (unsigned) + 1];
218 	snprintf (ifindex, sizeof (ifindex), "%X", tun6_getId (tunnel));
219 
220 	static const char path[] = PKGLIBEXECDIR"/miredo-privproc";
221 	switch (fork ())
222 	{
223 		case -1:
224 			close (fd[0]);
225 			close (fd[1]);
226 			goto error;
227 
228 		case 0:
229 			if (dup2 (fd[0], 0) == 0 && dup2 (fd[0], 1) == 1)
230 				execl (path, path, ifindex, (char *)NULL);
231 
232 			syslog (LOG_ERR, _("Could not execute %s: %m"), path);
233 			exit (1);
234 	}
235 	close (fd[0]);
236 	*pfd = fd[1];
237 	return tunnel;
238 error:
239 	tun6_destroy (tunnel);
240 	return NULL;
241 }
242 
243 
244 static int
configure_tunnel(int fd,const struct in6_addr * addr,unsigned mtu)245 configure_tunnel (int fd, const struct in6_addr *addr, unsigned mtu)
246 {
247 	struct miredo_tunnel_settings s;
248 	int res;
249 
250 	if (mtu > 65535)
251 	{
252 		errno = EINVAL;
253 		return -1;
254 	}
255 
256 	memset (&s, 0, sizeof (s));
257 	memcpy (&s.addr, addr, sizeof (s.addr));
258 	s.mtu = (uint16_t)mtu;
259 
260 	if ((send (fd, &s, sizeof (s), MSG_NOSIGNAL) != sizeof (s))
261 	 || (recv (fd, &res, sizeof (res), MSG_WAITALL) != sizeof (res)))
262 		return -1;
263 
264 	return res;
265 }
266 
267 
268 static void
destroy_dynamic_tunnel(tun6 * tunnel,int fd)269 destroy_dynamic_tunnel (tun6 *tunnel, int fd)
270 {
271 	assert (fd != -1);
272 	close (fd);
273 
274 	wait (NULL); // wait for privsep process
275 
276 	tun6_destroy (tunnel);
277 }
278 
279 
280 /**
281  * Callback to configure a Teredo tunneling interface.
282  */
283 static void
miredo_up_callback(void * data,const struct in6_addr * addr,uint16_t mtu)284 miredo_up_callback (void *data, const struct in6_addr *addr, uint16_t mtu)
285 {
286 	char str[INET6_ADDRSTRLEN];
287 
288 	syslog (LOG_NOTICE, _("Teredo pseudo-tunnel started"));
289 	if (inet_ntop (AF_INET6, addr, str, sizeof (str)) != NULL)
290 		syslog (LOG_INFO, _(" (address: %s, MTU: %"PRIu16")"),
291 		        str, mtu);
292 
293 	assert (data != NULL);
294 
295 	configure_tunnel (((miredo_tunnel *)data)->priv_fd, addr, mtu);
296 }
297 
298 
299 /**
300  * Callback to deconfigure a Teredo tunneling interface.
301  */
302 static void
miredo_down_callback(void * data)303 miredo_down_callback (void *data)
304 {
305 	assert (data != NULL);
306 
307 	configure_tunnel (((miredo_tunnel *)data)->priv_fd, &in6addr_any,
308 	                         1280);
309 	syslog (LOG_NOTICE, _("Teredo pseudo-tunnel stopped"));
310 }
311 
312 
313 static int
setup_client(teredo_tunnel * client,const char * server,const char * server2)314 setup_client (teredo_tunnel *client, const char *server, const char *server2)
315 {
316 	teredo_set_state_cb (client, miredo_up_callback, miredo_down_callback);
317 	return teredo_set_client_mode (client, server, server2);
318 }
319 #else
320 # define create_dynamic_tunnel( a, b )   NULL
321 # define destroy_dynamic_tunnel( a, b )   (void)0
322 # define setup_client( a, b, c )         (-1)
323 #endif
324 
325 
326 static tun6 *
create_static_tunnel(const char * restrict ifname,const struct in6_addr * restrict prefix,uint16_t mtu)327 create_static_tunnel (const char *restrict ifname,
328                       const struct in6_addr *restrict prefix,
329                       uint16_t mtu)
330 {
331 	tun6 *tunnel = tun6_create (ifname);
332 
333 	if ((tunnel == NULL) && (ifname != NULL) && (errno == ENOSYS))
334 		tunnel = tun6_create (NULL);
335 	if (tunnel == NULL)
336 		return NULL;
337 
338 	if (tun6_setMTU (tunnel, mtu) || tun6_bringUp (tunnel)
339 	 || tun6_addAddress (tunnel, &teredo_restrict, 64)
340 	 || tun6_addRoute (tunnel, prefix, 32, 0))
341 	{
342 		tun6_destroy (tunnel);
343 		return NULL;
344 	}
345 	return tunnel;
346 }
347 
348 
349 #if 0 && !defined (MIREDO_DEFAULT_USERNAME)
350 static void
351 destroy_static_tunnel (tun6 *restrict tunnel,
352                        const struct in6_addr *restrict prefix)
353 {
354 	/*
355 	 * Manual clean up of the tunnel device is only possible if we retain root
356 	 * privileges. Unfortunately, if we don't do this, it becomes impossible
357 	 * to restart Miredo on FreeBSD. The proper fix belongs in the FreeBSD
358 	 * kernel - that's the only way to handle kills (or would-be crashes) of
359 	 * Miredo; that's part of the standard job of a solid kernel process
360 	 * killer.
361 	 */
362 	tun6_delRoute (tunnel, prefix, 32, 0);
363 	tun6_delAddress (tunnel, &teredo_restrict, 64);
364 	tun6_bringDown (tunnel);
365 	tun6_destroy (tunnel);
366 }
367 #else
368 # define destroy_static_tunnel( t, p ) tun6_destroy( t )
369 #endif
370 
371 
372 static int
setup_relay(teredo_tunnel * relay,uint32_t prefix,bool cone)373 setup_relay (teredo_tunnel *relay, uint32_t prefix, bool cone)
374 {
375 	teredo_set_prefix (relay, prefix);
376 	teredo_set_cone_flag (relay, cone);
377 	return teredo_set_relay_mode (relay);
378 }
379 
380 
381 /**
382  * Thread to encapsulate IPv6 packets into UDP.
383  * Cancellation safe.
384  */
miredo_encap_thread(void * d)385 static LIBTEREDO_NORETURN void *miredo_encap_thread (void *d)
386 {
387 	teredo_tunnel *relay = ((miredo_tunnel *)d)->relay;
388 	tun6 *tunnel = ((miredo_tunnel *)d)->tunnel;
389 
390 	for (;;)
391 	{
392 		/* Handle incoming data */
393 		struct
394 		{
395 			struct ip6_hdr ip6;
396 			uint8_t fill[65467];
397 		} pbuf;
398 
399 		/* Forwards IPv6 packet to Teredo
400 		 * (Packet transmission) */
401 		int val = tun6_wait_recv (tunnel, &pbuf.ip6, sizeof (pbuf));
402 		if (val >= 40)
403 		{
404 			pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
405 			teredo_transmit (relay, &pbuf.ip6, val);
406 			pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
407 		}
408 		else
409 			pthread_testcancel ();
410 	}
411 }
412 
413 
414 /**
415  * Miredo main daemon function, with UDP datagrams and IPv6 packets
416  * receive loop.
417  */
418 static int
run_tunnel(miredo_tunnel * tunnel)419 run_tunnel (miredo_tunnel *tunnel)
420 {
421 	pthread_t encap_th;
422 	if (teredo_run_async (tunnel->relay)
423 	 || pthread_create (&encap_th, NULL, miredo_encap_thread, tunnel))
424 		return -1;
425 
426 	sigset_t dummyset, set;
427 	sigemptyset (&dummyset);
428 	pthread_sigmask (SIG_BLOCK, &dummyset, &set);
429 	while (sigwait (&set, &(int){ 0 }));
430 
431 	pthread_cancel (encap_th);
432 	pthread_join (encap_th, NULL);
433 	return 0;
434 }
435 
436 
437 static int
relay_run(miredo_conf * conf,const char * server_name)438 relay_run (miredo_conf *conf, const char *server_name)
439 {
440 	/*
441 	 * CONFIGURATION
442 	 */
443 	union teredo_addr prefix;
444 	memset (&prefix, 0, sizeof (prefix));
445 	prefix.teredo.prefix = htonl (TEREDO_PREFIX);
446 
447 	int mode = TEREDO_CLIENT;
448 	if (!ParseRelayType (conf, "RelayType", &mode))
449 	{
450 		syslog (LOG_ALERT, _("Fatal configuration error"));
451 		return -2;
452 	}
453 
454 #ifdef MIREDO_TEREDO_CLIENT
455 	const char *server_name2 = NULL;
456 	char namebuf[NI_MAXHOST], namebuf2[NI_MAXHOST];
457 #endif
458 	uint16_t mtu = 1280;
459 	bool cone = false;
460 
461 	if (mode & TEREDO_CLIENT)
462 	{
463 #ifdef MIREDO_TEREDO_CLIENT
464 		if (server_name == NULL)
465 		{
466 			char *name = miredo_conf_get (conf, "ServerAddress", NULL);
467 			if (name == NULL)
468 			{
469 				syslog (LOG_ALERT, _("Server address not specified"));
470 				syslog (LOG_ALERT, _("Fatal configuration error"));
471 				return -2;
472 			}
473 			strlcpy (namebuf, name, sizeof (namebuf));
474 			free (name);
475 			server_name = namebuf;
476 
477 			name = miredo_conf_get (conf, "ServerAddress2", NULL);
478 			if (name != NULL)
479 			{
480 				strlcpy (namebuf2, name, sizeof (namebuf2));
481 				free (name);
482 				server_name2 = namebuf2;
483 			}
484 		}
485 #else
486 		syslog (LOG_ALERT, _("Unsupported Teredo client mode"));
487 		syslog (LOG_ALERT, _("Fatal configuration error"));
488 		return -2;
489 #endif
490 	}
491 	else
492 	{
493 		server_name = NULL;
494 		mtu = 1280;
495 		cone = (mode == TEREDO_CONE);
496 
497 		if (!miredo_conf_parse_teredo_prefix (conf, "Prefix",
498 		                                      &prefix.teredo.prefix)
499 		 || !miredo_conf_get_int16 (conf, "InterfaceMTU", &mtu, NULL))
500 		{
501 			syslog (LOG_ALERT, _("Fatal configuration error"));
502 			return -2;
503 		}
504 	}
505 
506 	uint32_t bind_ip = INADDR_ANY;
507 	uint16_t bind_port =
508 #if 0
509 		/*
510 		 * We use 3545 as a Teredo service port.
511 		 * It is better to use a fixed port number for the
512 		 * purpose of firewalling, rather than a pseudo-random
513 		 * one (all the more as it might be a "dangerous"
514 		 * often firewalled port, such as 1214 as it happened
515 		 * to me once).
516 		 */
517 		IPPORT_TEREDO + 1;
518 #else
519 		0;
520 #endif
521 
522 	if (!miredo_conf_parse_IPv4 (conf, "BindAddress", &bind_ip)
523 	 || !miredo_conf_get_int16 (conf, "BindPort", &bind_port, NULL))
524 	{
525 		syslog (LOG_ALERT, _("Fatal configuration error"));
526 		return -2;
527 	}
528 
529 	bind_port = htons (bind_port);
530 
531 	char *ifname = miredo_conf_get (conf, "InterfaceName", NULL);
532 
533 	miredo_conf_clear (conf, 5);
534 
535 	/*
536 	 * SETUP
537 	 */
538 
539 	// Tunneling interface initialization
540 	int privfd = -1;
541 	tun6 *tunnel = (mode & TEREDO_CLIENT)
542 		? create_dynamic_tunnel (ifname, &privfd)
543 		: create_static_tunnel (ifname, &prefix.ip6, mtu);
544 
545 	if (ifname != NULL)
546 		free (ifname);
547 
548 	int retval = -1;
549 
550 	if (tunnel == NULL)
551 	{
552 		syslog (LOG_ALERT, _("Miredo setup failure: %s"),
553 		        _("Cannot create IPv6 tunnel"));
554 		return -1;
555 	}
556 
557 	if (miredo_init ((mode & TEREDO_CLIENT) != 0))
558 		syslog (LOG_ALERT, _("Miredo setup failure: %s"),
559 		        _("libteredo cannot be initialized"));
560 	else
561 	{
562 		if (drop_privileges () == 0)
563 		{
564 			teredo_tunnel *relay = teredo_create (bind_ip, bind_port);
565 			if (relay != NULL)
566 			{
567 				miredo_tunnel data = { tunnel, privfd, relay };
568 				teredo_set_privdata (relay, &data);
569 				teredo_set_recv_callback (relay, miredo_recv_callback);
570 				teredo_set_icmpv6_callback (relay, miredo_icmp6_callback);
571 
572 				retval = (mode & TEREDO_CLIENT)
573 					? setup_client (relay, server_name, server_name2)
574 					: setup_relay (relay, prefix.teredo.prefix, cone);
575 
576 				/*
577 				 * RUN
578 				 */
579 				if (retval == 0)
580 					retval = run_tunnel (&data);
581 				teredo_destroy (relay);
582 			}
583 
584 			if (retval)
585 				syslog (LOG_ALERT, _("Miredo setup failure: %s"),
586 				        _("libteredo cannot be initialized"));
587 		}
588 		miredo_deinit ((mode & TEREDO_CLIENT) != 0);
589 	}
590 
591 	if (mode & TEREDO_CLIENT)
592 		destroy_dynamic_tunnel (tunnel, privfd);
593 	else
594 		destroy_static_tunnel (tunnel, &prefix.ip6);
595 
596 	return retval;
597 }
598 
599 
miredo_setup_fd(int fd)600 static void miredo_setup_fd (int fd)
601 {
602 	(void) fcntl (fd, F_SETFD, FD_CLOEXEC);
603 }
604 
605 
miredo_setup_nonblock_fd(int fd)606 static void miredo_setup_nonblock_fd (int fd)
607 {
608 	int flags = fcntl (fd, F_GETFL);
609 	if (flags == -1)
610 		flags = 0;
611 	(void) fcntl (fd, F_SETFL, O_NONBLOCK | flags);
612 	miredo_setup_fd (fd);
613 }
614 
615 
main(int argc,char * argv[])616 int main (int argc, char *argv[])
617 {
618 #ifdef HAVE_LIBCAP
619 	static const cap_value_t capv[] =
620 	{
621 		CAP_NET_ADMIN, /* required by libtun6 */
622 		CAP_NET_RAW /* required for raw ICMPv6 socket */
623 	};
624 
625 	miredo_capv = capv;
626 	miredo_capc = sizeof (capv) / sizeof (capv[0]);
627 #endif
628 
629 	miredo_name = "miredo";
630 	miredo_diagnose = relay_diagnose;
631 	miredo_run = relay_run;
632 
633 	return miredo_main (argc, argv);
634 }
635 
636