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