Obtained from:	KAME
This commit is contained in:
Hajimu UMEMOTO 2002-06-01 17:28:12 +00:00
parent 511dab6218
commit 99a92b2c8a

View File

@ -168,36 +168,36 @@ main(argc, argv)
#endif #endif
while ((ch = getopt(argc, argv, OPTIONS)) != -1) { while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
#undef OPTIONS #undef OPTIONS
switch(ch) { switch (ch) {
case 'c': case 'c':
conffile = optarg; conffile = optarg;
break; break;
case 'd': case 'd':
dflag = 1; dflag = 1;
break; break;
case 'D': case 'D':
dflag = 2; dflag = 2;
break; break;
case 'f': case 'f':
fflag = 1; fflag = 1;
break; break;
case 'M': case 'M':
mcastif = optarg; mcastif = optarg;
break; break;
#ifdef MIP6 #ifdef MIP6
case 'm': case 'm':
mobileip6 = 1; mobileip6 = 1;
break; break;
#endif #endif
case 'R': case 'R':
fprintf(stderr, "rtadvd: " fprintf(stderr, "rtadvd: "
"the -R option is currently ignored.\n"); "the -R option is currently ignored.\n");
/* accept_rr = 1; */ /* accept_rr = 1; */
/* run anyway... */ /* run anyway... */
break; break;
case 's': case 's':
sflag = 1; sflag = 1;
break; break;
} }
} }
argc -= optind; argc -= optind;
@ -242,11 +242,11 @@ main(argc, argv)
/* record the current PID */ /* record the current PID */
pid = getpid(); pid = getpid();
if ((pidfp = fopen(pidfilename, "w")) == NULL) if ((pidfp = fopen(pidfilename, "w")) == NULL) {
syslog(LOG_ERR, syslog(LOG_ERR,
"<%s> failed to open a log file(%s), run anyway.", "<%s> failed to open a log file(%s), run anyway.",
__FUNCTION__, pidfilename); __FUNCTION__, pidfilename);
else { } else {
fprintf(pidfp, "%d\n", pid); fprintf(pidfp, "%d\n", pid);
fclose(pidfp); fclose(pidfp);
} }
@ -283,15 +283,14 @@ main(argc, argv)
if (timeout != NULL) { if (timeout != NULL) {
syslog(LOG_DEBUG, syslog(LOG_DEBUG,
"<%s> set timer to %ld:%ld. waiting for " "<%s> set timer to %ld:%ld. waiting for "
"inputs or timeout", "inputs or timeout", __FUNCTION__,
__FUNCTION__, (long int)timeout->tv_sec,
(long int)timeout->tv_sec, (long int)timeout->tv_usec);
(long int)timeout->tv_usec);
} else { } else {
syslog(LOG_DEBUG, syslog(LOG_DEBUG,
"<%s> there's no timer. waiting for inputs", "<%s> there's no timer. waiting for inputs",
__FUNCTION__); __FUNCTION__);
} }
if ((i = select(maxfd + 1, &select_fd, if ((i = select(maxfd + 1, &select_fd,
@ -299,7 +298,7 @@ main(argc, argv)
/* EINTR would occur upon SIGUSR1 for status dump */ /* EINTR would occur upon SIGUSR1 for status dump */
if (errno != EINTR) if (errno != EINTR)
syslog(LOG_ERR, "<%s> select: %s", syslog(LOG_ERR, "<%s> select: %s",
__FUNCTION__, strerror(errno)); __FUNCTION__, strerror(errno));
continue; continue;
} }
if (i == 0) /* timeout */ if (i == 0) /* timeout */
@ -364,11 +363,8 @@ rtmsg_input()
n = read(rtsock, msg, sizeof(msg)); n = read(rtsock, msg, sizeof(msg));
if (dflag > 1) { if (dflag > 1) {
syslog(LOG_DEBUG, syslog(LOG_DEBUG, "<%s> received a routing message "
"<%s> received a routing message " "(type = %d, len = %d)", __FUNCTION__, rtmsg_type(msg), n);
"(type = %d, len = %d)",
__FUNCTION__,
rtmsg_type(msg), n);
} }
if (n > rtmsg_len(msg)) { if (n > rtmsg_len(msg)) {
/* /*
@ -377,10 +373,10 @@ rtmsg_input()
*/ */
if (dflag > 1) if (dflag > 1)
syslog(LOG_DEBUG, syslog(LOG_DEBUG,
"<%s> received data length is larger than" "<%s> received data length is larger than "
"1st routing message len. multiple messages?" "1st routing message len. multiple messages? "
" read %d bytes, but 1st msg len = %d", "read %d bytes, but 1st msg len = %d",
__FUNCTION__, n, rtmsg_len(msg)); __FUNCTION__, n, rtmsg_len(msg));
#if 0 #if 0
/* adjust length */ /* adjust length */
n = rtmsg_len(msg); n = rtmsg_len(msg);
@ -435,99 +431,92 @@ rtmsg_input()
} }
oldifflags = iflist[ifindex]->ifm_flags; oldifflags = iflist[ifindex]->ifm_flags;
switch(type) { switch (type) {
case RTM_ADD: case RTM_ADD:
/* init ifflags because it may have changed */ /* init ifflags because it may have changed */
iflist[ifindex]->ifm_flags = iflist[ifindex]->ifm_flags =
if_getflags(ifindex, if_getflags(ifindex, iflist[ifindex]->ifm_flags);
iflist[ifindex]->ifm_flags);
if (sflag) if (sflag)
break; /* we aren't interested in prefixes */ break; /* we aren't interested in prefixes */
addr = get_addr(msg); addr = get_addr(msg);
plen = get_prefixlen(msg); plen = get_prefixlen(msg);
/* sanity check for plen */ /* sanity check for plen */
if (plen < 4 /* as RFC2373, prefixlen is at least 4 */ /* as RFC2373, prefixlen is at least 4 */
|| plen > 127) { if (plen < 4 || plen > 127) {
syslog(LOG_INFO, "<%s> new interface route's" syslog(LOG_INFO, "<%s> new interface route's"
"plen %d is invalid for a prefix", "plen %d is invalid for a prefix",
__FUNCTION__, plen); __FUNCTION__, plen);
break; break;
} }
prefix = find_prefix(rai, addr, plen); prefix = find_prefix(rai, addr, plen);
if (prefix) { if (prefix) {
if (dflag > 1) { if (dflag > 1) {
syslog(LOG_DEBUG, syslog(LOG_DEBUG,
"<%s> new prefix(%s/%d) " "<%s> new prefix(%s/%d) "
"added on %s, " "added on %s, "
"but it was already in list", "but it was already in list",
__FUNCTION__, __FUNCTION__,
inet_ntop(AF_INET6, inet_ntop(AF_INET6, addr,
addr, (char *)addrbuf, (char *)addrbuf, INET6_ADDRSTRLEN),
INET6_ADDRSTRLEN), plen, rai->ifname);
plen, }
rai->ifname);
}
break;
}
make_prefix(rai, ifindex, addr, plen);
break;
case RTM_DELETE:
/* init ifflags because it may have changed */
iflist[ifindex]->ifm_flags =
if_getflags(ifindex,
iflist[ifindex]->ifm_flags);
if (sflag)
break;
addr = get_addr(msg);
plen = get_prefixlen(msg);
/* sanity check for plen */
if (plen < 4 /* as RFC2373, prefixlen is at least 4 */
|| plen > 127) {
syslog(LOG_INFO, "<%s> deleted interface"
"route's"
"plen %d is invalid for a prefix",
__FUNCTION__, plen);
break; break;
} }
prefix = find_prefix(rai, addr, plen); make_prefix(rai, ifindex, addr, plen);
if (prefix == NULL) { break;
if (dflag > 1) { case RTM_DELETE:
syslog(LOG_DEBUG, /* init ifflags because it may have changed */
"<%s> prefix(%s/%d) was " iflist[ifindex]->ifm_flags =
"deleted on %s, " if_getflags(ifindex, iflist[ifindex]->ifm_flags);
"but it was not in list",
__FUNCTION__, if (sflag)
inet_ntop(AF_INET6, break;
addr, (char *)addrbuf,
INET6_ADDRSTRLEN), addr = get_addr(msg);
plen, plen = get_prefixlen(msg);
rai->ifname); /* sanity check for plen */
} /* as RFC2373, prefixlen is at least 4 */
break; if (plen < 4 || plen > 127) {
} syslog(LOG_INFO,
delete_prefix(rai, prefix); "<%s> deleted interface route's "
break; "plen %d is invalid for a prefix",
__FUNCTION__, plen);
break;
}
prefix = find_prefix(rai, addr, plen);
if (prefix == NULL) {
if (dflag > 1) {
syslog(LOG_DEBUG,
"<%s> prefix(%s/%d) was "
"deleted on %s, "
"but it was not in list",
__FUNCTION__,
inet_ntop(AF_INET6, addr,
(char *)addrbuf, INET6_ADDRSTRLEN),
plen, rai->ifname);
}
break;
}
delete_prefix(rai, prefix);
break;
case RTM_NEWADDR: case RTM_NEWADDR:
case RTM_DELADDR: case RTM_DELADDR:
/* init ifflags because it may have changed */ /* init ifflags because it may have changed */
iflist[ifindex]->ifm_flags = iflist[ifindex]->ifm_flags =
if_getflags(ifindex, if_getflags(ifindex, iflist[ifindex]->ifm_flags);
iflist[ifindex]->ifm_flags); break;
break;
case RTM_IFINFO: case RTM_IFINFO:
iflist[ifindex]->ifm_flags = get_ifm_flags(next); iflist[ifindex]->ifm_flags = get_ifm_flags(next);
break; break;
default: default:
/* should not reach here */ /* should not reach here */
if (dflag > 1) { if (dflag > 1) {
syslog(LOG_DEBUG, syslog(LOG_DEBUG,
"<%s:%d> unknown rtmsg %d on %s", "<%s:%d> unknown rtmsg %d on %s",
__FUNCTION__, __LINE__, type, __FUNCTION__, __LINE__, type,
if_indextoname(ifindex, ifname)); if_indextoname(ifindex, ifname));
} }
return; return;
} }
@ -536,21 +525,19 @@ rtmsg_input()
if ((oldifflags & IFF_UP) != 0 && /* UP to DOWN */ if ((oldifflags & IFF_UP) != 0 && /* UP to DOWN */
(iflist[ifindex]->ifm_flags & IFF_UP) == 0) { (iflist[ifindex]->ifm_flags & IFF_UP) == 0) {
syslog(LOG_INFO, syslog(LOG_INFO,
"<%s> interface %s becomes down. stop timer.", "<%s> interface %s becomes down. stop timer.",
__FUNCTION__, rai->ifname); __FUNCTION__, rai->ifname);
rtadvd_remove_timer(&rai->timer); rtadvd_remove_timer(&rai->timer);
} } else if ((oldifflags & IFF_UP) == 0 && /* DOWN to UP */
else if ((oldifflags & IFF_UP) == 0 && /* DOWN to UP */
(iflist[ifindex]->ifm_flags & IFF_UP) != 0) { (iflist[ifindex]->ifm_flags & IFF_UP) != 0) {
syslog(LOG_INFO, syslog(LOG_INFO,
"<%s> interface %s becomes up. restart timer.", "<%s> interface %s becomes up. restart timer.",
__FUNCTION__, rai->ifname); __FUNCTION__, rai->ifname);
rai->initcounter = 0; /* reset the counter */ rai->initcounter = 0; /* reset the counter */
rai->waiting = 0; /* XXX */ rai->waiting = 0; /* XXX */
rai->timer = rtadvd_add_timer(ra_timeout, rai->timer = rtadvd_add_timer(ra_timeout,
ra_timer_update, ra_timer_update, rai, rai);
rai, rai);
ra_timer_update((void *)rai, &rai->timer->tm); ra_timer_update((void *)rai, &rai->timer->tm);
rtadvd_set_timer(&rai->timer->tm, rai->timer); rtadvd_set_timer(&rai->timer->tm, rai->timer);
} }
@ -645,104 +632,102 @@ rtadvd_input()
icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base; icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;
#endif #endif
switch(icp->icmp6_type) { switch (icp->icmp6_type) {
case ND_ROUTER_SOLICIT: case ND_ROUTER_SOLICIT:
/* /*
* Message verification - RFC-2461 6.1.1 * Message verification - RFC-2461 6.1.1
* XXX: these checks must be done in the kernel as well, * XXX: these checks must be done in the kernel as well,
* but we can't completely rely on them. * but we can't completely rely on them.
*/ */
if (*hlimp != 255) { if (*hlimp != 255) {
syslog(LOG_NOTICE, syslog(LOG_NOTICE,
"<%s> RS with invalid hop limit(%d) " "<%s> RS with invalid hop limit(%d) "
"received from %s on %s", "received from %s on %s",
__FUNCTION__, *hlimp, __FUNCTION__, *hlimp,
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN), INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf)); if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return; return;
} }
if (icp->icmp6_code) { if (icp->icmp6_code) {
syslog(LOG_NOTICE, syslog(LOG_NOTICE,
"<%s> RS with invalid ICMP6 code(%d) " "<%s> RS with invalid ICMP6 code(%d) "
"received from %s on %s", "received from %s on %s",
__FUNCTION__, icp->icmp6_code, __FUNCTION__, icp->icmp6_code,
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN), INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf)); if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return; return;
} }
if (i < sizeof(struct nd_router_solicit)) { if (i < sizeof(struct nd_router_solicit)) {
syslog(LOG_NOTICE, syslog(LOG_NOTICE,
"<%s> RS from %s on %s does not have enough " "<%s> RS from %s on %s does not have enough "
"length (len = %d)", "length (len = %d)",
__FUNCTION__, __FUNCTION__,
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN), INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); if_indextoname(pi->ipi6_ifindex, ifnamebuf), i);
return; return;
} }
rs_input(i, (struct nd_router_solicit *)icp, pi, &from); rs_input(i, (struct nd_router_solicit *)icp, pi, &from);
break; break;
case ND_ROUTER_ADVERT: case ND_ROUTER_ADVERT:
/* /*
* Message verification - RFC-2461 6.1.2 * Message verification - RFC-2461 6.1.2
* XXX: there's a same dilemma as above... * XXX: there's a same dilemma as above...
*/ */
if (*hlimp != 255) { if (*hlimp != 255) {
syslog(LOG_NOTICE, syslog(LOG_NOTICE,
"<%s> RA with invalid hop limit(%d) " "<%s> RA with invalid hop limit(%d) "
"received from %s on %s", "received from %s on %s",
__FUNCTION__, *hlimp, __FUNCTION__, *hlimp,
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN), INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf)); if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return; return;
} }
if (icp->icmp6_code) { if (icp->icmp6_code) {
syslog(LOG_NOTICE, syslog(LOG_NOTICE,
"<%s> RA with invalid ICMP6 code(%d) " "<%s> RA with invalid ICMP6 code(%d) "
"received from %s on %s", "received from %s on %s",
__FUNCTION__, icp->icmp6_code, __FUNCTION__, icp->icmp6_code,
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN), INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf)); if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return; return;
} }
if (i < sizeof(struct nd_router_advert)) { if (i < sizeof(struct nd_router_advert)) {
syslog(LOG_NOTICE, syslog(LOG_NOTICE,
"<%s> RA from %s on %s does not have enough " "<%s> RA from %s on %s does not have enough "
"length (len = %d)", "length (len = %d)",
__FUNCTION__, __FUNCTION__,
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN), INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); if_indextoname(pi->ipi6_ifindex, ifnamebuf), i);
return; return;
} }
ra_input(i, (struct nd_router_advert *)icp, pi, &from); ra_input(i, (struct nd_router_advert *)icp, pi, &from);
break; break;
case ICMP6_ROUTER_RENUMBERING: case ICMP6_ROUTER_RENUMBERING:
if (accept_rr == 0) { if (accept_rr == 0) {
syslog(LOG_ERR, syslog(LOG_ERR, "<%s> received a router renumbering "
"<%s> received a router renumbering " "message, but not allowed to be accepted",
"message, but not allowed to be accepted", __FUNCTION__);
__FUNCTION__); break;
break; }
} rr_input(i, (struct icmp6_router_renum *)icp, pi, &from,
rr_input(i, (struct icmp6_router_renum *)icp, pi, &from, &dst);
&dst); break;
break; default:
default: /*
/* * Note that this case is POSSIBLE, especially just
* Note that this case is POSSIBLE, especially just * after invocation of the daemon. This is because we
* after invocation of the daemon. This is because we * could receive message after opening the socket and
* could receive message after opening the socket and * before setting ICMP6 type filter(see sock_open()).
* before setting ICMP6 type filter(see sock_open()). */
*/ syslog(LOG_ERR, "<%s> invalid icmp type(%d)",
syslog(LOG_ERR, __FUNCTION__, icp->icmp6_type);
"<%s> invalid icmp type(%d)", return;
__FUNCTION__, icp->icmp6_type);
return;
} }
return; return;
@ -1112,8 +1097,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
pp->pltimeexpire); pp->pltimeexpire);
inconsistent++; inconsistent++;
} }
} } else if (preferred_time != pp->preflifetime) {
else if (preferred_time != pp->preflifetime) {
syslog(LOG_INFO, syslog(LOG_INFO,
"<%s> prefeerred lifetime for %s/%d" "<%s> prefeerred lifetime for %s/%d"
" inconsistent on %s:" " inconsistent on %s:"
@ -1149,8 +1133,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
pp->vltimeexpire); pp->vltimeexpire);
inconsistent++; inconsistent++;
} }
} } else if (valid_time != pp->validlifetime) {
else if (valid_time != pp->validlifetime) {
syslog(LOG_INFO, syslog(LOG_INFO,
"<%s> valid lifetime for %s/%d" "<%s> valid lifetime for %s/%d"
" inconsistent on %s:" " inconsistent on %s:"
@ -1221,64 +1204,59 @@ nd6_options(struct nd_opt_hdr *hdr, int limit,
optlen = hdr->nd_opt_len << 3; optlen = hdr->nd_opt_len << 3;
if (hdr->nd_opt_len == 0) { if (hdr->nd_opt_len == 0) {
syslog(LOG_ERR, syslog(LOG_ERR,
"<%s> bad ND option length(0) (type = %d)", "<%s> bad ND option length(0) (type = %d)",
__FUNCTION__, hdr->nd_opt_type); __FUNCTION__, hdr->nd_opt_type);
goto bad; goto bad;
} }
if (hdr->nd_opt_type > ND_OPT_MTU) { if (hdr->nd_opt_type > ND_OPT_MTU) {
syslog(LOG_INFO, syslog(LOG_INFO,
"<%s> unknown ND option(type %d)", "<%s> unknown ND option(type %d)",
__FUNCTION__, __FUNCTION__, hdr->nd_opt_type);
hdr->nd_opt_type);
continue; continue;
} }
if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) { if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) {
syslog(LOG_INFO, syslog(LOG_INFO,
"<%s> unexpected ND option(type %d)", "<%s> unexpected ND option(type %d)",
__FUNCTION__, __FUNCTION__, hdr->nd_opt_type);
hdr->nd_opt_type);
continue; continue;
} }
switch(hdr->nd_opt_type) { switch (hdr->nd_opt_type) {
case ND_OPT_SOURCE_LINKADDR: case ND_OPT_SOURCE_LINKADDR:
case ND_OPT_TARGET_LINKADDR: case ND_OPT_TARGET_LINKADDR:
case ND_OPT_REDIRECTED_HEADER: case ND_OPT_REDIRECTED_HEADER:
case ND_OPT_MTU: case ND_OPT_MTU:
if (ndopts->nd_opt_array[hdr->nd_opt_type]) { if (ndopts->nd_opt_array[hdr->nd_opt_type]) {
syslog(LOG_INFO, syslog(LOG_INFO,
"<%s> duplicated ND option" "<%s> duplicated ND option (type = %d)",
" (type = %d)", __FUNCTION__, hdr->nd_opt_type);
__FUNCTION__, }
hdr->nd_opt_type); ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
} break;
ndopts->nd_opt_array[hdr->nd_opt_type] = hdr; case ND_OPT_PREFIX_INFORMATION:
break; {
case ND_OPT_PREFIX_INFORMATION: struct nd_optlist *pfxlist;
{
struct nd_optlist *pfxlist;
if (ndopts->nd_opts_pi == 0) { if (ndopts->nd_opts_pi == 0) {
ndopts->nd_opts_pi = ndopts->nd_opts_pi =
(struct nd_opt_prefix_info *)hdr; (struct nd_opt_prefix_info *)hdr;
continue; continue;
} }
if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) { if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) {
syslog(LOG_ERR, syslog(LOG_ERR, "<%s> can't allocate memory",
"<%s> can't allocate memory", __FUNCTION__);
__FUNCTION__); goto bad;
goto bad; }
} pfxlist->next = ndopts->nd_opts_list;
pfxlist->next = ndopts->nd_opts_list; pfxlist->opt = hdr;
pfxlist->opt = hdr; ndopts->nd_opts_list = pfxlist;
ndopts->nd_opts_list = pfxlist;
break; break;
} }
default: /* impossible */ default: /* impossible */
break; break;
} }
} }
@ -1295,7 +1273,7 @@ free_ndopts(union nd_opts *ndopts)
{ {
struct nd_optlist *opt = ndopts->nd_opts_list, *next; struct nd_optlist *opt = ndopts->nd_opts_list, *next;
while(opt) { while (opt) {
next = opt->next; next = opt->next;
free(opt); free(opt);
opt = next; opt = next;
@ -1392,7 +1370,7 @@ sock_open()
__FUNCTION__); __FUNCTION__);
exit(1); exit(1);
} }
while(ra) { while (ra) {
mreq.ipv6mr_interface = ra->ifindex; mreq.ipv6mr_interface = ra->ifindex;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
sizeof(mreq)) < 0) { sizeof(mreq)) < 0) {