Home | History | Annotate | Line # | Download | only in faithd
faithd.c revision 1.10.2.2
      1  1.10.2.2  itojun /*	$NetBSD: faithd.c,v 1.10.2.2 2000/07/07 11:33:34 itojun Exp $	*/
      2  1.10.2.1  itojun /*	$KAME: faithd.c,v 1.19 2000/06/29 01:17:29 itojun Exp $	*/
      3       1.1  itojun 
      4       1.1  itojun /*
      5       1.1  itojun  * Copyright (C) 1997 and 1998 WIDE Project.
      6       1.1  itojun  * All rights reserved.
      7      1.10  itojun  *
      8       1.1  itojun  * Redistribution and use in source and binary forms, with or without
      9       1.1  itojun  * modification, are permitted provided that the following conditions
     10       1.1  itojun  * are met:
     11       1.1  itojun  * 1. Redistributions of source code must retain the above copyright
     12       1.1  itojun  *    notice, this list of conditions and the following disclaimer.
     13       1.1  itojun  * 2. Redistributions in binary form must reproduce the above copyright
     14       1.1  itojun  *    notice, this list of conditions and the following disclaimer in the
     15       1.1  itojun  *    documentation and/or other materials provided with the distribution.
     16       1.1  itojun  * 3. Neither the name of the project nor the names of its contributors
     17       1.1  itojun  *    may be used to endorse or promote products derived from this software
     18       1.1  itojun  *    without specific prior written permission.
     19      1.10  itojun  *
     20       1.1  itojun  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     21       1.1  itojun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22       1.1  itojun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     23       1.1  itojun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     24       1.1  itojun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     25       1.1  itojun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     26       1.1  itojun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     27       1.1  itojun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     28       1.1  itojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     29       1.1  itojun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     30       1.1  itojun  * SUCH DAMAGE.
     31       1.1  itojun  */
     32       1.1  itojun 
     33       1.1  itojun /*
     34       1.1  itojun  * User level translator from IPv6 to IPv4.
     35       1.1  itojun  *
     36       1.1  itojun  * Usage: faithd [<port> <progpath> <arg1(progname)> <arg2> ...]
     37       1.1  itojun  *   e.g. faithd telnet /usr/local/v6/sbin/telnetd telnetd
     38       1.1  itojun  */
     39       1.9  itojun #define HAVE_GETIFADDRS
     40       1.1  itojun 
     41       1.1  itojun #include <sys/param.h>
     42       1.1  itojun #include <sys/types.h>
     43       1.1  itojun #include <sys/sysctl.h>
     44       1.1  itojun #include <sys/socket.h>
     45       1.1  itojun #include <sys/wait.h>
     46       1.1  itojun #include <sys/stat.h>
     47       1.1  itojun #include <sys/time.h>
     48       1.1  itojun #include <sys/ioctl.h>
     49       1.1  itojun #ifdef __FreeBSD__
     50       1.1  itojun #include <libutil.h>
     51       1.1  itojun #endif
     52       1.1  itojun 
     53       1.1  itojun #include <stdio.h>
     54       1.1  itojun #include <stdlib.h>
     55       1.1  itojun #include <stdarg.h>
     56       1.1  itojun #include <string.h>
     57       1.1  itojun #include <syslog.h>
     58       1.1  itojun #include <unistd.h>
     59       1.1  itojun #include <errno.h>
     60       1.1  itojun #include <signal.h>
     61       1.1  itojun #include <fcntl.h>
     62       1.1  itojun #include <termios.h>
     63       1.1  itojun 
     64       1.1  itojun #include <net/if_types.h>
     65       1.1  itojun #ifdef IFT_FAITH
     66       1.1  itojun # define USE_ROUTE
     67       1.1  itojun # include <net/if.h>
     68       1.1  itojun # include <net/route.h>
     69       1.1  itojun # include <net/if_dl.h>
     70       1.1  itojun #endif
     71       1.1  itojun 
     72       1.1  itojun #include <netinet/in.h>
     73       1.1  itojun #include <arpa/inet.h>
     74       1.1  itojun #include <netdb.h>
     75       1.9  itojun #ifdef HAVE_GETIFADDRS
     76       1.9  itojun #include <ifaddrs.h>
     77       1.9  itojun #endif
     78       1.1  itojun 
     79       1.1  itojun #ifdef FAITH4
     80       1.1  itojun #include <resolv.h>
     81       1.1  itojun #include <arpa/nameser.h>
     82       1.1  itojun #ifndef FAITH_NS
     83       1.1  itojun #define FAITH_NS "FAITH_NS"
     84       1.1  itojun #endif
     85       1.1  itojun #endif
     86       1.1  itojun 
     87       1.1  itojun #include "faithd.h"
     88       1.1  itojun 
     89       1.1  itojun char *serverpath = NULL;
     90       1.1  itojun char *serverarg[MAXARGV + 1];
     91       1.1  itojun static char *faithdname = NULL;
     92       1.1  itojun char logname[BUFSIZ];
     93       1.7  itojun char procname[BUFSIZ];
     94       1.1  itojun struct myaddrs {
     95       1.1  itojun 	struct myaddrs *next;
     96       1.1  itojun 	struct sockaddr *addr;
     97       1.1  itojun };
     98       1.1  itojun struct myaddrs *myaddrs = NULL;
     99       1.1  itojun static char *service;
    100       1.1  itojun #ifdef USE_ROUTE
    101       1.1  itojun static int sockfd = 0;
    102       1.1  itojun #endif
    103       1.1  itojun int dflag = 0;
    104       1.1  itojun static int pflag = 0;
    105       1.1  itojun 
    106       1.1  itojun int main __P((int, char **));
    107       1.1  itojun static void play_service __P((int));
    108       1.1  itojun static void play_child __P((int, struct sockaddr *));
    109       1.1  itojun static int faith_prefix __P((struct sockaddr *));
    110       1.1  itojun static int map6to4 __P((struct sockaddr_in6 *, struct sockaddr_in *));
    111       1.1  itojun #ifdef FAITH4
    112       1.1  itojun static int map4to6 __P((struct sockaddr_in *, struct sockaddr_in6 *));
    113       1.1  itojun #endif
    114       1.1  itojun static void sig_child __P((int));
    115       1.1  itojun static void sig_terminate __P((int));
    116       1.1  itojun static void start_daemon __P((void));
    117       1.9  itojun #ifndef HAVE_GETIFADDRS
    118       1.1  itojun static unsigned int if_maxindex __P((void));
    119       1.9  itojun #endif
    120       1.1  itojun static void grab_myaddrs __P((void));
    121       1.1  itojun static void free_myaddrs __P((void));
    122       1.1  itojun static void update_myaddrs __P((void));
    123       1.1  itojun static void usage __P((void));
    124       1.1  itojun 
    125       1.1  itojun int
    126       1.1  itojun main(int argc, char *argv[])
    127       1.1  itojun {
    128       1.1  itojun 	struct addrinfo hints, *res;
    129       1.1  itojun 	int s_wld, error, i, serverargc, on = 1;
    130       1.1  itojun 	int family = AF_INET6;
    131       1.1  itojun 	int c;
    132       1.1  itojun #ifdef FAITH_NS
    133       1.1  itojun 	char *ns;
    134       1.1  itojun #endif /* FAITH_NS */
    135       1.1  itojun 
    136       1.1  itojun 	/*
    137       1.1  itojun 	 * Initializing stuff
    138       1.1  itojun 	 */
    139       1.1  itojun 
    140       1.1  itojun 	faithdname = strrchr(argv[0], '/');
    141       1.1  itojun 	if (faithdname)
    142       1.1  itojun 		faithdname++;
    143       1.1  itojun 	else
    144       1.1  itojun 		faithdname = argv[0];
    145       1.1  itojun 
    146       1.1  itojun 	while ((c = getopt(argc, argv, "dp46")) != -1) {
    147       1.1  itojun 		switch (c) {
    148       1.1  itojun 		case 'd':
    149       1.1  itojun 			dflag++;
    150       1.1  itojun 			break;
    151       1.1  itojun 		case 'p':
    152       1.1  itojun 			pflag++;
    153       1.1  itojun 			break;
    154       1.1  itojun #ifdef FAITH4
    155       1.1  itojun 		case '4':
    156       1.1  itojun 			family = AF_INET;
    157       1.1  itojun 			break;
    158       1.1  itojun 		case '6':
    159       1.1  itojun 			family = AF_INET6;
    160       1.1  itojun 			break;
    161       1.1  itojun #endif
    162       1.1  itojun 		default:
    163       1.1  itojun 			usage();
    164       1.1  itojun 			break;
    165       1.1  itojun 		}
    166       1.1  itojun 	}
    167       1.1  itojun 	argc -= optind;
    168       1.1  itojun 	argv += optind;
    169       1.1  itojun 
    170       1.1  itojun #ifdef FAITH_NS
    171       1.1  itojun 	if ((ns = getenv(FAITH_NS)) != NULL) {
    172       1.1  itojun 		struct sockaddr_storage ss;
    173       1.1  itojun 		struct addrinfo hints, *res;
    174       1.1  itojun 		char serv[NI_MAXSERV];
    175       1.1  itojun 
    176       1.1  itojun 		memset(&ss, 0, sizeof(ss));
    177       1.1  itojun 		memset(&hints, 0, sizeof(hints));
    178       1.7  itojun 		snprintf(serv, sizeof(serv), "%u", NAMESERVER_PORT);
    179       1.1  itojun 		hints.ai_flags = AI_NUMERICHOST;
    180       1.1  itojun 		if (getaddrinfo(ns, serv, &hints, &res) ==  0) {
    181       1.1  itojun 			res_init();
    182       1.1  itojun 			memcpy(&_res_ext.nsaddr, res->ai_addr, res->ai_addrlen);
    183       1.1  itojun 			_res.nscount = 1;
    184       1.1  itojun 		}
    185       1.1  itojun 	}
    186       1.1  itojun #endif /* FAITH_NS */
    187       1.1  itojun 
    188       1.1  itojun #ifdef USE_ROUTE
    189       1.1  itojun 	grab_myaddrs();
    190       1.1  itojun #endif
    191       1.1  itojun 
    192       1.1  itojun 	switch (argc) {
    193       1.1  itojun 	case 0:
    194       1.1  itojun 		serverpath = DEFAULT_PATH;
    195       1.1  itojun 		serverarg[0] = DEFAULT_NAME;
    196       1.1  itojun 		serverarg[1] = NULL;
    197       1.1  itojun 		service = DEFAULT_PORT_NAME;
    198       1.1  itojun 		break;
    199       1.1  itojun 	default:
    200       1.1  itojun 		serverargc = argc - NUMARG;
    201       1.1  itojun 		if (serverargc > MAXARGV)
    202       1.1  itojun 			exit_error("too many augments");
    203       1.1  itojun 
    204      1.10  itojun 		serverpath = malloc(strlen(argv[NUMPRG]) + 1);
    205       1.1  itojun 		strcpy(serverpath, argv[NUMPRG]);
    206       1.1  itojun 		for (i = 0; i < serverargc; i++) {
    207      1.10  itojun 			serverarg[i] = malloc(strlen(argv[i + NUMARG]) + 1);
    208       1.1  itojun 			strcpy(serverarg[i], argv[i + NUMARG]);
    209       1.1  itojun 		}
    210       1.1  itojun 		serverarg[i] = NULL;
    211       1.1  itojun 		/* fall throuth */
    212       1.1  itojun 	case 1:	/* no local service */
    213       1.1  itojun 		service = argv[NUMPRT];
    214       1.1  itojun 		break;
    215       1.1  itojun 	}
    216       1.1  itojun 
    217       1.1  itojun 	/*
    218       1.1  itojun 	 * Opening wild card socket for this service.
    219       1.1  itojun 	 */
    220       1.1  itojun 
    221       1.1  itojun 	memset(&hints, 0, sizeof(hints));
    222       1.1  itojun 	hints.ai_flags = AI_PASSIVE;
    223       1.1  itojun 	hints.ai_family = family;
    224       1.1  itojun 	hints.ai_socktype = SOCK_STREAM;
    225       1.1  itojun 	hints.ai_protocol = 0;
    226       1.1  itojun 	error = getaddrinfo(NULL, service, &hints, &res);
    227      1.10  itojun 	if (error)
    228       1.3  itojun 		exit_error("getaddrinfo: %s", gai_strerror(error));
    229       1.1  itojun 
    230       1.1  itojun 	s_wld = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    231       1.1  itojun 	if (s_wld == -1)
    232       1.1  itojun 		exit_error("socket: %s", ERRSTR);
    233       1.1  itojun 
    234       1.1  itojun #ifdef IPV6_FAITH
    235       1.1  itojun 	if (res->ai_family == AF_INET6) {
    236       1.1  itojun 		error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_FAITH, &on, sizeof(on));
    237       1.1  itojun 		if (error == -1)
    238       1.4  itojun 			exit_error("setsockopt(IPV6_FAITH): %s", ERRSTR);
    239       1.1  itojun 	}
    240       1.1  itojun #endif
    241       1.1  itojun #ifdef FAITH4
    242       1.1  itojun #ifdef IP_FAITH
    243       1.1  itojun 	if (res->ai_family == AF_INET) {
    244       1.1  itojun 		error = setsockopt(s_wld, IPPROTO_IP, IP_FAITH, &on, sizeof(on));
    245       1.1  itojun 		if (error == -1)
    246       1.4  itojun 			exit_error("setsockopt(IP_FAITH): %s", ERRSTR);
    247       1.1  itojun 	}
    248       1.1  itojun #endif
    249       1.1  itojun #endif /* FAITH4 */
    250       1.1  itojun 
    251       1.1  itojun 	error = setsockopt(s_wld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    252       1.1  itojun 	if (error == -1)
    253       1.4  itojun 		exit_error("setsockopt(SO_REUSEADDR): %s", ERRSTR);
    254       1.1  itojun 
    255       1.1  itojun 	error = setsockopt(s_wld, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));
    256       1.1  itojun 	if (error == -1)
    257       1.4  itojun 		exit_error("setsockopt(SO_OOBINLINE): %s", ERRSTR);
    258       1.1  itojun 
    259       1.1  itojun 	error = bind(s_wld, (struct sockaddr *)res->ai_addr, res->ai_addrlen);
    260       1.1  itojun 	if (error == -1)
    261       1.1  itojun 		exit_error("bind: %s", ERRSTR);
    262       1.1  itojun 
    263       1.1  itojun 	error = listen(s_wld, 5);
    264       1.1  itojun 	if (error == -1)
    265       1.1  itojun 		exit_error("listen: %s", ERRSTR);
    266       1.1  itojun 
    267       1.1  itojun #ifdef USE_ROUTE
    268       1.1  itojun 	sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
    269       1.1  itojun 	if (sockfd < 0) {
    270       1.1  itojun 		exit_error("socket(PF_ROUTE): %s", ERRSTR);
    271       1.1  itojun 		/*NOTREACHED*/
    272       1.1  itojun 	}
    273       1.1  itojun #endif
    274       1.1  itojun 
    275       1.1  itojun 	/*
    276       1.1  itojun 	 * Everything is OK.
    277       1.1  itojun 	 */
    278       1.1  itojun 
    279       1.1  itojun 	start_daemon();
    280       1.1  itojun 
    281       1.7  itojun 	snprintf(logname, sizeof(logname), "faithd %s", service);
    282       1.7  itojun 	snprintf(procname, sizeof(procname), "accepting port %s", service);
    283       1.1  itojun 	openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
    284       1.1  itojun 	syslog(LOG_INFO, "Staring faith daemon for %s port", service);
    285       1.1  itojun 
    286       1.1  itojun 	play_service(s_wld);
    287       1.1  itojun 	/*NOTRECHED*/
    288       1.1  itojun 	exit(1);	/*pacify gcc*/
    289       1.1  itojun }
    290       1.1  itojun 
    291       1.1  itojun static void
    292       1.1  itojun play_service(int s_wld)
    293       1.1  itojun {
    294       1.1  itojun 	struct sockaddr_storage srcaddr;
    295       1.1  itojun 	int len;
    296       1.1  itojun 	int s_src;
    297       1.1  itojun 	pid_t child_pid;
    298       1.1  itojun 	fd_set rfds;
    299       1.1  itojun 	int error;
    300       1.1  itojun 	int maxfd;
    301       1.1  itojun 
    302       1.1  itojun 	/*
    303       1.1  itojun 	 * Wait, accept, fork, faith....
    304       1.1  itojun 	 */
    305       1.1  itojun again:
    306  1.10.2.2  itojun 	setproctitle("%s", procname);
    307       1.1  itojun 
    308       1.1  itojun 	FD_ZERO(&rfds);
    309       1.1  itojun 	FD_SET(s_wld, &rfds);
    310       1.1  itojun 	maxfd = s_wld;
    311       1.1  itojun #ifdef USE_ROUTE
    312       1.1  itojun 	if (sockfd) {
    313       1.1  itojun 		FD_SET(sockfd, &rfds);
    314       1.1  itojun 		maxfd = (maxfd < sockfd) ? sockfd : maxfd;
    315       1.1  itojun 	}
    316       1.1  itojun #endif
    317       1.1  itojun 
    318       1.1  itojun 	error = select(maxfd + 1, &rfds, NULL, NULL, NULL);
    319       1.1  itojun 	if (error < 0) {
    320       1.1  itojun 		if (errno == EINTR)
    321       1.1  itojun 			goto again;
    322       1.1  itojun 		exit_failure("select: %s", ERRSTR);
    323       1.1  itojun 		/*NOTREACHED*/
    324       1.1  itojun 	}
    325       1.1  itojun 
    326       1.1  itojun #ifdef USE_ROUTE
    327       1.1  itojun 	if (FD_ISSET(sockfd, &rfds)) {
    328       1.1  itojun 		update_myaddrs();
    329       1.1  itojun 	}
    330       1.1  itojun #endif
    331       1.1  itojun 	if (FD_ISSET(s_wld, &rfds)) {
    332       1.1  itojun 		len = sizeof(srcaddr);
    333       1.1  itojun 		s_src = accept(s_wld, (struct sockaddr *)&srcaddr,
    334       1.1  itojun 			&len);
    335       1.1  itojun 		if (s_src == -1)
    336       1.1  itojun 			exit_failure("socket: %s", ERRSTR);
    337       1.1  itojun 
    338       1.1  itojun 		child_pid = fork();
    339       1.1  itojun 
    340       1.1  itojun 		if (child_pid == 0) {
    341       1.1  itojun 			/* child process */
    342       1.1  itojun 			close(s_wld);
    343       1.1  itojun 			closelog();
    344       1.1  itojun 			openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
    345       1.1  itojun 			play_child(s_src, (struct sockaddr *)&srcaddr);
    346       1.1  itojun 			exit_failure("should never reach here");
    347       1.1  itojun 		} else {
    348       1.1  itojun 			/* parent process */
    349       1.1  itojun 			close(s_src);
    350       1.1  itojun 			if (child_pid == -1)
    351       1.1  itojun 				syslog(LOG_ERR, "can't fork");
    352       1.1  itojun 		}
    353       1.1  itojun 	}
    354       1.1  itojun 	goto again;
    355       1.1  itojun }
    356       1.1  itojun 
    357       1.1  itojun static void
    358       1.1  itojun play_child(int s_src, struct sockaddr *srcaddr)
    359       1.1  itojun {
    360      1.10  itojun 	struct sockaddr_storage dstaddr6;
    361       1.1  itojun 	struct sockaddr_storage dstaddr4;
    362       1.1  itojun 	char src[MAXHOSTNAMELEN];
    363       1.1  itojun 	char dst6[MAXHOSTNAMELEN];
    364       1.1  itojun 	char dst4[MAXHOSTNAMELEN];
    365       1.1  itojun 	int len = sizeof(dstaddr6);
    366       1.1  itojun 	int s_dst, error, hport, nresvport, on = 1;
    367       1.1  itojun 	struct timeval tv;
    368       1.2  itojun 	struct sockaddr *sa4;
    369       1.1  itojun 
    370       1.1  itojun 	tv.tv_sec = 1;
    371       1.1  itojun 	tv.tv_usec = 0;
    372       1.1  itojun 
    373       1.1  itojun 	getnameinfo(srcaddr, srcaddr->sa_len,
    374       1.1  itojun 		src, sizeof(src), NULL, 0, NI_NUMERICHOST);
    375       1.1  itojun 	syslog(LOG_INFO, "accepted a client from %s", src);
    376       1.1  itojun 
    377       1.1  itojun 	error = getsockname(s_src, (struct sockaddr *)&dstaddr6, &len);
    378       1.1  itojun 	if (error == -1)
    379       1.1  itojun 		exit_failure("getsockname: %s", ERRSTR);
    380       1.1  itojun 
    381       1.2  itojun 	getnameinfo((struct sockaddr *)&dstaddr6, len,
    382       1.1  itojun 		dst6, sizeof(dst6), NULL, 0, NI_NUMERICHOST);
    383       1.1  itojun 	syslog(LOG_INFO, "the client is connecting to %s", dst6);
    384       1.1  itojun 
    385       1.1  itojun 	if (!faith_prefix((struct sockaddr *)&dstaddr6)) {
    386       1.1  itojun 		if (serverpath) {
    387       1.1  itojun 			/*
    388       1.1  itojun 			 * Local service
    389       1.1  itojun 			 */
    390       1.1  itojun 			syslog(LOG_INFO, "executing local %s", serverpath);
    391       1.1  itojun 			dup2(s_src, 0);
    392       1.1  itojun 			close(s_src);
    393       1.1  itojun 			dup2(0, 1);
    394       1.1  itojun 			dup2(0, 2);
    395       1.1  itojun 			execv(serverpath, serverarg);
    396       1.1  itojun 			syslog(LOG_ERR, "execv %s: %s", serverpath, ERRSTR);
    397       1.1  itojun 			_exit(EXIT_FAILURE);
    398       1.1  itojun 		} else {
    399       1.1  itojun 			close(s_src);
    400       1.1  itojun 			exit_success("no local service for %s", service);
    401       1.1  itojun 		}
    402       1.1  itojun 	}
    403       1.1  itojun 
    404       1.1  itojun 	/*
    405       1.1  itojun 	 * Act as a translator
    406       1.1  itojun 	 */
    407       1.1  itojun 
    408       1.2  itojun 	switch (((struct sockaddr *)&dstaddr6)->sa_family) {
    409       1.2  itojun 	case AF_INET6:
    410       1.1  itojun 		if (!map6to4((struct sockaddr_in6 *)&dstaddr6,
    411       1.1  itojun 		    (struct sockaddr_in *)&dstaddr4)) {
    412       1.1  itojun 			close(s_src);
    413       1.1  itojun 			exit_error("map6to4 failed");
    414       1.1  itojun 		}
    415       1.1  itojun 		syslog(LOG_INFO, "translating from v6 to v4");
    416       1.2  itojun 		break;
    417       1.1  itojun #ifdef FAITH4
    418       1.2  itojun 	case AF_INET:
    419       1.1  itojun 		if (!map4to6((struct sockaddr_in *)&dstaddr6,
    420       1.1  itojun 		    (struct sockaddr_in6 *)&dstaddr4)) {
    421       1.1  itojun 			close(s_src);
    422       1.1  itojun 			exit_error("map4to6 failed");
    423       1.1  itojun 		}
    424       1.1  itojun 		syslog(LOG_INFO, "translating from v4 to v6");
    425       1.2  itojun 		break;
    426       1.1  itojun #endif
    427       1.2  itojun 	default:
    428       1.1  itojun 		close(s_src);
    429       1.1  itojun 		exit_error("family not supported");
    430       1.2  itojun 		/*NOTREACHED*/
    431       1.1  itojun 	}
    432       1.1  itojun 
    433       1.2  itojun 	sa4 = (struct sockaddr *)&dstaddr4;
    434       1.2  itojun 	getnameinfo(sa4, sa4->sa_len,
    435       1.1  itojun 		dst4, sizeof(dst4), NULL, 0, NI_NUMERICHOST);
    436       1.1  itojun 	syslog(LOG_INFO, "the translator is connecting to %s", dst4);
    437       1.1  itojun 
    438       1.1  itojun 	setproctitle("port %s, %s -> %s", service, src, dst4);
    439       1.1  itojun 
    440       1.2  itojun 	if (sa4->sa_family == AF_INET6)
    441       1.1  itojun 		hport = ntohs(((struct sockaddr_in6 *)&dstaddr4)->sin6_port);
    442       1.1  itojun 	else /* AF_INET */
    443       1.1  itojun 		hport = ntohs(((struct sockaddr_in *)&dstaddr4)->sin_port);
    444       1.1  itojun 
    445       1.1  itojun 	switch (hport) {
    446       1.1  itojun 	case RLOGIN_PORT:
    447       1.1  itojun 	case RSH_PORT:
    448       1.2  itojun 		s_dst = rresvport_af(&nresvport, sa4->sa_family);
    449       1.1  itojun 		break;
    450       1.1  itojun 	default:
    451       1.1  itojun 		if (pflag)
    452       1.2  itojun 			s_dst = rresvport_af(&nresvport, sa4->sa_family);
    453       1.1  itojun 		else
    454       1.2  itojun 			s_dst = socket(sa4->sa_family, SOCK_STREAM, 0);
    455       1.1  itojun 		break;
    456       1.1  itojun 	}
    457       1.1  itojun 	if (s_dst == -1)
    458       1.1  itojun 		exit_failure("socket: %s", ERRSTR);
    459       1.1  itojun 
    460       1.1  itojun 	error = setsockopt(s_dst, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));
    461       1.1  itojun 	if (error == -1)
    462       1.4  itojun 		exit_error("setsockopt(SO_OOBINLINE): %s", ERRSTR);
    463       1.1  itojun 
    464       1.1  itojun 	error = setsockopt(s_src, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
    465       1.1  itojun 	if (error == -1)
    466       1.4  itojun 		exit_error("setsockopt(SO_SNDTIMEO): %s", ERRSTR);
    467       1.1  itojun 	error = setsockopt(s_dst, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
    468       1.1  itojun 	if (error == -1)
    469       1.4  itojun 		exit_error("setsockopt(SO_SNDTIMEO): %s", ERRSTR);
    470       1.1  itojun 
    471       1.8  itojun 	error = connect(s_dst, sa4, sa4->sa_len);
    472       1.1  itojun 	if (error == -1)
    473       1.1  itojun 		exit_failure("connect: %s", ERRSTR);
    474       1.1  itojun 
    475       1.1  itojun 	switch (hport) {
    476       1.1  itojun 	case FTP_PORT:
    477       1.1  itojun 		ftp_relay(s_src, s_dst);
    478       1.1  itojun 		break;
    479       1.1  itojun 	case RSH_PORT:
    480       1.1  itojun 		rsh_relay(s_src, s_dst);
    481       1.1  itojun 		break;
    482       1.1  itojun 	default:
    483       1.1  itojun 		tcp_relay(s_src, s_dst, service);
    484       1.1  itojun 		break;
    485       1.1  itojun 	}
    486       1.1  itojun 
    487       1.1  itojun 	/* NOTREACHED */
    488       1.1  itojun }
    489       1.1  itojun 
    490       1.1  itojun /* 0: non faith, 1: faith */
    491       1.1  itojun static int
    492       1.1  itojun faith_prefix(struct sockaddr *dst)
    493       1.1  itojun {
    494       1.1  itojun #ifndef USE_ROUTE
    495       1.1  itojun 	int mib[4], size;
    496       1.1  itojun 	struct in6_addr faith_prefix;
    497       1.1  itojun 	struct sockaddr_in6 *dst6 = (struct sockaddr_in *)dst;
    498       1.1  itojun 
    499       1.1  itojun 	if (dst->sa_family != AF_INET6)
    500       1.1  itojun 		return 0;
    501       1.1  itojun 
    502       1.1  itojun 	mib[0] = CTL_NET;
    503       1.1  itojun 	mib[1] = PF_INET6;
    504       1.1  itojun 	mib[2] = IPPROTO_IPV6;
    505       1.1  itojun 	mib[3] = IPV6CTL_FAITH_PREFIX;
    506       1.1  itojun 	size = sizeof(struct in6_addr);
    507       1.1  itojun 	if (sysctl(mib, 4, &faith_prefix, &size, NULL, 0) < 0)
    508       1.1  itojun 		exit_error("sysctl: %s", ERRSTR);
    509       1.1  itojun 
    510       1.2  itojun 	if (memcmp(dst, &faith_prefix,
    511       1.2  itojun 			sizeof(struct in6_addr) - sizeof(struct in_addr) == 0) {
    512       1.1  itojun 		return 1;
    513       1.2  itojun 	}
    514       1.1  itojun 	return 0;
    515       1.1  itojun #else
    516       1.1  itojun 	struct myaddrs *p;
    517       1.1  itojun 	struct sockaddr_in6 *sin6;
    518       1.1  itojun 	struct sockaddr_in *sin4;
    519       1.3  itojun 	struct sockaddr_in6 *dst6;
    520       1.3  itojun 	struct sockaddr_in *dst4;
    521       1.3  itojun 	struct sockaddr_in dstmap;
    522       1.3  itojun 
    523       1.4  itojun 	dst6 = (struct sockaddr_in6 *)dst;
    524       1.3  itojun 	if (dst->sa_family == AF_INET6
    525       1.3  itojun 	 && IN6_IS_ADDR_V4MAPPED(&dst6->sin6_addr)) {
    526       1.3  itojun 		/* ugly... */
    527       1.3  itojun 		memset(&dstmap, 0, sizeof(dstmap));
    528       1.3  itojun 		dstmap.sin_family = AF_INET;
    529       1.3  itojun 		dstmap.sin_len = sizeof(dstmap);
    530       1.3  itojun 		memcpy(&dstmap.sin_addr, &dst6->sin6_addr.s6_addr[12],
    531       1.3  itojun 			sizeof(dstmap.sin_addr));
    532       1.3  itojun 		dst = (struct sockaddr *)&dstmap;
    533       1.3  itojun 	}
    534       1.3  itojun 
    535       1.3  itojun 	dst6 = (struct sockaddr_in6 *)dst;
    536       1.3  itojun 	dst4 = (struct sockaddr_in *)dst;
    537       1.1  itojun 
    538       1.1  itojun 	for (p = myaddrs; p; p = p->next) {
    539       1.1  itojun 		sin6 = (struct sockaddr_in6 *)p->addr;
    540       1.1  itojun 		sin4 = (struct sockaddr_in *)p->addr;
    541       1.1  itojun 
    542       1.3  itojun 		if (p->addr->sa_len != dst->sa_len
    543       1.3  itojun 		 || p->addr->sa_family != dst->sa_family)
    544       1.3  itojun 			continue;
    545       1.3  itojun 
    546       1.3  itojun 		switch (dst->sa_family) {
    547       1.3  itojun 		case AF_INET6:
    548       1.3  itojun 			if (sin6->sin6_scope_id == dst6->sin6_scope_id
    549       1.5  itojun 			 && IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &dst6->sin6_addr))
    550       1.1  itojun 				return 0;
    551       1.3  itojun 			break;
    552       1.3  itojun 		case AF_INET:
    553       1.3  itojun 			if (sin4->sin_addr.s_addr == dst4->sin_addr.s_addr)
    554       1.6  itojun 				return 0;
    555       1.3  itojun 			break;
    556       1.1  itojun 		}
    557       1.1  itojun 	}
    558       1.1  itojun 	return 1;
    559       1.1  itojun #endif
    560       1.1  itojun }
    561       1.1  itojun 
    562       1.1  itojun /* 0: non faith, 1: faith */
    563       1.1  itojun static int
    564       1.1  itojun map6to4(struct sockaddr_in6 *dst6, struct sockaddr_in *dst4)
    565       1.1  itojun {
    566       1.1  itojun 	memset(dst4, 0, sizeof(*dst4));
    567       1.1  itojun 	dst4->sin_len = sizeof(*dst4);
    568       1.1  itojun 	dst4->sin_family = AF_INET;
    569       1.1  itojun 	dst4->sin_port = dst6->sin6_port;
    570       1.2  itojun 	memcpy(&dst4->sin_addr, &dst6->sin6_addr.s6_addr[12],
    571       1.2  itojun 		sizeof(dst4->sin_addr));
    572       1.1  itojun 
    573       1.1  itojun 	if (dst4->sin_addr.s_addr == INADDR_ANY
    574       1.1  itojun 	 || dst4->sin_addr.s_addr == INADDR_BROADCAST
    575       1.1  itojun 	 || IN_MULTICAST(dst4->sin_addr.s_addr))
    576       1.1  itojun 		return 0;
    577       1.1  itojun 
    578       1.1  itojun 	return 1;
    579       1.1  itojun }
    580       1.1  itojun 
    581       1.1  itojun #ifdef FAITH4
    582       1.1  itojun /* 0: non faith, 1: faith */
    583       1.1  itojun static int
    584       1.1  itojun map4to6(struct sockaddr_in *dst4, struct sockaddr_in6 *dst6)
    585       1.1  itojun {
    586       1.1  itojun 	char host[NI_MAXHOST];
    587       1.1  itojun 	char serv[NI_MAXSERV];
    588       1.1  itojun 	struct addrinfo hints, *res;
    589       1.1  itojun 	int ai_errno;
    590       1.1  itojun 
    591       1.1  itojun 	if (getnameinfo((struct sockaddr *)dst4, dst4->sin_len, host, sizeof(host),
    592       1.1  itojun 			serv, sizeof(serv), NI_NAMEREQD|NI_NUMERICSERV) != 0)
    593       1.1  itojun 		return 0;
    594       1.1  itojun 
    595       1.1  itojun 	memset(&hints, 0, sizeof(hints));
    596       1.1  itojun 	hints.ai_flags = 0;
    597       1.1  itojun 	hints.ai_family = AF_INET6;
    598       1.1  itojun 	hints.ai_socktype = SOCK_STREAM;
    599       1.1  itojun 	hints.ai_protocol = 0;
    600       1.1  itojun 
    601       1.1  itojun 	if ((ai_errno = getaddrinfo(host, serv, &hints, &res)) != 0) {
    602       1.1  itojun 		syslog(LOG_INFO, "%s %s: %s", host, serv, gai_strerror(ai_errno));
    603       1.1  itojun 		return 0;
    604       1.1  itojun 	}
    605       1.1  itojun 
    606       1.1  itojun 	memcpy(dst6, res->ai_addr, res->ai_addrlen);
    607       1.1  itojun 
    608       1.1  itojun 	freeaddrinfo(res);
    609       1.1  itojun 
    610       1.1  itojun 	return 1;
    611       1.1  itojun }
    612       1.1  itojun #endif /* FAITH4 */
    613       1.1  itojun 
    614       1.1  itojun static void
    615       1.1  itojun sig_child(int sig)
    616       1.1  itojun {
    617       1.1  itojun 	int status;
    618       1.1  itojun 	pid_t pid;
    619       1.1  itojun 
    620       1.1  itojun 	pid = wait3(&status, WNOHANG, (struct rusage *)0);
    621       1.1  itojun 	if (pid && status)
    622       1.1  itojun 		syslog(LOG_WARNING, "child %d exit status 0x%x", pid, status);
    623       1.1  itojun }
    624       1.1  itojun 
    625       1.1  itojun void
    626       1.1  itojun sig_terminate(int sig)
    627       1.1  itojun {
    628       1.1  itojun 	syslog(LOG_INFO, "Terminating faith daemon");
    629       1.1  itojun 	exit(EXIT_SUCCESS);
    630       1.1  itojun }
    631       1.1  itojun 
    632       1.1  itojun static void
    633       1.1  itojun start_daemon(void)
    634       1.1  itojun {
    635       1.1  itojun 	if (daemon(0, 0) == -1)
    636       1.1  itojun 		exit_error("daemon: %s", ERRSTR);
    637       1.1  itojun 
    638       1.1  itojun 	if (signal(SIGCHLD, sig_child) == SIG_ERR)
    639       1.1  itojun 		exit_failure("signal CHLD: %s", ERRSTR);
    640       1.1  itojun 
    641       1.1  itojun 	if (signal(SIGTERM, sig_terminate) == SIG_ERR)
    642       1.1  itojun 		exit_failure("signal TERM: %s", ERRSTR);
    643       1.1  itojun }
    644       1.1  itojun 
    645       1.1  itojun void
    646       1.1  itojun exit_error(const char *fmt, ...)
    647       1.1  itojun {
    648       1.1  itojun 	va_list ap;
    649       1.1  itojun 	char buf[BUFSIZ];
    650       1.1  itojun 
    651       1.1  itojun 	va_start(ap, fmt);
    652       1.7  itojun 	vsnprintf(buf, sizeof(buf), fmt, ap);
    653       1.1  itojun 	va_end(ap);
    654       1.1  itojun 	fprintf(stderr, "%s\n", buf);
    655       1.1  itojun 	exit(EXIT_FAILURE);
    656       1.1  itojun }
    657       1.1  itojun 
    658       1.1  itojun void
    659       1.1  itojun exit_failure(const char *fmt, ...)
    660       1.1  itojun {
    661       1.1  itojun 	va_list ap;
    662       1.1  itojun 	char buf[BUFSIZ];
    663       1.1  itojun 
    664       1.1  itojun 	va_start(ap, fmt);
    665       1.7  itojun 	vsnprintf(buf, sizeof(buf), fmt, ap);
    666       1.1  itojun 	va_end(ap);
    667  1.10.2.1  itojun 	syslog(LOG_ERR, "%s", buf);
    668       1.1  itojun 	exit(EXIT_FAILURE);
    669       1.1  itojun }
    670       1.1  itojun 
    671       1.1  itojun void
    672       1.1  itojun exit_success(const char *fmt, ...)
    673       1.1  itojun {
    674       1.1  itojun 	va_list ap;
    675       1.1  itojun 	char buf[BUFSIZ];
    676       1.1  itojun 
    677       1.1  itojun 	va_start(ap, fmt);
    678       1.7  itojun 	vsnprintf(buf, sizeof(buf), fmt, ap);
    679       1.1  itojun 	va_end(ap);
    680  1.10.2.1  itojun 	syslog(LOG_INFO, "%s", buf);
    681       1.1  itojun 	exit(EXIT_SUCCESS);
    682       1.1  itojun }
    683       1.1  itojun 
    684       1.1  itojun #ifdef USE_ROUTE
    685       1.9  itojun #ifndef HAVE_GETIFADDRS
    686       1.1  itojun static unsigned int
    687       1.1  itojun if_maxindex()
    688       1.1  itojun {
    689       1.1  itojun 	struct if_nameindex *p, *p0;
    690       1.1  itojun 	unsigned int max = 0;
    691       1.1  itojun 
    692       1.1  itojun 	p0 = if_nameindex();
    693       1.1  itojun 	for (p = p0; p && p->if_index && p->if_name; p++) {
    694       1.1  itojun 		if (max < p->if_index)
    695       1.1  itojun 			max = p->if_index;
    696       1.1  itojun 	}
    697       1.1  itojun 	if_freenameindex(p0);
    698       1.1  itojun 	return max;
    699       1.1  itojun }
    700       1.9  itojun #endif
    701       1.1  itojun 
    702       1.1  itojun static void
    703       1.1  itojun grab_myaddrs()
    704       1.1  itojun {
    705       1.9  itojun #ifdef HAVE_GETIFADDRS
    706       1.9  itojun 	struct ifaddrs *ifap, *ifa;
    707       1.9  itojun 	struct myaddrs *p;
    708       1.9  itojun 	struct sockaddr_in6 *sin6;
    709       1.9  itojun 
    710       1.9  itojun 	if (getifaddrs(&ifap) != 0) {
    711       1.9  itojun 		exit_failure("getifaddrs");
    712       1.9  itojun 		/*NOTREACHED*/
    713       1.9  itojun 	}
    714       1.9  itojun 
    715       1.9  itojun 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
    716       1.9  itojun 		switch (ifa->ifa_addr->sa_family) {
    717       1.9  itojun 		case AF_INET:
    718       1.9  itojun 		case AF_INET6:
    719       1.9  itojun 			break;
    720       1.9  itojun 		default:
    721       1.9  itojun 			continue;
    722       1.9  itojun 		}
    723       1.9  itojun 
    724       1.9  itojun 		p = (struct myaddrs *)malloc(sizeof(struct myaddrs) +
    725       1.9  itojun 		    ifa->ifa_addr->sa_len);
    726       1.9  itojun 		if (!p) {
    727       1.9  itojun 			exit_failure("not enough core");
    728       1.9  itojun 			/*NOTREACHED*/
    729       1.9  itojun 		}
    730       1.9  itojun 		memcpy(p + 1, ifa->ifa_addr, ifa->ifa_addr->sa_len);
    731       1.9  itojun 		p->next = myaddrs;
    732       1.9  itojun 		p->addr = (struct sockaddr *)(p + 1);
    733       1.9  itojun #ifdef __KAME__
    734       1.9  itojun 		if (ifa->ifa_addr->sa_family == AF_INET6) {
    735       1.9  itojun 			sin6 = (struct sockaddr_in6 *)p->addr;
    736       1.9  itojun 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
    737       1.9  itojun 			 || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
    738       1.9  itojun 				sin6->sin6_scope_id =
    739       1.9  itojun 					ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
    740       1.9  itojun 				sin6->sin6_addr.s6_addr[2] = 0;
    741       1.9  itojun 				sin6->sin6_addr.s6_addr[3] = 0;
    742       1.9  itojun 			}
    743       1.9  itojun 		}
    744       1.9  itojun #endif
    745       1.9  itojun 		myaddrs = p;
    746       1.9  itojun 		if (dflag) {
    747       1.9  itojun 			char hbuf[NI_MAXHOST];
    748       1.9  itojun 			getnameinfo(p->addr, p->addr->sa_len,
    749       1.9  itojun 				hbuf, sizeof(hbuf), NULL, 0,
    750       1.9  itojun 				NI_NUMERICHOST);
    751       1.9  itojun 			syslog(LOG_INFO, "my interface: %s %s", hbuf,
    752       1.9  itojun 			    ifa->ifa_name);
    753       1.9  itojun 		}
    754       1.9  itojun 	}
    755       1.9  itojun 
    756       1.9  itojun 	freeifaddrs(ifap);
    757       1.9  itojun #else
    758       1.1  itojun 	int s;
    759       1.1  itojun 	unsigned int maxif;
    760       1.1  itojun 	struct ifreq *iflist;
    761       1.1  itojun 	struct ifconf ifconf;
    762       1.9  itojun 	struct ifreq *ifr, *ifrp, *ifr_end;
    763       1.1  itojun 	struct myaddrs *p;
    764       1.1  itojun 	struct sockaddr_in6 *sin6;
    765       1.9  itojun 	size_t siz;
    766       1.9  itojun 	char ifrbuf[sizeof(struct ifreq) + 1024];
    767       1.1  itojun 
    768       1.1  itojun 	maxif = if_maxindex() + 1;
    769       1.1  itojun 	iflist = (struct ifreq *)malloc(maxif * BUFSIZ);	/* XXX */
    770       1.1  itojun 	if (!iflist) {
    771       1.1  itojun 		exit_failure("not enough core");
    772       1.1  itojun 		/*NOTREACHED*/
    773       1.1  itojun 	}
    774       1.1  itojun 
    775       1.1  itojun 	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
    776       1.1  itojun 		exit_failure("socket(SOCK_DGRAM)");
    777       1.1  itojun 		/*NOTREACHED*/
    778       1.1  itojun 	}
    779       1.1  itojun 	memset(&ifconf, 0, sizeof(ifconf));
    780       1.1  itojun 	ifconf.ifc_req = iflist;
    781       1.1  itojun 	ifconf.ifc_len = maxif * BUFSIZ;	/* XXX */
    782       1.1  itojun 	if (ioctl(s, SIOCGIFCONF, &ifconf) < 0) {
    783       1.1  itojun 		exit_failure("ioctl(SIOCGIFCONF)");
    784       1.1  itojun 		/*NOTREACHED*/
    785       1.1  itojun 	}
    786       1.1  itojun 	close(s);
    787       1.1  itojun 
    788       1.1  itojun 	/* Look for this interface in the list */
    789       1.1  itojun 	ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len);
    790       1.9  itojun 	for (ifrp = ifconf.ifc_req;
    791       1.9  itojun 	     ifrp < ifr_end;
    792       1.9  itojun 	     ifrp = (struct ifreq *)((char *)ifrp + siz)) {
    793       1.9  itojun 		memcpy(ifrbuf, ifrp, sizeof(*ifrp));
    794       1.9  itojun 		ifr = (struct ifreq *)ifrbuf;
    795       1.9  itojun 		siz = ifr->ifr_addr.sa_len;
    796       1.9  itojun 		if (siz < sizeof(ifr->ifr_addr))
    797       1.9  itojun 			siz = sizeof(ifr->ifr_addr);
    798       1.9  itojun 		siz += (sizeof(*ifrp) - sizeof(ifr->ifr_addr));
    799       1.9  itojun 		if (siz > sizeof(ifrbuf)) {
    800       1.9  itojun 			/* ifr too big */
    801       1.9  itojun 			break;
    802       1.9  itojun 		}
    803       1.9  itojun 		memcpy(ifrbuf, ifrp, siz);
    804       1.9  itojun 
    805       1.1  itojun 		switch (ifr->ifr_addr.sa_family) {
    806       1.1  itojun 		case AF_INET:
    807       1.1  itojun 		case AF_INET6:
    808       1.1  itojun 			p = (struct myaddrs *)malloc(sizeof(struct myaddrs)
    809       1.1  itojun 				+ ifr->ifr_addr.sa_len);
    810       1.1  itojun 			if (!p) {
    811       1.1  itojun 				exit_failure("not enough core");
    812       1.1  itojun 				/*NOTREACHED*/
    813       1.1  itojun 			}
    814       1.1  itojun 			memcpy(p + 1, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
    815       1.1  itojun 			p->next = myaddrs;
    816       1.1  itojun 			p->addr = (struct sockaddr *)(p + 1);
    817       1.1  itojun #ifdef __KAME__
    818       1.1  itojun 			if (ifr->ifr_addr.sa_family == AF_INET6) {
    819       1.1  itojun 				sin6 = (struct sockaddr_in6 *)p->addr;
    820       1.1  itojun 				if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
    821       1.1  itojun 				 || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
    822       1.1  itojun 					sin6->sin6_scope_id =
    823       1.2  itojun 						ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
    824       1.2  itojun 					sin6->sin6_addr.s6_addr[2] = 0;
    825       1.2  itojun 					sin6->sin6_addr.s6_addr[3] = 0;
    826       1.1  itojun 				}
    827       1.1  itojun 			}
    828       1.1  itojun #endif
    829       1.1  itojun 			myaddrs = p;
    830       1.1  itojun 			if (dflag) {
    831       1.1  itojun 				char hbuf[NI_MAXHOST];
    832       1.1  itojun 				getnameinfo(p->addr, p->addr->sa_len,
    833       1.1  itojun 					hbuf, sizeof(hbuf), NULL, 0,
    834       1.1  itojun 					NI_NUMERICHOST);
    835       1.1  itojun 				syslog(LOG_INFO, "my interface: %s %s", hbuf, ifr->ifr_name);
    836       1.1  itojun 			}
    837       1.1  itojun 			break;
    838       1.1  itojun 		default:
    839       1.1  itojun 			break;
    840       1.1  itojun 		}
    841       1.1  itojun 	}
    842       1.1  itojun 
    843       1.1  itojun 	free(iflist);
    844       1.9  itojun #endif
    845       1.1  itojun }
    846       1.1  itojun 
    847       1.1  itojun static void
    848       1.1  itojun free_myaddrs()
    849       1.1  itojun {
    850       1.1  itojun 	struct myaddrs *p, *q;
    851       1.1  itojun 
    852       1.1  itojun 	p = myaddrs;
    853       1.1  itojun 	while (p) {
    854       1.1  itojun 		q = p->next;
    855       1.1  itojun 		free(p);
    856       1.1  itojun 		p = q;
    857       1.1  itojun 	}
    858       1.1  itojun 	myaddrs = NULL;
    859       1.1  itojun }
    860       1.1  itojun 
    861       1.1  itojun static void
    862       1.1  itojun update_myaddrs()
    863       1.1  itojun {
    864       1.1  itojun 	char msg[BUFSIZ];
    865       1.1  itojun 	int len;
    866       1.1  itojun 	struct rt_msghdr *rtm;
    867       1.1  itojun 
    868       1.1  itojun 	len = read(sockfd, msg, sizeof(msg));
    869       1.1  itojun 	if (len < 0) {
    870       1.1  itojun 		syslog(LOG_ERR, "read(PF_ROUTE) failed");
    871       1.1  itojun 		return;
    872       1.1  itojun 	}
    873       1.1  itojun 	rtm = (struct rt_msghdr *)msg;
    874       1.1  itojun 	if (len < 4 || len < rtm->rtm_msglen) {
    875       1.1  itojun 		syslog(LOG_ERR, "read(PF_ROUTE) short read");
    876       1.1  itojun 		return;
    877       1.1  itojun 	}
    878       1.1  itojun 	if (rtm->rtm_version != RTM_VERSION) {
    879       1.1  itojun 		syslog(LOG_ERR, "routing socket version mismatch");
    880       1.1  itojun 		close(sockfd);
    881       1.1  itojun 		sockfd = 0;
    882       1.1  itojun 		return;
    883       1.1  itojun 	}
    884       1.1  itojun 	switch (rtm->rtm_type) {
    885       1.1  itojun 	case RTM_NEWADDR:
    886       1.1  itojun 	case RTM_DELADDR:
    887       1.1  itojun 	case RTM_IFINFO:
    888       1.1  itojun 		break;
    889       1.1  itojun 	default:
    890       1.1  itojun 		return;
    891       1.1  itojun 	}
    892       1.1  itojun 	/* XXX more filters here? */
    893       1.1  itojun 
    894       1.1  itojun 	syslog(LOG_INFO, "update interface address list");
    895       1.1  itojun 	free_myaddrs();
    896       1.1  itojun 	grab_myaddrs();
    897       1.1  itojun }
    898       1.1  itojun #endif /*USE_ROUTE*/
    899       1.1  itojun 
    900       1.1  itojun static void
    901       1.1  itojun usage()
    902       1.1  itojun {
    903       1.1  itojun 	fprintf(stderr, "usage: %s [-dp] [service [serverpath [serverargs]]]\n",
    904       1.1  itojun 		faithdname);
    905       1.1  itojun 	exit(0);
    906       1.1  itojun }
    907