xref: /freebsd/usr.sbin/rrenumd/rrenumd.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
133841545SHajimu UMEMOTO /*	$KAME: rrenumd.c,v 1.20 2000/11/08 02:40:53 itojun Exp $	*/
2434d523bSKris Kennaway 
3*8a16b7a1SPedro F. Giffuni /*-
4*8a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
5*8a16b7a1SPedro F. Giffuni  *
69a4365d0SYoshinobu Inoue  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
79a4365d0SYoshinobu Inoue  * All rights reserved.
89a4365d0SYoshinobu Inoue  *
99a4365d0SYoshinobu Inoue  * Redistribution and use in source and binary forms, with or without
109a4365d0SYoshinobu Inoue  * modification, are permitted provided that the following conditions
119a4365d0SYoshinobu Inoue  * are met:
129a4365d0SYoshinobu Inoue  * 1. Redistributions of source code must retain the above copyright
139a4365d0SYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer.
149a4365d0SYoshinobu Inoue  * 2. Redistributions in binary form must reproduce the above copyright
159a4365d0SYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer in the
169a4365d0SYoshinobu Inoue  *    documentation and/or other materials provided with the distribution.
179a4365d0SYoshinobu Inoue  * 3. Neither the name of the project nor the names of its contributors
189a4365d0SYoshinobu Inoue  *    may be used to endorse or promote products derived from this software
199a4365d0SYoshinobu Inoue  *    without specific prior written permission.
209a4365d0SYoshinobu Inoue  *
219a4365d0SYoshinobu Inoue  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
229a4365d0SYoshinobu Inoue  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
239a4365d0SYoshinobu Inoue  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
249a4365d0SYoshinobu Inoue  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
259a4365d0SYoshinobu Inoue  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
269a4365d0SYoshinobu Inoue  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
279a4365d0SYoshinobu Inoue  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
289a4365d0SYoshinobu Inoue  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
299a4365d0SYoshinobu Inoue  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
309a4365d0SYoshinobu Inoue  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
319a4365d0SYoshinobu Inoue  * SUCH DAMAGE.
329a4365d0SYoshinobu Inoue  */
339a4365d0SYoshinobu Inoue 
349a4365d0SYoshinobu Inoue #include <sys/param.h>
359a4365d0SYoshinobu Inoue #include <sys/socket.h>
369a4365d0SYoshinobu Inoue #include <sys/uio.h>
379a4365d0SYoshinobu Inoue #include <sys/time.h>
389a4365d0SYoshinobu Inoue 
399a4365d0SYoshinobu Inoue #include <string.h>
409a4365d0SYoshinobu Inoue 
419a4365d0SYoshinobu Inoue #include <net/route.h>
429a4365d0SYoshinobu Inoue 
439a4365d0SYoshinobu Inoue #include <netinet/in_systm.h>
449a4365d0SYoshinobu Inoue #include <netinet/in.h>
459a4365d0SYoshinobu Inoue #include <netinet/ip.h>
469a4365d0SYoshinobu Inoue #include <netinet/ip6.h>
479a4365d0SYoshinobu Inoue #include <netinet/icmp6.h>
489a4365d0SYoshinobu Inoue 
49434d523bSKris Kennaway #include <arpa/inet.h>
50434d523bSKris Kennaway 
519a4365d0SYoshinobu Inoue #ifdef IPSEC
528409aedfSGeorge V. Neville-Neil #include <netipsec/ipsec.h>
539a4365d0SYoshinobu Inoue #endif
549a4365d0SYoshinobu Inoue 
559a4365d0SYoshinobu Inoue #include <stdio.h>
56434d523bSKris Kennaway #include <err.h>
579a4365d0SYoshinobu Inoue #include <errno.h>
589a4365d0SYoshinobu Inoue #include <stdlib.h>
599a4365d0SYoshinobu Inoue #include <unistd.h>
609a4365d0SYoshinobu Inoue #include <syslog.h>
619a4365d0SYoshinobu Inoue 
629a4365d0SYoshinobu Inoue #include "rrenumd.h"
639a4365d0SYoshinobu Inoue 
649a4365d0SYoshinobu Inoue #define LL_ALLROUTERS "ff02::2"
659a4365d0SYoshinobu Inoue #define SL_ALLROUTERS "ff05::2"
669a4365d0SYoshinobu Inoue 
6733841545SHajimu UMEMOTO #define RR_MCHLIM_DEFAULT 64
6833841545SHajimu UMEMOTO 
699a4365d0SYoshinobu Inoue #ifndef IN6_IS_SCOPE_LINKLOCAL
709a4365d0SYoshinobu Inoue #define IN6_IS_SCOPE_LINKLOCAL(a)	\
719a4365d0SYoshinobu Inoue 	((IN6_IS_ADDR_LINKLOCAL(a)) ||	\
729a4365d0SYoshinobu Inoue 	 (IN6_IS_ADDR_MC_LINKLOCAL(a)))
739a4365d0SYoshinobu Inoue #endif /* IN6_IS_SCOPE_LINKLOCAL */
749a4365d0SYoshinobu Inoue 
759a4365d0SYoshinobu Inoue struct flags {
769a4365d0SYoshinobu Inoue 	u_long debug : 1;
779a4365d0SYoshinobu Inoue 	u_long fg : 1;
789a4365d0SYoshinobu Inoue #ifdef IPSEC
799a4365d0SYoshinobu Inoue #ifdef IPSEC_POLICY_IPSEC
809a4365d0SYoshinobu Inoue 	u_long policy : 1;
81434d523bSKris Kennaway #else /* IPSEC_POLICY_IPSEC */
82434d523bSKris Kennaway 	u_long auth : 1;
83434d523bSKris Kennaway 	u_long encrypt : 1;
849a4365d0SYoshinobu Inoue #endif /* IPSEC_POLICY_IPSEC */
859a4365d0SYoshinobu Inoue #endif /*IPSEC*/
869a4365d0SYoshinobu Inoue };
879a4365d0SYoshinobu Inoue 
889a4365d0SYoshinobu Inoue struct msghdr sndmhdr;
899a4365d0SYoshinobu Inoue struct msghdr rcvmhdr;
909a4365d0SYoshinobu Inoue struct sockaddr_in6 from;
919a4365d0SYoshinobu Inoue struct sockaddr_in6 sin6_ll_allrouters;
929a4365d0SYoshinobu Inoue 
93434d523bSKris Kennaway int s4, s6;
94434d523bSKris Kennaway int with_v4dest, with_v6dest;
959a4365d0SYoshinobu Inoue struct in6_addr prefix; /* ADHOC */
969a4365d0SYoshinobu Inoue int prefixlen = 64; /* ADHOC */
979a4365d0SYoshinobu Inoue 
98784bddbcSKevin Lo extern int parse(FILE **);
9933841545SHajimu UMEMOTO 
100784bddbcSKevin Lo static void show_usage(void);
101784bddbcSKevin Lo static void init_sin6(struct sockaddr_in6 *, const char *);
10233841545SHajimu UMEMOTO #if 0
103784bddbcSKevin Lo static void join_multi(const char *);
10433841545SHajimu UMEMOTO #endif
105784bddbcSKevin Lo static void init_globals(void);
106784bddbcSKevin Lo static void config(FILE **);
10733841545SHajimu UMEMOTO #ifdef IPSEC_POLICY_IPSEC
108784bddbcSKevin Lo static void sock6_open(struct flags *, char *);
109784bddbcSKevin Lo static void sock4_open(struct flags *, char *);
11033841545SHajimu UMEMOTO #else
111784bddbcSKevin Lo static void sock6_open(struct flags *);
112784bddbcSKevin Lo static void sock4_open(struct flags *);
11333841545SHajimu UMEMOTO #endif
114784bddbcSKevin Lo static void rrenum_output(struct payload_list *, struct dst_list *);
115784bddbcSKevin Lo static void rrenum_snd_eachdst(struct payload_list *);
11633841545SHajimu UMEMOTO #if 0
117784bddbcSKevin Lo static void rrenum_snd_fullsequence(void);
11833841545SHajimu UMEMOTO #endif
119784bddbcSKevin Lo static void rrenum_input(int);
120784bddbcSKevin Lo int main(int, char *[]);
12133841545SHajimu UMEMOTO 
1229a4365d0SYoshinobu Inoue 
1239a4365d0SYoshinobu Inoue /* Print usage. Don't call this after daemonized. */
1249a4365d0SYoshinobu Inoue static void
show_usage()1259a4365d0SYoshinobu Inoue show_usage()
1269a4365d0SYoshinobu Inoue {
1279a4365d0SYoshinobu Inoue 	fprintf(stderr, "usage: rrenumd [-c conf_file|-s] [-df"
1289a4365d0SYoshinobu Inoue #ifdef IPSEC
1299a4365d0SYoshinobu Inoue #ifdef IPSEC_POLICY_IPSEC
1309a4365d0SYoshinobu Inoue 		"] [-P policy"
131434d523bSKris Kennaway #else /* IPSEC_POLICY_IPSEC */
132434d523bSKris Kennaway 		"AE"
1339a4365d0SYoshinobu Inoue #endif /* IPSEC_POLICY_IPSEC */
1349a4365d0SYoshinobu Inoue #endif /* IPSEC */
1359a4365d0SYoshinobu Inoue 		"]\n");
1369a4365d0SYoshinobu Inoue 	exit(1);
1379a4365d0SYoshinobu Inoue }
1389a4365d0SYoshinobu Inoue 
13933841545SHajimu UMEMOTO static void
init_sin6(struct sockaddr_in6 * sin6,const char * addr_ascii)1409a4365d0SYoshinobu Inoue init_sin6(struct sockaddr_in6 *sin6, const char *addr_ascii)
1419a4365d0SYoshinobu Inoue {
1429a4365d0SYoshinobu Inoue 	memset(sin6, 0, sizeof(*sin6));
1439a4365d0SYoshinobu Inoue 	sin6->sin6_len = sizeof(*sin6);
1449a4365d0SYoshinobu Inoue 	sin6->sin6_family = AF_INET6;
1459a4365d0SYoshinobu Inoue 	if (inet_pton(AF_INET6, addr_ascii, &sin6->sin6_addr) != 1)
1469a4365d0SYoshinobu Inoue 		; /* XXX do something */
1479a4365d0SYoshinobu Inoue }
1489a4365d0SYoshinobu Inoue 
149434d523bSKris Kennaway #if 0  /* XXX: not necessary ?? */
15033841545SHajimu UMEMOTO static void
151434d523bSKris Kennaway join_multi(const char *addrname)
152434d523bSKris Kennaway {
153434d523bSKris Kennaway 	struct ipv6_mreq mreq;
154434d523bSKris Kennaway 
155434d523bSKris Kennaway 	if (inet_pton(AF_INET6, addrname, &mreq.ipv6mr_multiaddr.s6_addr)
156434d523bSKris Kennaway 	    != 1) {
157434d523bSKris Kennaway 		syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
15824dcf06bSStefan Farfeleder 		       __func__);
159434d523bSKris Kennaway 		exit(1);
160434d523bSKris Kennaway 	}
161434d523bSKris Kennaway 	/* ADHOC: currently join only one */
162434d523bSKris Kennaway 	{
163434d523bSKris Kennaway 		if ((mreq.ipv6mr_interface = if_nametoindex(ifname)) == 0) {
164434d523bSKris Kennaway 			syslog(LOG_ERR, "<%s> ifname %s should be invalid: %s",
16524dcf06bSStefan Farfeleder 			       __func__, ifname, strerror(errno));
166434d523bSKris Kennaway 			exit(1);
167434d523bSKris Kennaway 		}
168434d523bSKris Kennaway 		if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP,
169434d523bSKris Kennaway 			       &mreq,
170434d523bSKris Kennaway 			       sizeof(mreq)) < 0) {
171434d523bSKris Kennaway 			syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP on %s: %s",
17224dcf06bSStefan Farfeleder 			       __func__, ifname, strerror(errno));
173434d523bSKris Kennaway 			exit(1);
174434d523bSKris Kennaway 		}
175434d523bSKris Kennaway 	}
176434d523bSKris Kennaway }
177434d523bSKris Kennaway #endif
178434d523bSKris Kennaway 
17933841545SHajimu UMEMOTO static void
init_globals()1809a4365d0SYoshinobu Inoue init_globals()
1819a4365d0SYoshinobu Inoue {
1829a4365d0SYoshinobu Inoue 	static struct iovec rcviov;
1839a4365d0SYoshinobu Inoue 	static u_char rprdata[4500]; /* maximal MTU of connected links */
184434d523bSKris Kennaway 	static u_char *rcvcmsgbuf = NULL;
185434d523bSKris Kennaway 	static u_char *sndcmsgbuf = NULL;
186434d523bSKris Kennaway 	int sndcmsglen, rcvcmsglen;
1879a4365d0SYoshinobu Inoue 
1889a4365d0SYoshinobu Inoue 	/* init ll_allrouters */
1899a4365d0SYoshinobu Inoue 	init_sin6(&sin6_ll_allrouters, LL_ALLROUTERS);
1909a4365d0SYoshinobu Inoue 
1919a4365d0SYoshinobu Inoue 	/* initialize msghdr for receiving packets */
1929a4365d0SYoshinobu Inoue 	rcviov.iov_base = (caddr_t)rprdata;
1939a4365d0SYoshinobu Inoue 	rcviov.iov_len = sizeof(rprdata);
1949a4365d0SYoshinobu Inoue 	rcvmhdr.msg_namelen = sizeof(struct sockaddr_in6);
1959a4365d0SYoshinobu Inoue 	rcvmhdr.msg_iov = &rcviov;
1969a4365d0SYoshinobu Inoue 	rcvmhdr.msg_iovlen = 1;
197434d523bSKris Kennaway 	rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
198434d523bSKris Kennaway 		CMSG_SPACE(sizeof(int));
199434d523bSKris Kennaway 	if (rcvcmsgbuf == NULL &&
200434d523bSKris Kennaway 	    (rcvcmsgbuf = (u_char *)malloc(rcvcmsglen)) == NULL) {
20124dcf06bSStefan Farfeleder 		syslog(LOG_ERR, "<%s>: malloc failed", __func__);
202434d523bSKris Kennaway 		exit(1);
203434d523bSKris Kennaway 	}
2049a4365d0SYoshinobu Inoue 	rcvmhdr.msg_control = (caddr_t)rcvcmsgbuf;
205434d523bSKris Kennaway 	rcvmhdr.msg_controllen = rcvcmsglen;
2069a4365d0SYoshinobu Inoue 
2079a4365d0SYoshinobu Inoue 	/* initialize msghdr for sending packets */
2089a4365d0SYoshinobu Inoue 	sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
2099a4365d0SYoshinobu Inoue 	sndmhdr.msg_iovlen = 1;
210434d523bSKris Kennaway 	sndcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
211434d523bSKris Kennaway 		CMSG_SPACE(sizeof(int));
212434d523bSKris Kennaway 	if (sndcmsgbuf == NULL &&
213434d523bSKris Kennaway 	    (sndcmsgbuf = (u_char *)malloc(sndcmsglen)) == NULL) {
21424dcf06bSStefan Farfeleder 		syslog(LOG_ERR, "<%s>: malloc failed", __func__);
215434d523bSKris Kennaway 		exit(1);
216434d523bSKris Kennaway 	}
2179a4365d0SYoshinobu Inoue 	sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
218434d523bSKris Kennaway 	sndmhdr.msg_controllen = sndcmsglen;
2199a4365d0SYoshinobu Inoue }
2209a4365d0SYoshinobu Inoue 
22133841545SHajimu UMEMOTO static void
config(FILE ** fpp)2229a4365d0SYoshinobu Inoue config(FILE **fpp)
2239a4365d0SYoshinobu Inoue {
2249a4365d0SYoshinobu Inoue 	struct payload_list *pl;
2259a4365d0SYoshinobu Inoue 	struct iovec *iov;
2269a4365d0SYoshinobu Inoue 	struct icmp6_router_renum *irr;
2279a4365d0SYoshinobu Inoue 	struct rr_pco_match *rpm;
2289a4365d0SYoshinobu Inoue 
2299a4365d0SYoshinobu Inoue 	if (parse(fpp) < 0) {
23024dcf06bSStefan Farfeleder 		syslog(LOG_ERR, "<%s> parse failed", __func__);
2319a4365d0SYoshinobu Inoue 		exit(1);
2329a4365d0SYoshinobu Inoue 	}
2339a4365d0SYoshinobu Inoue 
2349a4365d0SYoshinobu Inoue 	/* initialize fields not configured by parser */
2359a4365d0SYoshinobu Inoue 	for (pl = pl_head; pl; pl = pl->pl_next) {
2369a4365d0SYoshinobu Inoue 		iov = (struct iovec *)&pl->pl_sndiov;
2379a4365d0SYoshinobu Inoue 		irr = (struct icmp6_router_renum *)&pl->pl_irr;
2389a4365d0SYoshinobu Inoue 		rpm = (struct rr_pco_match *)&pl->pl_rpm;
2399a4365d0SYoshinobu Inoue 
2409a4365d0SYoshinobu Inoue 		irr->rr_type = ICMP6_ROUTER_RENUMBERING;
2419a4365d0SYoshinobu Inoue 		irr->rr_code = 0;
2429a4365d0SYoshinobu Inoue 		/*
2439a4365d0SYoshinobu Inoue 		 * now we don't support multiple PCOs in a rr message.
2449a4365d0SYoshinobu Inoue 		 * so segment number is not supported.
2459a4365d0SYoshinobu Inoue 		 */
2469a4365d0SYoshinobu Inoue 		/* TODO: rr flags config in parser */
2479a4365d0SYoshinobu Inoue 		irr->rr_flags |= ICMP6_RR_FLAGS_SPECSITE;
2489a4365d0SYoshinobu Inoue 		/* TODO: max delay config in parser */
2499a4365d0SYoshinobu Inoue 
2509a4365d0SYoshinobu Inoue 		/*
2519a4365d0SYoshinobu Inoue 		 * means only 1 use_prefix is contained as router-renum-05.txt.
2529a4365d0SYoshinobu Inoue 		 * now we don't support multiple PCOs in a rr message,
2539a4365d0SYoshinobu Inoue 		 * nor multiple use_prefix in one PCO.
2549a4365d0SYoshinobu Inoue 		 */
2559a4365d0SYoshinobu Inoue 		rpm->rpm_len = 4*1 +3;
2569a4365d0SYoshinobu Inoue 		rpm->rpm_ordinal = 0;
2579a4365d0SYoshinobu Inoue 		iov->iov_base = (caddr_t)irr;
2589a4365d0SYoshinobu Inoue 		iov->iov_len =  sizeof(struct icmp6_router_renum)
2599a4365d0SYoshinobu Inoue 			+ sizeof(struct rr_pco_match)
2609a4365d0SYoshinobu Inoue 			+ sizeof(struct rr_pco_use);
2619a4365d0SYoshinobu Inoue 	}
2629a4365d0SYoshinobu Inoue }
2639a4365d0SYoshinobu Inoue 
26433841545SHajimu UMEMOTO static void
sock6_open(struct flags * flags,char * policy)2659a4365d0SYoshinobu Inoue sock6_open(struct flags *flags
2669a4365d0SYoshinobu Inoue #ifdef IPSEC_POLICY_IPSEC
2679a4365d0SYoshinobu Inoue 	   , char *policy
2689a4365d0SYoshinobu Inoue #endif /* IPSEC_POLICY_IPSEC */
2699a4365d0SYoshinobu Inoue 	   )
2709a4365d0SYoshinobu Inoue {
2719a4365d0SYoshinobu Inoue 	struct icmp6_filter filt;
272434d523bSKris Kennaway 	int on;
273434d523bSKris Kennaway #ifdef IPSEC
274434d523bSKris Kennaway #ifndef IPSEC_POLICY_IPSEC
275434d523bSKris Kennaway 	int optval;
276434d523bSKris Kennaway #endif
277434d523bSKris Kennaway #endif
2789a4365d0SYoshinobu Inoue 
2799a4365d0SYoshinobu Inoue 	if (with_v6dest == 0)
2809a4365d0SYoshinobu Inoue 		return;
2819a4365d0SYoshinobu Inoue 	if (with_v6dest &&
2829a4365d0SYoshinobu Inoue 	    (s6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
28324dcf06bSStefan Farfeleder 		syslog(LOG_ERR, "<%s> socket(v6): %s", __func__,
2849a4365d0SYoshinobu Inoue 		       strerror(errno));
2859a4365d0SYoshinobu Inoue 		exit(1);
2869a4365d0SYoshinobu Inoue 	}
2879a4365d0SYoshinobu Inoue 
288434d523bSKris Kennaway 	/*
289434d523bSKris Kennaway 	 * join all routers multicast addresses.
290434d523bSKris Kennaway 	 */
291434d523bSKris Kennaway #if 0 /* XXX: not necessary ?? */
292434d523bSKris Kennaway 	join_multi(LL_ALLROUTERS);
293434d523bSKris Kennaway 	join_multi(SL_ALLROUTERS);
294434d523bSKris Kennaway #endif
2959a4365d0SYoshinobu Inoue 
2969a4365d0SYoshinobu Inoue 	/* set icmpv6 filter */
2979a4365d0SYoshinobu Inoue 	ICMP6_FILTER_SETBLOCKALL(&filt);
2989a4365d0SYoshinobu Inoue 	ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt);
2999a4365d0SYoshinobu Inoue 	if (setsockopt(s6, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
3009a4365d0SYoshinobu Inoue 		       sizeof(filt)) < 0) {
3019a4365d0SYoshinobu Inoue 		syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s",
30224dcf06bSStefan Farfeleder 		       __func__, strerror(errno));
3039a4365d0SYoshinobu Inoue 		exit(1);
3049a4365d0SYoshinobu Inoue 	}
3059a4365d0SYoshinobu Inoue 
3069a4365d0SYoshinobu Inoue 	/* specify to tell receiving interface */
3079a4365d0SYoshinobu Inoue 	on = 1;
30887931affSHajimu UMEMOTO 	if (setsockopt(s6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
3099a4365d0SYoshinobu Inoue 		       sizeof(on)) < 0) {
31036a81187SHajimu UMEMOTO 		syslog(LOG_ERR, "<%s> IPV6_RECVPKTINFO: %s",
31124dcf06bSStefan Farfeleder 		       __func__, strerror(errno));
3129a4365d0SYoshinobu Inoue 		exit(1);
3139a4365d0SYoshinobu Inoue 	}
3149a4365d0SYoshinobu Inoue 
3159a4365d0SYoshinobu Inoue #ifdef IPSEC
3169a4365d0SYoshinobu Inoue #ifdef IPSEC_POLICY_IPSEC
3179a4365d0SYoshinobu Inoue 	if (flags->policy) {
3189a4365d0SYoshinobu Inoue 		char *buf;
3199a4365d0SYoshinobu Inoue 		buf = ipsec_set_policy(policy, strlen(policy));
3209a4365d0SYoshinobu Inoue 		if (buf == NULL)
321ffd40070SKris Kennaway 			errx(1, "%s", ipsec_strerror());
3229a4365d0SYoshinobu Inoue 		/* XXX should handle in/out bound policy. */
3239a4365d0SYoshinobu Inoue 		if (setsockopt(s6, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
3249a4365d0SYoshinobu Inoue 				buf, ipsec_get_policylen(buf)) < 0)
32533841545SHajimu UMEMOTO 			err(1, "setsockopt(IPV6_IPSEC_POLICY)");
3269a4365d0SYoshinobu Inoue 		free(buf);
3279a4365d0SYoshinobu Inoue 	}
328434d523bSKris Kennaway #else /* IPSEC_POLICY_IPSEC */
329434d523bSKris Kennaway 	if (flags->auth) {
330434d523bSKris Kennaway 		optval = IPSEC_LEVEL_REQUIRE;
331434d523bSKris Kennaway 		if (setsockopt(s6, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL,
332434d523bSKris Kennaway 			       &optval, sizeof(optval)) == -1) {
333434d523bSKris Kennaway 			syslog(LOG_ERR, "<%s> IPV6_AUTH_TRANS_LEVEL: %s",
33424dcf06bSStefan Farfeleder 			       __func__, strerror(errno));
335434d523bSKris Kennaway 			exit(1);
336434d523bSKris Kennaway 		}
337434d523bSKris Kennaway 	}
338434d523bSKris Kennaway 	if (flags->encrypt) {
339434d523bSKris Kennaway 		optval = IPSEC_LEVEL_REQUIRE;
340434d523bSKris Kennaway 		if (setsockopt(s6, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL,
341434d523bSKris Kennaway 				&optval, sizeof(optval)) == -1) {
342434d523bSKris Kennaway 			syslog(LOG_ERR, "<%s> IPV6_ESP_TRANS_LEVEL: %s",
34324dcf06bSStefan Farfeleder 			       __func__, strerror(errno));
344434d523bSKris Kennaway 			exit(1);
345434d523bSKris Kennaway 		}
346434d523bSKris Kennaway 	}
347434d523bSKris Kennaway #endif /* IPSEC_POLICY_IPSEC */
348434d523bSKris Kennaway #endif /* IPSEC */
349434d523bSKris Kennaway }
350434d523bSKris Kennaway 
35133841545SHajimu UMEMOTO static void
sock4_open(struct flags * flags,char * policy)352434d523bSKris Kennaway sock4_open(struct flags *flags
353434d523bSKris Kennaway #ifdef IPSEC_POLICY_IPSEC
354434d523bSKris Kennaway 	   , char *policy
355434d523bSKris Kennaway #endif /* IPSEC_POLICY_IPSEC */
356434d523bSKris Kennaway 	   )
357434d523bSKris Kennaway {
358434d523bSKris Kennaway #ifdef IPSEC
359434d523bSKris Kennaway #ifndef IPSEC_POLICY_IPSEC
360434d523bSKris Kennaway 	int optval;
361434d523bSKris Kennaway #endif
362434d523bSKris Kennaway #endif
363434d523bSKris Kennaway 
364434d523bSKris Kennaway 	if (with_v4dest == 0)
365434d523bSKris Kennaway 		return;
366434d523bSKris Kennaway 	if ((s4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
36724dcf06bSStefan Farfeleder 		syslog(LOG_ERR, "<%s> socket(v4): %s", __func__,
368434d523bSKris Kennaway 		       strerror(errno));
369434d523bSKris Kennaway 		exit(1);
370434d523bSKris Kennaway 	}
371434d523bSKris Kennaway 
372434d523bSKris Kennaway #if 0 /* XXX: not necessary ?? */
373434d523bSKris Kennaway 	/*
374434d523bSKris Kennaway 	 * join all routers multicast addresses.
375434d523bSKris Kennaway 	 */
376434d523bSKris Kennaway 	some_join_function();
377434d523bSKris Kennaway #endif
378434d523bSKris Kennaway 
379434d523bSKris Kennaway #ifdef IPSEC
380434d523bSKris Kennaway #ifdef IPSEC_POLICY_IPSEC
381434d523bSKris Kennaway 	if (flags->policy) {
382434d523bSKris Kennaway 		char *buf;
383434d523bSKris Kennaway 		buf = ipsec_set_policy(policy, strlen(policy));
384434d523bSKris Kennaway 		if (buf == NULL)
385ffd40070SKris Kennaway 			errx(1, "%s", ipsec_strerror());
386434d523bSKris Kennaway 		/* XXX should handle in/out bound policy. */
387434d523bSKris Kennaway 		if (setsockopt(s4, IPPROTO_IP, IP_IPSEC_POLICY,
388434d523bSKris Kennaway 				buf, ipsec_get_policylen(buf)) < 0)
38933841545SHajimu UMEMOTO 			err(1, "setsockopt(IP_IPSEC_POLICY)");
390434d523bSKris Kennaway 		free(buf);
391434d523bSKris Kennaway 	}
392434d523bSKris Kennaway #else /* IPSEC_POLICY_IPSEC */
393434d523bSKris Kennaway 	if (flags->auth) {
394434d523bSKris Kennaway 		optval = IPSEC_LEVEL_REQUIRE;
395434d523bSKris Kennaway 		if (setsockopt(s4, IPPROTO_IP, IP_AUTH_TRANS_LEVEL,
396434d523bSKris Kennaway 			       &optval, sizeof(optval)) == -1) {
397434d523bSKris Kennaway 			syslog(LOG_ERR, "<%s> IP_AUTH_TRANS_LEVEL: %s",
39824dcf06bSStefan Farfeleder 			       __func__, strerror(errno));
399434d523bSKris Kennaway 			exit(1);
400434d523bSKris Kennaway 		}
401434d523bSKris Kennaway 	}
402434d523bSKris Kennaway 	if (flags->encrypt) {
403434d523bSKris Kennaway 		optval = IPSEC_LEVEL_REQUIRE;
404434d523bSKris Kennaway 		if (setsockopt(s4, IPPROTO_IP, IP_ESP_TRANS_LEVEL,
405434d523bSKris Kennaway 				&optval, sizeof(optval)) == -1) {
406434d523bSKris Kennaway 			syslog(LOG_ERR, "<%s> IP_ESP_TRANS_LEVEL: %s",
40724dcf06bSStefan Farfeleder 			       __func__, strerror(errno));
408434d523bSKris Kennaway 			exit(1);
409434d523bSKris Kennaway 		}
410434d523bSKris Kennaway 	}
4119a4365d0SYoshinobu Inoue #endif /* IPSEC_POLICY_IPSEC */
4129a4365d0SYoshinobu Inoue #endif /* IPSEC */
4139a4365d0SYoshinobu Inoue }
4149a4365d0SYoshinobu Inoue 
41533841545SHajimu UMEMOTO static void
rrenum_output(struct payload_list * pl,struct dst_list * dl)4169a4365d0SYoshinobu Inoue rrenum_output(struct payload_list *pl, struct dst_list *dl)
4179a4365d0SYoshinobu Inoue {
4189a4365d0SYoshinobu Inoue 	int i, msglen = 0;
4199a4365d0SYoshinobu Inoue 	struct cmsghdr *cm;
4209a4365d0SYoshinobu Inoue 	struct in6_pktinfo *pi;
4219a4365d0SYoshinobu Inoue 	struct sockaddr_in6 *sin6 = NULL;
4229a4365d0SYoshinobu Inoue 
4239a4365d0SYoshinobu Inoue 	sndmhdr.msg_name = (caddr_t)dl->dl_dst;
4249a4365d0SYoshinobu Inoue 	if (dl->dl_dst->sa_family == AF_INET6)
4259a4365d0SYoshinobu Inoue 		sin6 = (struct sockaddr_in6 *)dl->dl_dst;
4269a4365d0SYoshinobu Inoue 
4279a4365d0SYoshinobu Inoue 	if (sin6 != NULL &&
42833841545SHajimu UMEMOTO 	    IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
42933841545SHajimu UMEMOTO 		int hoplimit = RR_MCHLIM_DEFAULT;
4309a4365d0SYoshinobu Inoue 
4319a4365d0SYoshinobu Inoue 		cm = CMSG_FIRSTHDR(&sndmhdr);
4329a4365d0SYoshinobu Inoue 		/* specify the outgoing interface */
4339a4365d0SYoshinobu Inoue 		cm->cmsg_level = IPPROTO_IPV6;
4349a4365d0SYoshinobu Inoue 		cm->cmsg_type = IPV6_PKTINFO;
4359a4365d0SYoshinobu Inoue 		cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
4369a4365d0SYoshinobu Inoue 		pi = (struct in6_pktinfo *)CMSG_DATA(cm);
4379a4365d0SYoshinobu Inoue 		memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));	/*XXX*/
4389a4365d0SYoshinobu Inoue 		pi->ipi6_ifindex = sin6->sin6_scope_id;
439434d523bSKris Kennaway 		msglen += CMSG_LEN(sizeof(struct in6_pktinfo));
4409a4365d0SYoshinobu Inoue 
4419a4365d0SYoshinobu Inoue 		/* specify the hop limit of the packet if dest is link local */
4429a4365d0SYoshinobu Inoue 		/* not defined by router-renum-05.txt, but maybe its OK */
4439a4365d0SYoshinobu Inoue 		cm = CMSG_NXTHDR(&sndmhdr, cm);
4449a4365d0SYoshinobu Inoue 		cm->cmsg_level = IPPROTO_IPV6;
4459a4365d0SYoshinobu Inoue 		cm->cmsg_type = IPV6_HOPLIMIT;
4469a4365d0SYoshinobu Inoue 		cm->cmsg_len = CMSG_LEN(sizeof(int));
4479a4365d0SYoshinobu Inoue 		memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
448434d523bSKris Kennaway 		msglen += CMSG_LEN(sizeof(int));
4499a4365d0SYoshinobu Inoue 	}
4509a4365d0SYoshinobu Inoue 	sndmhdr.msg_controllen = msglen;
4519a4365d0SYoshinobu Inoue 	if (sndmhdr.msg_controllen == 0)
4529a4365d0SYoshinobu Inoue 		sndmhdr.msg_control = 0;
4539a4365d0SYoshinobu Inoue 
4549a4365d0SYoshinobu Inoue 	sndmhdr.msg_iov = &pl->pl_sndiov;
455434d523bSKris Kennaway 	i = sendmsg(dl->dl_dst->sa_family == AF_INET ? s4 : s6, &sndmhdr, 0);
4569a4365d0SYoshinobu Inoue 
4579a4365d0SYoshinobu Inoue 	if (i < 0 || i != sndmhdr.msg_iov->iov_len)
45824dcf06bSStefan Farfeleder 		syslog(LOG_ERR, "<%s> sendmsg: %s", __func__,
4599a4365d0SYoshinobu Inoue 		       strerror(errno));
4609a4365d0SYoshinobu Inoue }
4619a4365d0SYoshinobu Inoue 
46233841545SHajimu UMEMOTO static void
rrenum_snd_eachdst(struct payload_list * pl)4639a4365d0SYoshinobu Inoue rrenum_snd_eachdst(struct payload_list *pl)
4649a4365d0SYoshinobu Inoue {
4659a4365d0SYoshinobu Inoue 	struct dst_list *dl;
4669a4365d0SYoshinobu Inoue 
4679a4365d0SYoshinobu Inoue 	for (dl = dl_head; dl; dl = dl->dl_next) {
4689a4365d0SYoshinobu Inoue 		rrenum_output(pl, dl);
4699a4365d0SYoshinobu Inoue 	}
4709a4365d0SYoshinobu Inoue }
4719a4365d0SYoshinobu Inoue 
47233841545SHajimu UMEMOTO #if 0
47333841545SHajimu UMEMOTO static void
4749a4365d0SYoshinobu Inoue rrenum_snd_fullsequence()
4759a4365d0SYoshinobu Inoue {
4769a4365d0SYoshinobu Inoue 	struct payload_list *pl;
4779a4365d0SYoshinobu Inoue 
4789a4365d0SYoshinobu Inoue 	for (pl = pl_head; pl; pl = pl->pl_next) {
4799a4365d0SYoshinobu Inoue 		rrenum_snd_eachdst(pl);
4809a4365d0SYoshinobu Inoue 	}
4819a4365d0SYoshinobu Inoue }
48233841545SHajimu UMEMOTO #endif
4839a4365d0SYoshinobu Inoue 
48433841545SHajimu UMEMOTO static void
rrenum_input(int s)4859a4365d0SYoshinobu Inoue rrenum_input(int s)
4869a4365d0SYoshinobu Inoue {
4879a4365d0SYoshinobu Inoue 	int i;
4889a4365d0SYoshinobu Inoue 	struct icmp6_router_renum *rr;
4899a4365d0SYoshinobu Inoue 
4909a4365d0SYoshinobu Inoue 	/* get message */
4919a4365d0SYoshinobu Inoue 	if ((i = recvmsg(s, &rcvmhdr, 0)) < 0) {
49224dcf06bSStefan Farfeleder 		syslog(LOG_ERR, "<%s> recvmsg: %s", __func__,
4939a4365d0SYoshinobu Inoue 		       strerror(errno));
4949a4365d0SYoshinobu Inoue 		return;
4959a4365d0SYoshinobu Inoue 	}
496434d523bSKris Kennaway 	if (s == s4)
497434d523bSKris Kennaway 		i -= sizeof(struct ip);
4989a4365d0SYoshinobu Inoue 	if (i < sizeof(struct icmp6_router_renum)) {
4999a4365d0SYoshinobu Inoue 		syslog(LOG_ERR, "<%s> packet size(%d) is too short",
50024dcf06bSStefan Farfeleder 		       __func__, i);
5019a4365d0SYoshinobu Inoue 		return;
5029a4365d0SYoshinobu Inoue 	}
503434d523bSKris Kennaway 	if (s == s4) {
504434d523bSKris Kennaway 		struct ip *ip = (struct ip *)rcvmhdr.msg_iov->iov_base;
505434d523bSKris Kennaway 
506434d523bSKris Kennaway 		rr = (struct icmp6_router_renum *)(ip + 1);
507434d523bSKris Kennaway 	} else /* s == s6 */
5089a4365d0SYoshinobu Inoue 		rr = (struct icmp6_router_renum *)rcvmhdr.msg_iov->iov_base;
5099a4365d0SYoshinobu Inoue 
5109a4365d0SYoshinobu Inoue 	switch(rr->rr_code) {
5119a4365d0SYoshinobu Inoue 	case ICMP6_ROUTER_RENUMBERING_COMMAND:
5129a4365d0SYoshinobu Inoue 		/* COMMAND will be processed by rtadvd */
5139a4365d0SYoshinobu Inoue 		break;
5149a4365d0SYoshinobu Inoue 	case ICMP6_ROUTER_RENUMBERING_RESULT:
5159a4365d0SYoshinobu Inoue 		/* TODO: receiving result message */
5169a4365d0SYoshinobu Inoue 		break;
5179a4365d0SYoshinobu Inoue 	default:
518434d523bSKris Kennaway 		syslog(LOG_ERR,	"<%s> received unknown code %d",
51924dcf06bSStefan Farfeleder 		       __func__, rr->rr_code);
5209a4365d0SYoshinobu Inoue 		break;
5219a4365d0SYoshinobu Inoue 	}
5229a4365d0SYoshinobu Inoue }
5239a4365d0SYoshinobu Inoue 
5249a4365d0SYoshinobu Inoue int
main(int argc,char * argv[])5259a4365d0SYoshinobu Inoue main(int argc, char *argv[])
5269a4365d0SYoshinobu Inoue {
5279a4365d0SYoshinobu Inoue 	FILE *fp = stdin;
5289a4365d0SYoshinobu Inoue 	fd_set fdset;
5299a4365d0SYoshinobu Inoue 	struct timeval timeout;
5309a4365d0SYoshinobu Inoue 	int ch, i, maxfd = 0, send_counter = 0;
5319a4365d0SYoshinobu Inoue 	struct flags flags;
5329a4365d0SYoshinobu Inoue 	struct payload_list *pl;
5339a4365d0SYoshinobu Inoue #ifdef IPSEC_POLICY_IPSEC
5349a4365d0SYoshinobu Inoue 	char *policy = NULL;
5359a4365d0SYoshinobu Inoue #endif
5369a4365d0SYoshinobu Inoue 
5379a4365d0SYoshinobu Inoue 	memset(&flags, 0, sizeof(flags));
538434d523bSKris Kennaway 	openlog("rrenumd", LOG_PID, LOG_DAEMON);
5399a4365d0SYoshinobu Inoue 
5409a4365d0SYoshinobu Inoue 	/* get options */
5419a4365d0SYoshinobu Inoue 	while ((ch = getopt(argc, argv, "c:sdf"
5429a4365d0SYoshinobu Inoue #ifdef IPSEC
5439a4365d0SYoshinobu Inoue #ifdef IPSEC_POLICY_IPSEC
54496fbd5a8SHajimu UMEMOTO 			    "P:"
545434d523bSKris Kennaway #else /* IPSEC_POLICY_IPSEC */
546434d523bSKris Kennaway 			    "AE"
5479a4365d0SYoshinobu Inoue #endif /* IPSEC_POLICY_IPSEC */
5489a4365d0SYoshinobu Inoue #endif /* IPSEC */
5499a4365d0SYoshinobu Inoue 			    )) != -1){
5509a4365d0SYoshinobu Inoue 		switch (ch) {
5519a4365d0SYoshinobu Inoue 		case 'c':
5529a4365d0SYoshinobu Inoue 			if((fp = fopen(optarg, "r")) == NULL) {
5539a4365d0SYoshinobu Inoue 				syslog(LOG_ERR,
5549a4365d0SYoshinobu Inoue 				       "<%s> config file %s open failed",
55524dcf06bSStefan Farfeleder 				       __func__, optarg);
5569a4365d0SYoshinobu Inoue 				exit(1);
5579a4365d0SYoshinobu Inoue 			}
5589a4365d0SYoshinobu Inoue 			break;
5599a4365d0SYoshinobu Inoue 		case 's':
5609a4365d0SYoshinobu Inoue 			fp = stdin;
5619a4365d0SYoshinobu Inoue 			break;
5629a4365d0SYoshinobu Inoue 		case 'd':
5639a4365d0SYoshinobu Inoue 			flags.debug = 1;
5649a4365d0SYoshinobu Inoue 			break;
5659a4365d0SYoshinobu Inoue 		case 'f':
5669a4365d0SYoshinobu Inoue 			flags.fg = 1;
5679a4365d0SYoshinobu Inoue 			break;
5689a4365d0SYoshinobu Inoue #ifdef IPSEC
5699a4365d0SYoshinobu Inoue #ifdef IPSEC_POLICY_IPSEC
5709a4365d0SYoshinobu Inoue 		case 'P':
5719a4365d0SYoshinobu Inoue 			flags.policy = 1;
5729a4365d0SYoshinobu Inoue 			policy = strdup(optarg);
5739a4365d0SYoshinobu Inoue 			break;
574434d523bSKris Kennaway #else /* IPSEC_POLICY_IPSEC */
575434d523bSKris Kennaway 		case 'A':
576434d523bSKris Kennaway 			flags.auth = 1;
577434d523bSKris Kennaway 			break;
578434d523bSKris Kennaway 		case 'E':
579434d523bSKris Kennaway 			flags.encrypt = 1;
580434d523bSKris Kennaway 			break;
5819a4365d0SYoshinobu Inoue #endif /* IPSEC_POLICY_IPSEC */
5829a4365d0SYoshinobu Inoue #endif /*IPSEC*/
5839a4365d0SYoshinobu Inoue 		default:
5849a4365d0SYoshinobu Inoue 			show_usage();
5859a4365d0SYoshinobu Inoue 		}
5869a4365d0SYoshinobu Inoue 	}
5879a4365d0SYoshinobu Inoue 	argc -= optind;
5889a4365d0SYoshinobu Inoue 	argv += optind;
5899a4365d0SYoshinobu Inoue 
5909a4365d0SYoshinobu Inoue 	/* set log level */
5919a4365d0SYoshinobu Inoue 	if (flags.debug == 0)
5929a4365d0SYoshinobu Inoue 		(void)setlogmask(LOG_UPTO(LOG_ERR));
5939a4365d0SYoshinobu Inoue 	if (flags.debug == 1)
5949a4365d0SYoshinobu Inoue 		(void)setlogmask(LOG_UPTO(LOG_INFO));
5959a4365d0SYoshinobu Inoue 
5969a4365d0SYoshinobu Inoue 	/* init global variables */
5979a4365d0SYoshinobu Inoue 	init_globals();
5989a4365d0SYoshinobu Inoue 
5999a4365d0SYoshinobu Inoue 	config(&fp);
6009a4365d0SYoshinobu Inoue 
6019a4365d0SYoshinobu Inoue 	sock6_open(&flags
6029a4365d0SYoshinobu Inoue #ifdef IPSEC_POLICY_IPSEC
6039a4365d0SYoshinobu Inoue 		   , policy
6049a4365d0SYoshinobu Inoue #endif /* IPSEC_POLICY_IPSEC */
6059a4365d0SYoshinobu Inoue 		   );
606434d523bSKris Kennaway 	sock4_open(&flags
607434d523bSKris Kennaway #ifdef IPSEC_POLICY_IPSEC
608434d523bSKris Kennaway 		   , policy
609434d523bSKris Kennaway #endif /* IPSEC_POLICY_IPSEC */
610434d523bSKris Kennaway 		   );
6119a4365d0SYoshinobu Inoue 
6129a4365d0SYoshinobu Inoue 	if (!flags.fg)
6139a4365d0SYoshinobu Inoue 		daemon(0, 0);
6149a4365d0SYoshinobu Inoue 
6159a4365d0SYoshinobu Inoue 	FD_ZERO(&fdset);
6169a4365d0SYoshinobu Inoue 	if (with_v6dest) {
6179a4365d0SYoshinobu Inoue 		FD_SET(s6, &fdset);
6189a4365d0SYoshinobu Inoue 		if (s6 > maxfd)
6199a4365d0SYoshinobu Inoue 			maxfd = s6;
6209a4365d0SYoshinobu Inoue 	}
621434d523bSKris Kennaway 	if (with_v4dest) {
622434d523bSKris Kennaway 		FD_SET(s4, &fdset);
623434d523bSKris Kennaway 		if (s4 > maxfd)
624434d523bSKris Kennaway 			maxfd = s4;
625434d523bSKris Kennaway 	}
6269a4365d0SYoshinobu Inoue 
6279a4365d0SYoshinobu Inoue 	/* ADHOC: timeout each 30seconds */
6289a4365d0SYoshinobu Inoue 	memset(&timeout, 0, sizeof(timeout));
6299a4365d0SYoshinobu Inoue 
63033841545SHajimu UMEMOTO 	/* init temporary payload_list and send_counter*/
6319a4365d0SYoshinobu Inoue 	pl = pl_head;
6329a4365d0SYoshinobu Inoue 	send_counter = retry + 1;
6339a4365d0SYoshinobu Inoue 	while (1) {
6349a4365d0SYoshinobu Inoue 		struct fd_set select_fd = fdset; /* reinitialize */
6359a4365d0SYoshinobu Inoue 
6369a4365d0SYoshinobu Inoue 		if ((i = select(maxfd + 1, &select_fd, NULL, NULL,
6379a4365d0SYoshinobu Inoue 				&timeout)) < 0){
6389a4365d0SYoshinobu Inoue 			syslog(LOG_ERR, "<%s> select: %s",
63924dcf06bSStefan Farfeleder 			       __func__, strerror(errno));
6409a4365d0SYoshinobu Inoue 			continue;
6419a4365d0SYoshinobu Inoue 		}
6429a4365d0SYoshinobu Inoue 		if (i == 0) {	/* timeout */
6439a4365d0SYoshinobu Inoue 			if (pl == NULL)
6449a4365d0SYoshinobu Inoue 				exit(0);
6459a4365d0SYoshinobu Inoue 			rrenum_snd_eachdst(pl);
6469a4365d0SYoshinobu Inoue 			send_counter--;
64733841545SHajimu UMEMOTO 			timeout.tv_sec = 30;
6489a4365d0SYoshinobu Inoue 			if (send_counter == 0) {
64933841545SHajimu UMEMOTO 				timeout.tv_sec = 0;
6509a4365d0SYoshinobu Inoue 				pl = pl->pl_next;
6519a4365d0SYoshinobu Inoue 				send_counter = retry + 1;
6529a4365d0SYoshinobu Inoue 			}
6539a4365d0SYoshinobu Inoue 		}
654434d523bSKris Kennaway 		if (FD_ISSET(s4, &select_fd))
655434d523bSKris Kennaway 			rrenum_input(s4);
6569a4365d0SYoshinobu Inoue 		if (FD_ISSET(s6, &select_fd))
6579a4365d0SYoshinobu Inoue 			rrenum_input(s6);
6589a4365d0SYoshinobu Inoue 	}
6599a4365d0SYoshinobu Inoue }
660