rrenumd.c revision 78064
172445Sassar/* $KAME: rrenumd.c,v 1.20 2000/11/08 02:40:53 itojun Exp $ */ 272445Sassar 372445Sassar/* 472445Sassar * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 572445Sassar * All rights reserved. 672445Sassar * 772445Sassar * Redistribution and use in source and binary forms, with or without 872445Sassar * modification, are permitted provided that the following conditions 972445Sassar * are met: 1072445Sassar * 1. Redistributions of source code must retain the above copyright 1172445Sassar * notice, this list of conditions and the following disclaimer. 1272445Sassar * 2. Redistributions in binary form must reproduce the above copyright 1372445Sassar * notice, this list of conditions and the following disclaimer in the 1472445Sassar * documentation and/or other materials provided with the distribution. 1572445Sassar * 3. Neither the name of the project nor the names of its contributors 1672445Sassar * may be used to endorse or promote products derived from this software 1772445Sassar * without specific prior written permission. 1872445Sassar * 1972445Sassar * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2072445Sassar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2172445Sassar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2272445Sassar * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2372445Sassar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2472445Sassar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2572445Sassar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2672445Sassar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2772445Sassar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2872445Sassar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2972445Sassar * SUCH DAMAGE. 3072445Sassar * 3172445Sassar * $FreeBSD: head/usr.sbin/rrenumd/rrenumd.c 78064 2001-06-11 12:39:29Z ume $ 3272445Sassar */ 3372445Sassar 3472445Sassar#include <sys/param.h> 3578527Sassar#include <sys/socket.h> 3672445Sassar#include <sys/uio.h> 3772445Sassar#include <sys/time.h> 3872445Sassar 3972445Sassar#include <string.h> 4072445Sassar 4172445Sassar#include <net/route.h> 4272445Sassar 4372445Sassar#include <netinet/in_systm.h> 44120945Snectar#include <netinet/in.h> 4572445Sassar#include <netinet/ip.h> 46178825Sdfr#include <netinet/ip6.h> 4772445Sassar#include <netinet/icmp6.h> 4872445Sassar 4972445Sassar#include <arpa/inet.h> 5072445Sassar 5172445Sassar#ifdef IPSEC 5272445Sassar#include <netinet6/ipsec.h> 5372445Sassar#endif 5472445Sassar 5572445Sassar#include <stdio.h> 5672445Sassar#include <err.h> 5772445Sassar#include <errno.h> 5872445Sassar#include <stdlib.h> 5972445Sassar#include <unistd.h> 6078527Sassar#include <syslog.h> 6178527Sassar 6278527Sassar#include "rrenumd.h" 6378527Sassar 6478527Sassar#define LL_ALLROUTERS "ff02::2" 65120945Snectar#define SL_ALLROUTERS "ff05::2" 6678527Sassar 6778527Sassar#define RR_MCHLIM_DEFAULT 64 6878527Sassar 6978527Sassar#ifndef IN6_IS_SCOPE_LINKLOCAL 7078527Sassar#define IN6_IS_SCOPE_LINKLOCAL(a) \ 7178527Sassar ((IN6_IS_ADDR_LINKLOCAL(a)) || \ 7278527Sassar (IN6_IS_ADDR_MC_LINKLOCAL(a))) 7378527Sassar#endif /* IN6_IS_SCOPE_LINKLOCAL */ 7478527Sassar 75178825Sdfrstruct flags { 7678527Sassar u_long debug : 1; 7778527Sassar u_long fg : 1; 7878527Sassar#ifdef IPSEC 7978527Sassar#ifdef IPSEC_POLICY_IPSEC 8078527Sassar u_long policy : 1; 8178527Sassar#else /* IPSEC_POLICY_IPSEC */ 8278527Sassar u_long auth : 1; 8378527Sassar u_long encrypt : 1; 8478527Sassar#endif /* IPSEC_POLICY_IPSEC */ 8578527Sassar#endif /*IPSEC*/ 8678527Sassar}; 8778527Sassar 8878527Sassarstruct msghdr sndmhdr; 8978527Sassarstruct msghdr rcvmhdr; 9078527Sassarstruct sockaddr_in6 from; 9178527Sassarstruct sockaddr_in6 sin6_ll_allrouters; 9272445Sassar 9378527Sassarint s4, s6; 9472445Sassarint with_v4dest, with_v6dest; 9572445Sassarstruct in6_addr prefix; /* ADHOC */ 9678527Sassarint prefixlen = 64; /* ADHOC */ 9772445Sassar 9890926Snectarextern int parse __P((FILE **)); 9978527Sassar 10078527Sassarstatic void show_usage __P((void)); 10178527Sassarstatic void init_sin6 __P((struct sockaddr_in6 *, const char *)); 10278527Sassar#if 0 10378527Sassarstatic void join_multi __P((const char *)); 10478527Sassar#endif 10578527Sassarstatic void init_globals __P((void)); 10678527Sassarstatic void config __P((FILE **)); 10778527Sassar#ifdef IPSEC_POLICY_IPSEC 10878527Sassarstatic void sock6_open __P((struct flags *, char *)); 10978527Sassarstatic void sock4_open __P((struct flags *, char *)); 11078527Sassar#else 11172445Sassarstatic void sock6_open __P((struct flags *)); 11272445Sassarstatic void sock4_open __P((struct flags *)); 11372445Sassar#endif 11472445Sassarstatic void rrenum_output __P((struct payload_list *, struct dst_list *)); 11572445Sassarstatic void rrenum_snd_eachdst __P((struct payload_list *)); 11672445Sassar#if 0 11772445Sassarstatic void rrenum_snd_fullsequence __P((void)); 11872445Sassar#endif 11972445Sassarstatic void rrenum_input __P((int)); 12072445Sassarint main __P((int, char *[])); 12178527Sassar 122178825Sdfr 123178825Sdfr/* Print usage. Don't call this after daemonized. */ 12472445Sassarstatic void 12572445Sassarshow_usage() 12672445Sassar{ 12772445Sassar fprintf(stderr, "usage: rrenumd [-c conf_file|-s] [-df" 12872445Sassar#ifdef IPSEC 129178825Sdfr#ifdef IPSEC_POLICY_IPSEC 130178825Sdfr "] [-P policy" 13172445Sassar#else /* IPSEC_POLICY_IPSEC */ 13272445Sassar "AE" 13372445Sassar#endif /* IPSEC_POLICY_IPSEC */ 13472445Sassar#endif /* IPSEC */ 13572445Sassar "]\n"); 13678527Sassar exit(1); 13772445Sassar} 13872445Sassar 13972445Sassarstatic void 14072445Sassarinit_sin6(struct sockaddr_in6 *sin6, const char *addr_ascii) 14172445Sassar{ 14290926Snectar memset(sin6, 0, sizeof(*sin6)); 14390926Snectar sin6->sin6_len = sizeof(*sin6); 14490926Snectar sin6->sin6_family = AF_INET6; 14572445Sassar if (inet_pton(AF_INET6, addr_ascii, &sin6->sin6_addr) != 1) 14678527Sassar ; /* XXX do something */ 14772445Sassar} 14872445Sassar 14972445Sassar#if 0 /* XXX: not necessary ?? */ 15072445Sassarstatic void 15172445Sassarjoin_multi(const char *addrname) 15272445Sassar{ 15372445Sassar struct ipv6_mreq mreq; 15472445Sassar 15572445Sassar if (inet_pton(AF_INET6, addrname, &mreq.ipv6mr_multiaddr.s6_addr) 15672445Sassar != 1) { 15772445Sassar syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)", 15872445Sassar __FUNCTION__); 15978527Sassar exit(1); 16072445Sassar } 16190926Snectar /* ADHOC: currently join only one */ 16272445Sassar { 16372445Sassar if ((mreq.ipv6mr_interface = if_nametoindex(ifname)) == 0) { 16472445Sassar syslog(LOG_ERR, "<%s> ifname %s should be invalid: %s", 16572445Sassar __FUNCTION__, ifname, strerror(errno)); 16672445Sassar exit(1); 16772445Sassar } 16872445Sassar if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, 16972445Sassar &mreq, 17072445Sassar sizeof(mreq)) < 0) { 17172445Sassar syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP on %s: %s", 17272445Sassar __FUNCTION__, ifname, strerror(errno)); 17372445Sassar exit(1); 17472445Sassar } 17572445Sassar } 17672445Sassar} 17772445Sassar#endif 17872445Sassar 17972445Sassarstatic void 18072445Sassarinit_globals() 18172445Sassar{ 18272445Sassar static struct iovec rcviov; 18372445Sassar static u_char rprdata[4500]; /* maximal MTU of connected links */ 184178825Sdfr static u_char *rcvcmsgbuf = NULL; 18572445Sassar static u_char *sndcmsgbuf = NULL; 18672445Sassar int sndcmsglen, rcvcmsglen; 18772445Sassar 18872445Sassar /* init ll_allrouters */ 18972445Sassar init_sin6(&sin6_ll_allrouters, LL_ALLROUTERS); 19090926Snectar 19172445Sassar /* initialize msghdr for receiving packets */ 19272445Sassar rcviov.iov_base = (caddr_t)rprdata; 19372445Sassar rcviov.iov_len = sizeof(rprdata); 19472445Sassar rcvmhdr.msg_namelen = sizeof(struct sockaddr_in6); 19572445Sassar rcvmhdr.msg_iov = &rcviov; 196178825Sdfr rcvmhdr.msg_iovlen = 1; 197178825Sdfr rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 198178825Sdfr CMSG_SPACE(sizeof(int)); 199178825Sdfr if (rcvcmsgbuf == NULL && 20072445Sassar (rcvcmsgbuf = (u_char *)malloc(rcvcmsglen)) == NULL) { 20172445Sassar syslog(LOG_ERR, "<%s>: malloc failed", __FUNCTION__); 20290926Snectar exit(1); 203178825Sdfr } 204178825Sdfr rcvmhdr.msg_control = (caddr_t)rcvcmsgbuf; 205178825Sdfr rcvmhdr.msg_controllen = rcvcmsglen; 206178825Sdfr 207178825Sdfr /* initialize msghdr for sending packets */ 208178825Sdfr sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); 20990926Snectar sndmhdr.msg_iovlen = 1; 210178825Sdfr sndcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 21190926Snectar CMSG_SPACE(sizeof(int)); 21278527Sassar if (sndcmsgbuf == NULL && 21378527Sassar (sndcmsgbuf = (u_char *)malloc(sndcmsglen)) == NULL) { 21472445Sassar syslog(LOG_ERR, "<%s>: malloc failed", __FUNCTION__); 21572445Sassar exit(1); 216178825Sdfr } 21790926Snectar sndmhdr.msg_control = (caddr_t)sndcmsgbuf; 21872445Sassar sndmhdr.msg_controllen = sndcmsglen; 21972445Sassar} 22072445Sassar 22172445Sassarstatic void 22272445Sassarconfig(FILE **fpp) 22372445Sassar{ 22472445Sassar struct payload_list *pl; 22578527Sassar struct iovec *iov; 226178825Sdfr struct icmp6_router_renum *irr; 227178825Sdfr struct rr_pco_match *rpm; 22872445Sassar 22972445Sassar if (parse(fpp) < 0) { 23072445Sassar syslog(LOG_ERR, "<%s> parse failed", __FUNCTION__); 23172445Sassar exit(1); 23272445Sassar } 23372445Sassar 23472445Sassar /* initialize fields not configured by parser */ 23578527Sassar for (pl = pl_head; pl; pl = pl->pl_next) { 23672445Sassar iov = (struct iovec *)&pl->pl_sndiov; 23790926Snectar irr = (struct icmp6_router_renum *)&pl->pl_irr; 23872445Sassar rpm = (struct rr_pco_match *)&pl->pl_rpm; 23972445Sassar 24072445Sassar irr->rr_type = ICMP6_ROUTER_RENUMBERING; 241178825Sdfr irr->rr_code = 0; 242178825Sdfr /* 24372445Sassar * now we don't support multiple PCOs in a rr message. 244178825Sdfr * so segment number is not supported. 24572445Sassar */ 24672445Sassar /* TODO: rr flags config in parser */ 247178825Sdfr irr->rr_flags |= ICMP6_RR_FLAGS_SPECSITE; 24890926Snectar /* TODO: max delay config in parser */ 24972445Sassar 25072445Sassar /* 25178527Sassar * means only 1 use_prefix is contained as router-renum-05.txt. 25272445Sassar * now we don't support multiple PCOs in a rr message, 25372445Sassar * nor multiple use_prefix in one PCO. 25472445Sassar */ 25572445Sassar rpm->rpm_len = 4*1 +3; 25672445Sassar rpm->rpm_ordinal = 0; 25772445Sassar iov->iov_base = (caddr_t)irr; 25872445Sassar iov->iov_len = sizeof(struct icmp6_router_renum) 25972445Sassar + sizeof(struct rr_pco_match) 26072445Sassar + sizeof(struct rr_pco_use); 26172445Sassar } 26272445Sassar} 26372445Sassar 26472445Sassarstatic void 26572445Sassarsock6_open(struct flags *flags 26672445Sassar#ifdef IPSEC_POLICY_IPSEC 26772445Sassar , char *policy 268178825Sdfr#endif /* IPSEC_POLICY_IPSEC */ 269178825Sdfr ) 27090926Snectar{ 27172445Sassar struct icmp6_filter filt; 27278527Sassar int on; 27372445Sassar#ifdef IPSEC 27472445Sassar#ifndef IPSEC_POLICY_IPSEC 27572445Sassar int optval; 27678527Sassar#endif 27772445Sassar#endif 278178825Sdfr 279178825Sdfr if (with_v6dest == 0) 28078527Sassar return; 28172445Sassar if (with_v6dest && 28272445Sassar (s6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { 28372445Sassar syslog(LOG_ERR, "<%s> socket(v6): %s", __FUNCTION__, 28472445Sassar strerror(errno)); 28572445Sassar exit(1); 28678527Sassar } 28772445Sassar 28872445Sassar /* 28972445Sassar * join all routers multicast addresses. 29072445Sassar */ 29172445Sassar#if 0 /* XXX: not necessary ?? */ 29272445Sassar join_multi(LL_ALLROUTERS); 29372445Sassar join_multi(SL_ALLROUTERS); 29472445Sassar#endif 29572445Sassar 29672445Sassar /* set icmpv6 filter */ 29772445Sassar ICMP6_FILTER_SETBLOCKALL(&filt); 29872445Sassar ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt); 29972445Sassar if (setsockopt(s6, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, 30072445Sassar sizeof(filt)) < 0) { 30172445Sassar syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s", 30272445Sassar __FUNCTION__, strerror(errno)); 30372445Sassar exit(1); 30472445Sassar } 30572445Sassar 30672445Sassar /* specify to tell receiving interface */ 30772445Sassar on = 1; 30872445Sassar if (setsockopt(s6, IPPROTO_IPV6, IPV6_PKTINFO, &on, 30972445Sassar sizeof(on)) < 0) { 31072445Sassar syslog(LOG_ERR, "<%s> IPV6_PKTINFO: %s", 31172445Sassar __FUNCTION__, strerror(errno)); 31272445Sassar exit(1); 31372445Sassar } 31472445Sassar 31572445Sassar#ifdef IPSEC 31672445Sassar#ifdef IPSEC_POLICY_IPSEC 31772445Sassar if (flags->policy) { 31872445Sassar char *buf; 31972445Sassar buf = ipsec_set_policy(policy, strlen(policy)); 32072445Sassar if (buf == NULL) 32172445Sassar errx(1, "%s", ipsec_strerror()); 32272445Sassar /* XXX should handle in/out bound policy. */ 32372445Sassar if (setsockopt(s6, IPPROTO_IPV6, IPV6_IPSEC_POLICY, 32472445Sassar buf, ipsec_get_policylen(buf)) < 0) 32578527Sassar err(1, "setsockopt(IPV6_IPSEC_POLICY)"); 32672445Sassar free(buf); 32772445Sassar } 32878527Sassar#else /* IPSEC_POLICY_IPSEC */ 32972445Sassar if (flags->auth) { 33072445Sassar optval = IPSEC_LEVEL_REQUIRE; 33172445Sassar if (setsockopt(s6, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, 332178825Sdfr &optval, sizeof(optval)) == -1) { 33372445Sassar syslog(LOG_ERR, "<%s> IPV6_AUTH_TRANS_LEVEL: %s", 33490926Snectar __FUNCTION__, strerror(errno)); 33590926Snectar exit(1); 33690926Snectar } 33790926Snectar } 33878527Sassar if (flags->encrypt) { 33972445Sassar optval = IPSEC_LEVEL_REQUIRE; 34072445Sassar if (setsockopt(s6, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, 34172445Sassar &optval, sizeof(optval)) == -1) { 34278527Sassar syslog(LOG_ERR, "<%s> IPV6_ESP_TRANS_LEVEL: %s", 34372445Sassar __FUNCTION__, strerror(errno)); 34472445Sassar exit(1); 34572445Sassar } 34672445Sassar } 34772445Sassar#endif /* IPSEC_POLICY_IPSEC */ 34872445Sassar#endif /* IPSEC */ 34972445Sassar 35072445Sassar return; 35172445Sassar} 35272445Sassar 35372445Sassarstatic void 35472445Sassarsock4_open(struct flags *flags 35572445Sassar#ifdef IPSEC_POLICY_IPSEC 35672445Sassar , char *policy 35778527Sassar#endif /* IPSEC_POLICY_IPSEC */ 35872445Sassar ) 35972445Sassar{ 36072445Sassar#ifdef IPSEC 36172445Sassar#ifndef IPSEC_POLICY_IPSEC 36272445Sassar int optval; 36372445Sassar#endif 36472445Sassar#endif 36572445Sassar 36672445Sassar if (with_v4dest == 0) 36778527Sassar return; 36872445Sassar if ((s4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { 36972445Sassar syslog(LOG_ERR, "<%s> socket(v4): %s", __FUNCTION__, 37078527Sassar strerror(errno)); 37172445Sassar exit(1); 37272445Sassar } 37372445Sassar 37472445Sassar#if 0 /* XXX: not necessary ?? */ 37578527Sassar /* 37672445Sassar * join all routers multicast addresses. 37772445Sassar */ 37872445Sassar some_join_function(); 37972445Sassar#endif 38072445Sassar 38172445Sassar#ifdef IPSEC 38272445Sassar#ifdef IPSEC_POLICY_IPSEC 38372445Sassar if (flags->policy) { 38472445Sassar char *buf; 38572445Sassar buf = ipsec_set_policy(policy, strlen(policy)); 38672445Sassar if (buf == NULL) 38772445Sassar errx(1, "%s", ipsec_strerror()); 38872445Sassar /* XXX should handle in/out bound policy. */ 38972445Sassar if (setsockopt(s4, IPPROTO_IP, IP_IPSEC_POLICY, 39072445Sassar buf, ipsec_get_policylen(buf)) < 0) 39178527Sassar err(1, "setsockopt(IP_IPSEC_POLICY)"); 39272445Sassar free(buf); 39372445Sassar } 39478527Sassar#else /* IPSEC_POLICY_IPSEC */ 39572445Sassar if (flags->auth) { 39672445Sassar optval = IPSEC_LEVEL_REQUIRE; 39772445Sassar if (setsockopt(s4, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, 39872445Sassar &optval, sizeof(optval)) == -1) { 39972445Sassar syslog(LOG_ERR, "<%s> IP_AUTH_TRANS_LEVEL: %s", 40078527Sassar __FUNCTION__, strerror(errno)); 40172445Sassar exit(1); 40278527Sassar } 40372445Sassar } 40472445Sassar if (flags->encrypt) { 40572445Sassar optval = IPSEC_LEVEL_REQUIRE; 40672445Sassar if (setsockopt(s4, IPPROTO_IP, IP_ESP_TRANS_LEVEL, 40772445Sassar &optval, sizeof(optval)) == -1) { 40872445Sassar syslog(LOG_ERR, "<%s> IP_ESP_TRANS_LEVEL: %s", 40972445Sassar __FUNCTION__, strerror(errno)); 41072445Sassar exit(1); 41172445Sassar } 41272445Sassar } 41372445Sassar#endif /* IPSEC_POLICY_IPSEC */ 41472445Sassar#endif /* IPSEC */ 41572445Sassar 41678527Sassar return; 41772445Sassar} 41872445Sassar 41972445Sassarstatic void 42078527Sassarrrenum_output(struct payload_list *pl, struct dst_list *dl) 42178527Sassar{ 42278527Sassar int i, msglen = 0; 42372445Sassar struct cmsghdr *cm; 42472445Sassar struct in6_pktinfo *pi; 42572445Sassar struct sockaddr_in6 *sin6 = NULL; 42678527Sassar 42772445Sassar sndmhdr.msg_name = (caddr_t)dl->dl_dst; 42872445Sassar if (dl->dl_dst->sa_family == AF_INET6) 42972445Sassar sin6 = (struct sockaddr_in6 *)dl->dl_dst; 43072445Sassar 43172445Sassar if (sin6 != NULL && 43272445Sassar IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 43372445Sassar int hoplimit = RR_MCHLIM_DEFAULT; 43472445Sassar 43572445Sassar cm = CMSG_FIRSTHDR(&sndmhdr); 43672445Sassar /* specify the outgoing interface */ 43772445Sassar cm->cmsg_level = IPPROTO_IPV6; 43872445Sassar cm->cmsg_type = IPV6_PKTINFO; 43972445Sassar cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 44072445Sassar pi = (struct in6_pktinfo *)CMSG_DATA(cm); 44172445Sassar memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/ 44272445Sassar pi->ipi6_ifindex = sin6->sin6_scope_id; 44372445Sassar msglen += CMSG_LEN(sizeof(struct in6_pktinfo)); 44472445Sassar 44578527Sassar /* specify the hop limit of the packet if dest is link local */ 44672445Sassar /* not defined by router-renum-05.txt, but maybe its OK */ 44772445Sassar cm = CMSG_NXTHDR(&sndmhdr, cm); 44872445Sassar cm->cmsg_level = IPPROTO_IPV6; 44972445Sassar cm->cmsg_type = IPV6_HOPLIMIT; 45072445Sassar cm->cmsg_len = CMSG_LEN(sizeof(int)); 45172445Sassar memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); 45272445Sassar msglen += CMSG_LEN(sizeof(int)); 45378527Sassar } 45472445Sassar sndmhdr.msg_controllen = msglen; 45572445Sassar if (sndmhdr.msg_controllen == 0) 45672445Sassar sndmhdr.msg_control = 0; 45772445Sassar 45872445Sassar sndmhdr.msg_iov = &pl->pl_sndiov; 45972445Sassar i = sendmsg(dl->dl_dst->sa_family == AF_INET ? s4 : s6, &sndmhdr, 0); 46072445Sassar 46172445Sassar if (i < 0 || i != sndmhdr.msg_iov->iov_len) 46272445Sassar syslog(LOG_ERR, "<%s> sendmsg: %s", __FUNCTION__, 46372445Sassar strerror(errno)); 46472445Sassar} 46572445Sassar 46672445Sassarstatic void 46772445Sassarrrenum_snd_eachdst(struct payload_list *pl) 46872445Sassar{ 46972445Sassar struct dst_list *dl; 47072445Sassar 47178527Sassar for (dl = dl_head; dl; dl = dl->dl_next) { 47272445Sassar rrenum_output(pl, dl); 47372445Sassar } 47472445Sassar} 47572445Sassar 47672445Sassar#if 0 47772445Sassarstatic void 47872445Sassarrrenum_snd_fullsequence() 47978527Sassar{ 48072445Sassar struct payload_list *pl; 48172445Sassar 48272445Sassar for (pl = pl_head; pl; pl = pl->pl_next) { 48372445Sassar rrenum_snd_eachdst(pl); 48472445Sassar } 48572445Sassar} 48672445Sassar#endif 48772445Sassar 48872445Sassarstatic void 48972445Sassarrrenum_input(int s) 49072445Sassar{ 49172445Sassar int i; 49272445Sassar struct icmp6_router_renum *rr; 49372445Sassar 49472445Sassar /* get message */ 49572445Sassar if ((i = recvmsg(s, &rcvmhdr, 0)) < 0) { 49672445Sassar syslog(LOG_ERR, "<%s> recvmsg: %s", __FUNCTION__, 49772445Sassar strerror(errno)); 49872445Sassar return; 49972445Sassar } 50072445Sassar if (s == s4) 50172445Sassar i -= sizeof(struct ip); 50278527Sassar if (i < sizeof(struct icmp6_router_renum)) { 50372445Sassar syslog(LOG_ERR, "<%s> packet size(%d) is too short", 50472445Sassar __FUNCTION__, i); 50572445Sassar return; 50672445Sassar } 50772445Sassar if (s == s4) { 50872445Sassar struct ip *ip = (struct ip *)rcvmhdr.msg_iov->iov_base; 50972445Sassar 51072445Sassar rr = (struct icmp6_router_renum *)(ip + 1); 51172445Sassar } else /* s == s6 */ 51272445Sassar rr = (struct icmp6_router_renum *)rcvmhdr.msg_iov->iov_base; 51372445Sassar 51472445Sassar switch(rr->rr_code) { 51572445Sassar case ICMP6_ROUTER_RENUMBERING_COMMAND: 51672445Sassar /* COMMAND will be processed by rtadvd */ 51772445Sassar break; 51872445Sassar case ICMP6_ROUTER_RENUMBERING_RESULT: 51972445Sassar /* TODO: receiving result message */ 52072445Sassar break; 52172445Sassar default: 52272445Sassar syslog(LOG_ERR, "<%s> received unknown code %d", 52372445Sassar __FUNCTION__, rr->rr_code); 52472445Sassar break; 52572445Sassar } 52672445Sassar} 52772445Sassar 52890926Snectarint 52972445Sassarmain(int argc, char *argv[]) 53072445Sassar{ 53172445Sassar FILE *fp = stdin; 53272445Sassar fd_set fdset; 53372445Sassar struct timeval timeout; 53472445Sassar int ch, i, maxfd = 0, send_counter = 0; 53572445Sassar struct flags flags; 53672445Sassar struct payload_list *pl; 53772445Sassar#ifdef IPSEC_POLICY_IPSEC 53872445Sassar char *policy = NULL; 53972445Sassar#endif 54072445Sassar 54172445Sassar memset(&flags, 0, sizeof(flags)); 54278527Sassar openlog("rrenumd", LOG_PID, LOG_DAEMON); 54372445Sassar 54472445Sassar /* get options */ 54572445Sassar while ((ch = getopt(argc, argv, "c:sdf" 54672445Sassar#ifdef IPSEC 54772445Sassar#ifdef IPSEC_POLICY_IPSEC 54872445Sassar "P" 54972445Sassar#else /* IPSEC_POLICY_IPSEC */ 55072445Sassar "AE" 55172445Sassar#endif /* IPSEC_POLICY_IPSEC */ 55272445Sassar#endif /* IPSEC */ 55372445Sassar )) != -1){ 55472445Sassar switch (ch) { 55572445Sassar case 'c': 55678527Sassar if((fp = fopen(optarg, "r")) == NULL) { 55772445Sassar syslog(LOG_ERR, 55872445Sassar "<%s> config file %s open failed", 55972445Sassar __FUNCTION__, optarg); 56072445Sassar exit(1); 56172445Sassar } 56272445Sassar break; 56372445Sassar case 's': 56472445Sassar fp = stdin; 56572445Sassar break; 56672445Sassar case 'd': 56772445Sassar flags.debug = 1; 56872445Sassar break; 56972445Sassar case 'f': 57072445Sassar flags.fg = 1; 57172445Sassar break; 57278527Sassar#ifdef IPSEC 57372445Sassar#ifdef IPSEC_POLICY_IPSEC 57472445Sassar case 'P': 57572445Sassar flags.policy = 1; 57672445Sassar policy = strdup(optarg); 57772445Sassar break; 57872445Sassar#else /* IPSEC_POLICY_IPSEC */ 57972445Sassar case 'A': 58072445Sassar flags.auth = 1; 58178527Sassar break; 58272445Sassar case 'E': 58378527Sassar flags.encrypt = 1; 58472445Sassar break; 58572445Sassar#endif /* IPSEC_POLICY_IPSEC */ 58672445Sassar#endif /*IPSEC*/ 58772445Sassar default: 58872445Sassar show_usage(); 58972445Sassar } 59072445Sassar } 59172445Sassar argc -= optind; 59272445Sassar argv += optind; 59378527Sassar 59478527Sassar /* set log level */ 59578527Sassar if (flags.debug == 0) 59678527Sassar (void)setlogmask(LOG_UPTO(LOG_ERR)); 59778527Sassar if (flags.debug == 1) 59878527Sassar (void)setlogmask(LOG_UPTO(LOG_INFO)); 59978527Sassar 60072445Sassar /* init global variables */ 60172445Sassar init_globals(); 60272445Sassar 60372445Sassar config(&fp); 60472445Sassar 60572445Sassar sock6_open(&flags 60672445Sassar#ifdef IPSEC_POLICY_IPSEC 60772445Sassar , policy 60872445Sassar#endif /* IPSEC_POLICY_IPSEC */ 60972445Sassar ); 61072445Sassar sock4_open(&flags 61172445Sassar#ifdef IPSEC_POLICY_IPSEC 61272445Sassar , policy 61372445Sassar#endif /* IPSEC_POLICY_IPSEC */ 61472445Sassar ); 61572445Sassar 61672445Sassar if (!flags.fg) 61772445Sassar daemon(0, 0); 61872445Sassar 61972445Sassar FD_ZERO(&fdset); 62072445Sassar if (with_v6dest) { 62172445Sassar FD_SET(s6, &fdset); 62272445Sassar if (s6 > maxfd) 62372445Sassar maxfd = s6; 62472445Sassar } 62572445Sassar if (with_v4dest) { 62672445Sassar FD_SET(s4, &fdset); 62772445Sassar if (s4 > maxfd) 62872445Sassar maxfd = s4; 62972445Sassar } 63072445Sassar 63172445Sassar /* ADHOC: timeout each 30seconds */ 63272445Sassar memset(&timeout, 0, sizeof(timeout)); 63378527Sassar 63478527Sassar /* init temporary payload_list and send_counter*/ 63572445Sassar pl = pl_head; 63672445Sassar send_counter = retry + 1; 63772445Sassar while (1) { 63872445Sassar struct fd_set select_fd = fdset; /* reinitialize */ 63972445Sassar 64072445Sassar if ((i = select(maxfd + 1, &select_fd, NULL, NULL, 64172445Sassar &timeout)) < 0){ 64272445Sassar syslog(LOG_ERR, "<%s> select: %s", 64372445Sassar __FUNCTION__, strerror(errno)); 64472445Sassar continue; 64572445Sassar } 64672445Sassar if (i == 0) { /* timeout */ 64772445Sassar if (pl == NULL) 64878527Sassar exit(0); 64972445Sassar rrenum_snd_eachdst(pl); 65072445Sassar send_counter--; 65172445Sassar timeout.tv_sec = 30; 65272445Sassar if (send_counter == 0) { 65372445Sassar timeout.tv_sec = 0; 65472445Sassar pl = pl->pl_next; 65572445Sassar send_counter = retry + 1; 65672445Sassar } 65772445Sassar } 65872445Sassar if (FD_ISSET(s4, &select_fd)) 65972445Sassar rrenum_input(s4); 66078527Sassar if (FD_ISSET(s6, &select_fd)) 66172445Sassar rrenum_input(s6); 66272445Sassar } 66372445Sassar} 66472445Sassar