Deleted Added
full compact
1,2c1,2
< /* $FreeBSD: head/sys/netinet6/nd6.c 74093 2001-03-11 05:31:45Z bmilekic $ */
< /* $KAME: nd6.c,v 1.68 2000/07/02 14:48:02 itojun Exp $ */
---
> /* $FreeBSD: head/sys/netinet6/nd6.c 78064 2001-06-11 12:39:29Z ume $ */
> /* $KAME: nd6.c,v 1.144 2001/05/24 07:44:00 itojun Exp $ */
45a46
> #include <sys/callout.h>
55a57
> #include <sys/sysctl.h>
86a89
> int nd6_gctimer = (60 * 60 * 24); /* 1 day: garbage collection timer */
92a96,101
> #ifdef ND6_DEBUG
> int nd6_debug = 1;
> #else
> int nd6_debug = 0;
> #endif
>
105a115
> static int regen_tmpaddr __P((struct in6_ifaddr *));
106a117,120
> struct callout nd6_slowtimo_ch;
> struct callout nd6_timer_ch;
> extern struct callout in6_tmpaddrtimer_ch;
>
129c143,144
< timeout(nd6_slowtimo, (caddr_t)0, ND6_SLOWTIMER_INTERVAL * hz);
---
> callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
> nd6_slowtimo, NULL);
195,210c210,233
< switch(ifp->if_type) {
< case IFT_ARCNET: /* XXX MTU handling needs more work */
< ndi->maxmtu = MIN(60480, ifp->if_mtu);
< break;
< case IFT_ETHER:
< ndi->maxmtu = MIN(ETHERMTU, ifp->if_mtu);
< break;
< case IFT_FDDI:
< ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu);
< break;
< case IFT_ATM:
< ndi->maxmtu = MIN(ATMMTU, ifp->if_mtu);
< break;
< default:
< ndi->maxmtu = ifp->if_mtu;
< break;
---
> switch (ifp->if_type) {
> case IFT_ARCNET: /* XXX MTU handling needs more work */
> ndi->maxmtu = MIN(60480, ifp->if_mtu);
> break;
> case IFT_ETHER:
> ndi->maxmtu = MIN(ETHERMTU, ifp->if_mtu);
> break;
> case IFT_FDDI:
> ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu);
> break;
> case IFT_ATM:
> ndi->maxmtu = MIN(ATMMTU, ifp->if_mtu);
> break;
> case IFT_IEEE1394: /* XXX should be IEEE1394MTU(1500) */
> ndi->maxmtu = MIN(ETHERMTU, ifp->if_mtu);
> break;
> #ifdef IFT_IEEE80211
> case IFT_IEEE80211: /* XXX should be IEEE80211MTU(1500) */
> ndi->maxmtu = MIN(ETHERMTU, ifp->if_mtu);
> break;
> #endif
> default:
> ndi->maxmtu = ifp->if_mtu;
> break;
331a355
> icmp6stat.icp6s_nd_badopt++;
345,346c369,371
< printf("duplicated ND6 option found "
< "(type=%d)\n", nd_opt->nd_opt_type);
---
> nd6log((LOG_INFO,
> "duplicated ND6 option found (type=%d)\n",
> nd_opt->nd_opt_type));
366c391
< log(LOG_DEBUG,
---
> nd6log((LOG_DEBUG,
368c393
< "option ignored\n", nd_opt->nd_opt_type);
---
> "option ignored\n", nd_opt->nd_opt_type));
375c400
< printf("too many loop in nd opt\n");
---
> nd6log((LOG_INFO, "too many loop in nd opt\n"));
394,396c419,424
< register struct llinfo_nd6 *ln;
< register struct nd_defrouter *dr;
< register struct nd_prefix *pr;
---
> struct llinfo_nd6 *ln;
> struct nd_defrouter *dr;
> struct nd_prefix *pr;
> struct ifnet *ifp;
> struct in6_ifaddr *ia6, *nia6;
> struct in6_addrlifetime *lt6;
399c427,428
< timeout(nd6_timer, (caddr_t)0, nd6_prune * hz);
---
> callout_reset(&nd6_timer_ch, nd6_prune * hz,
> nd6_timer, NULL);
405d433
< struct ifnet *ifp;
461c489
< nd6_free(rt);
---
> next = nd6_free(rt);
465c493
< if (ln->ln_expire)
---
> if (ln->ln_expire) {
466a495,496
> ln->ln_expire = time_second + nd6_gctimer;
> }
468,471c498,504
< /*
< * ND6_LLINFO_STALE state requires nothing for timer
< * routine.
< */
---
>
> case ND6_LLINFO_STALE:
> /* Garbage Collection(RFC 2461 5.3) */
> if (ln->ln_expire)
> next = nd6_free(rt);
> break;
>
482c515
< } else
---
> } else {
483a517,518
> ln->ln_expire = time_second + nd6_gctimer;
> }
493c528
< nd6_free(rt);
---
> next = nd6_free(rt);
496,498d530
< case ND6_LLINFO_WAITDELETE:
< nd6_free(rt);
< break;
503c535
< /* expire */
---
> /* expire default router list */
515,518d546
< pr = nd_prefix.lh_first;
< while (pr) {
< struct in6_ifaddr *ia6;
< struct in6_addrlifetime *lt6;
520,523c548,560
< if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
< ia6 = NULL;
< else
< ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
---
> /*
> * expire interface addresses.
> * in the past the loop was inside prefix expiry processing.
> * However, from a stricter speci-confrmance standpoint, we should
> * rather separate address lifetimes and prefix lifetimes.
> */
> addrloop:
> for (ia6 = in6_ifaddr; ia6; ia6 = nia6) {
> nia6 = ia6->ia_next;
> /* check address lifetime */
> lt6 = &ia6->ia6_lifetime;
> if (IFA6_IS_INVALID(ia6)) {
> int regen = 0;
525,533c562,575
< if (ia6) {
< /* check address lifetime */
< lt6 = &ia6->ia6_lifetime;
< if (lt6->ia6t_preferred && lt6->ia6t_preferred < time_second)
< ia6->ia6_flags |= IN6_IFF_DEPRECATED;
< if (lt6->ia6t_expire && lt6->ia6t_expire < time_second) {
< if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
< in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
< /* xxx ND_OPT_PI_FLAG_ONLINK processing */
---
> /*
> * If the expiring address is temporary, try
> * regenerating a new one. This would be useful when
> * we suspended a laptop PC, then turned on after a
> * period that could invalidate all temporary
> * addresses. Although we may have to restart the
> * loop (see below), it must be after purging the
> * address. Otherwise, we'd see an infinite loop of
> * regeneration.
> */
> if (ip6_use_tempaddr &&
> (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
> if (regen_tmpaddr(ia6) == 0)
> regen = 1;
534a577,616
>
> in6_purgeaddr(&ia6->ia_ifa);
>
> if (regen)
> goto addrloop; /* XXX: see below */
> } else if (IFA6_IS_DEPRECATED(ia6)) {
> int oldflags = ia6->ia6_flags;
>
> ia6->ia6_flags |= IN6_IFF_DEPRECATED;
>
> /*
> * If a temporary address has just become deprecated,
> * regenerate a new one if possible.
> */
> if (ip6_use_tempaddr &&
> (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
> (oldflags & IN6_IFF_DEPRECATED) == 0) {
>
> if (regen_tmpaddr(ia6) == 0) {
> /*
> * A new temporary address is
> * generated.
> * XXX: this means the address chain
> * has changed while we are still in
> * the loop. Although the change
> * would not cause disaster (because
> * it's not an addition, but a
> * deletion,) we'd rather restart the
> * loop just for safety. Or does this
> * significantly reduce performance??
> */
> goto addrloop;
> }
> }
> } else if (IFA6_IS_DEPRECATED(ia6)) {
> /*
> * A new RA might have made a deprecated address
> * preferred.
> */
> ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
535a618
> }
536a620,622
> /* expire prefix list */
> pr = nd_prefix.lh_first;
> while (pr) {
545a632,634
> *
> * I don't think such an offset is necessary.
> * (jinmei@kame.net, 20010130).
547,548c636
< if (pr->ndpr_expire
< && pr->ndpr_expire + NDPR_KEEP_EXPIRED < time_second) {
---
> if (pr->ndpr_expire && pr->ndpr_expire < time_second) {
554c642
< * separate. NEVER perform in6_ifdel here.
---
> * separate. NEVER perform in6_purgeaddr here.
564a653,716
> static int
> regen_tmpaddr(ia6)
> struct in6_ifaddr *ia6; /* deprecated/invalidated temporary address */
> {
> struct ifaddr *ifa;
> struct ifnet *ifp;
> struct in6_ifaddr *public_ifa6 = NULL;
>
> ifp = ia6->ia_ifa.ifa_ifp;
> for (ifa = ifp->if_addrlist.tqh_first; ifa;
> ifa = ifa->ifa_list.tqe_next)
> {
> struct in6_ifaddr *it6;
>
> if (ifa->ifa_addr->sa_family != AF_INET6)
> continue;
>
> it6 = (struct in6_ifaddr *)ifa;
>
> /* ignore no autoconf addresses. */
> if ((it6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
> continue;
>
> /* ignore autoconf addresses with different prefixes. */
> if (it6->ia6_ndpr == NULL || it6->ia6_ndpr != ia6->ia6_ndpr)
> continue;
>
> /*
> * Now we are looking at an autoconf address with the same
> * prefix as ours. If the address is temporary and is still
> * preferred, do not create another one. It would be rare, but
> * could happen, for example, when we resume a laptop PC after
> * a long period.
> */
> if ((it6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
> !IFA6_IS_DEPRECATED(it6)) {
> public_ifa6 = NULL;
> break;
> }
>
> /*
> * This is a public autoconf address that has the same prefix
> * as ours. If it is preferred, keep it. We can't break the
> * loop here, because there may be a still-preferred temporary
> * address with the prefix.
> */
> if (!IFA6_IS_DEPRECATED(it6))
> public_ifa6 = it6;
> }
>
> if (public_ifa6 != NULL) {
> int e;
>
> if ((e = in6_tmpifadd(public_ifa6, 0)) != 0) {
> log(LOG_NOTICE, "regen_tmpaddr: failed to create a new"
> " tmp addr,errno=%d\n", e);
> return(-1);
> }
> return(0);
> }
>
> return(-1);
> }
>
597,598c749,756
< if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
< in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
---
> /*
> * Previously, pr->ndpr_addr is removed as well,
> * but I strongly believe we don't have to do it.
> * nd6_purge() is only called from in6_ifdetach(),
> * which removes all the associated interface addresses
> * by itself.
> * (jinmei@kame.net 20010129)
> */
629c787
< nd6_free(rt);
---
> nln = nd6_free(rt);
633,655d790
<
< /*
< * Neighbor cache entry for interface route will be retained
< * with ND6_LLINFO_WAITDELETE state, by nd6_free(). Nuke it.
< */
< ln = llinfo_nd6.ln_next;
< while (ln && ln != &llinfo_nd6) {
< struct rtentry *rt;
< struct sockaddr_dl *sdl;
<
< nln = ln->ln_next;
< rt = ln->ln_rt;
< if (rt && rt->rt_gateway &&
< rt->rt_gateway->sa_family == AF_LINK) {
< sdl = (struct sockaddr_dl *)rt->rt_gateway;
< if (sdl->sdl_index == ifp->if_index) {
< rtrequest(RTM_DELETE, rt_key(rt),
< (struct sockaddr *)0, rt_mask(rt), 0,
< (struct rtentry **)0);
< }
< }
< ln = nln;
< }
760c895
< register struct ifaddr *ifa;
---
> struct ifaddr *ifa;
810c945
< void
---
> struct llinfo_nd6 *
814,815c949
< struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
< struct sockaddr_dl *sdl;
---
> struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo, *next;
820,821c954,955
< * Clear all destination cache entries for the neighbor.
< * XXX: is it better to restrict this to hosts?
---
> * we used to have pfctlinput(PRC_HOSTDEAD) here.
> * even though it is not harmful, it was not really necessary.
823d956
< pfctlinput(PRC_HOSTDEAD, rt_key(rt));
829a963
>
854a989,996
> /*
> * Since defrouter_select() does not affect the
> * on-link determination and MIP6 needs the check
> * before the default router selection, we perform
> * the check now.
> */
> pfxlist_onlink_check();
>
868d1009
< pfxlist_onlink_check();
873,880c1014,1020
< if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
< sdl->sdl_family == AF_LINK) {
< sdl->sdl_alen = 0;
< ln->ln_state = ND6_LLINFO_WAITDELETE;
< ln->ln_asked = 0;
< rt->rt_flags &= ~RTF_REJECT;
< return;
< }
---
> /*
> * Before deleting the entry, remember the next entry as the
> * return value. We need this because pfxlist_onlink_check() above
> * might have freed other entries (particularly the old next entry) as
> * a side effect (XXX).
> */
> next = ln->ln_next;
881a1022,1026
> /*
> * Detach the route from the routing tree and the list of neighbor
> * caches, and disable the route entry not to be used in already
> * cached routes.
> */
883a1029,1030
>
> return(next);
938,1034d1084
< #ifdef OLDIP6OUTPUT
< /*
< * Resolve an IP6 address into an ethernet address. If success,
< * desten is filled in. If there is no entry in ndptab,
< * set one up and multicast a solicitation for the IP6 address.
< * Hold onto this mbuf and resend it once the address
< * is finally resolved. A return value of 1 indicates
< * that desten has been filled in and the packet should be sent
< * normally; a 0 return indicates that the packet has been
< * taken over here, either now or for later transmission.
< */
< int
< nd6_resolve(ifp, rt, m, dst, desten)
< struct ifnet *ifp;
< struct rtentry *rt;
< struct mbuf *m;
< struct sockaddr *dst;
< u_char *desten;
< {
< struct llinfo_nd6 *ln = (struct llinfo_nd6 *)NULL;
< struct sockaddr_dl *sdl;
<
< if (m->m_flags & M_MCAST) {
< switch (ifp->if_type) {
< case IFT_ETHER:
< case IFT_FDDI:
< ETHER_MAP_IPV6_MULTICAST(&SIN6(dst)->sin6_addr,
< desten);
< return(1);
< break;
< case IFT_ARCNET:
< *desten = 0;
< return(1);
< break;
< default:
< m_freem(m);
< return(0);
< }
< }
< if (rt && (rt->rt_flags & RTF_LLINFO) != 0)
< ln = (struct llinfo_nd6 *)rt->rt_llinfo;
< else {
< if ((rt = nd6_lookup(&(SIN6(dst)->sin6_addr), 1, ifp)) != NULL)
< ln = (struct llinfo_nd6 *)rt->rt_llinfo;
< }
< if (!ln || !rt) {
< log(LOG_DEBUG, "nd6_resolve: can't allocate llinfo for %s\n",
< ip6_sprintf(&(SIN6(dst)->sin6_addr)));
< m_freem(m);
< return(0);
< }
< sdl = SDL(rt->rt_gateway);
< /*
< * Ckeck the address family and length is valid, the address
< * is resolved; otherwise, try to resolve.
< */
< if (ln->ln_state >= ND6_LLINFO_REACHABLE
< && sdl->sdl_family == AF_LINK
< && sdl->sdl_alen != 0) {
< bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
< if (ln->ln_state == ND6_LLINFO_STALE) {
< ln->ln_asked = 0;
< ln->ln_state = ND6_LLINFO_DELAY;
< ln->ln_expire = time_second + nd6_delay;
< }
< return(1);
< }
< /*
< * There is an ndp entry, but no ethernet address
< * response yet. Replace the held mbuf with this
< * latest one.
< *
< * XXX Does the code conform to rate-limiting rule?
< * (RFC 2461 7.2.2)
< */
< if (ln->ln_state == ND6_LLINFO_WAITDELETE ||
< ln->ln_state == ND6_LLINFO_NOSTATE)
< ln->ln_state = ND6_LLINFO_INCOMPLETE;
< if (ln->ln_hold)
< m_freem(ln->ln_hold);
< ln->ln_hold = m;
< if (ln->ln_expire) {
< rt->rt_flags &= ~RTF_REJECT;
< if (ln->ln_asked < nd6_mmaxtries &&
< ln->ln_expire < time_second) {
< ln->ln_asked++;
< ln->ln_expire = time_second +
< nd_ifinfo[ifp->if_index].retrans / 1000;
< nd6_ns_output(ifp, NULL, &(SIN6(dst)->sin6_addr),
< ln, 0);
< }
< }
< /* Do not free mbuf chain here as it is queued in llinfo_nd6 */
< return(0);
< }
< #endif /* OLDIP6OUTPUT */
<
1049a1100,1110
> if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) {
> /*
> * This is probably an interface direct route for a link
> * which does not need neighbor caches (e.g. fe80::%lo0/64).
> * We do not need special treatment below for such a route.
> * Moreover, the RTF_LLINFO flag which would be set below
> * would annoy the ndp(8) command.
> */
> return;
> }
>
1075c1136
< /* cludge for desktops */
---
> /* kludge for desktops */
1096c1157
< * note that the mechanism need a mutual agreement
---
> * note that the mechanism needs a mutual agreement
1098,1099c1159,1160
< * a new protocol, or new kludge.
< * - from RFC2461 6.2.4, host MUST NOT send unsolicited NA.
---
> * a new protocol, or a new kludge.
> * - from RFC2461 6.2.4, host MUST NOT send an unsolicited NA.
1115c1176
< if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
---
> if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
1123c1184,1185
< "nd6_rtrequest: bad gateway value\n");
---
> "nd6_rtrequest: bad gateway value: %s\n",
> if_name(ifp));
1195c1257
< ifa->ifa_refcnt++;
---
> IFAREF(ifa);
1216,1219c1278,1282
< (void)in6_addmulti(&llsol, ifp, &error);
< if (error)
< printf(
< "nd6_rtrequest: could not join solicited node multicast (errno=%d)\n", error);
---
> if (!in6_addmulti(&llsol, ifp, &error)) {
> nd6log((LOG_ERR, "%s: failed to join "
> "%s (errno=%d)\n", if_name(ifp),
> ip6_sprintf(&llsol), error));
> }
1256,1314d1318
< void
< nd6_p2p_rtrequest(req, rt, sa)
< int req;
< struct rtentry *rt;
< struct sockaddr *sa; /* xxx unused */
< {
< struct sockaddr *gate = rt->rt_gateway;
< static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
< struct ifnet *ifp = rt->rt_ifp;
< struct ifaddr *ifa;
<
< if (rt->rt_flags & RTF_GATEWAY)
< return;
<
< switch (req) {
< case RTM_ADD:
< /*
< * There is no backward compatibility :)
< *
< * if ((rt->rt_flags & RTF_HOST) == 0 &&
< * SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
< * rt->rt_flags |= RTF_CLONING;
< */
< if (rt->rt_flags & RTF_CLONING) {
< /*
< * Case 1: This route should come from
< * a route to interface.
< */
< rt_setgate(rt, rt_key(rt),
< (struct sockaddr *)&null_sdl);
< gate = rt->rt_gateway;
< SDL(gate)->sdl_type = ifp->if_type;
< SDL(gate)->sdl_index = ifp->if_index;
< break;
< }
< /* Announce a new entry if requested. */
< if (rt->rt_flags & RTF_ANNOUNCE)
< nd6_na_output(ifp,
< &SIN6(rt_key(rt))->sin6_addr,
< &SIN6(rt_key(rt))->sin6_addr,
< ip6_forwarding ? ND_NA_FLAG_ROUTER : 0,
< 1, NULL);
< /* FALLTHROUGH */
< case RTM_RESOLVE:
< /*
< * check if rt_key(rt) is one of my address assigned
< * to the interface.
< */
< ifa = (struct ifaddr *)in6ifa_ifpwithaddr(rt->rt_ifp,
< &SIN6(rt_key(rt))->sin6_addr);
< if (ifa) {
< if (nd6_useloopback) {
< rt->rt_ifp = &loif[0]; /*XXX*/
< }
< }
< break;
< }
< }
<
1333a1338,1340
> /*
> * obsolete API, use sysctl under net.inet6.icmp6
> */
1358a1366,1368
> * obsolete API, use sysctl under net.inet6.icmp6
> */
> /*
1370c1380,1381
< prl->prefix[i].prefix = pr->ndpr_prefix.sin6_addr;
---
> (void)in6_embedscope(&prl->prefix[i].prefix,
> &pr->ndpr_prefix, NULL, NULL);
1380c1391
< while(pfr) {
---
> while (pfr) {
1411c1422,1423
< prl->prefix[i].prefix = rpp->rp_prefix.sin6_addr;
---
> (void)in6_embedscope(&prl->prefix[i].prefix,
> &pr->ndpr_prefix, NULL, NULL);
1425a1438,1453
> case OSIOCGIFINFO_IN6:
> if (!nd_ifinfo || i >= nd_ifinfo_indexlim) {
> error = EINVAL;
> break;
> }
> ndi->ndi.linkmtu = nd_ifinfo[ifp->if_index].linkmtu;
> ndi->ndi.maxmtu = nd_ifinfo[ifp->if_index].maxmtu;
> ndi->ndi.basereachable =
> nd_ifinfo[ifp->if_index].basereachable;
> ndi->ndi.reachable = nd_ifinfo[ifp->if_index].reachable;
> ndi->ndi.retrans = nd_ifinfo[ifp->if_index].retrans;
> ndi->ndi.flags = nd_ifinfo[ifp->if_index].flags;
> ndi->ndi.recalctm = nd_ifinfo[ifp->if_index].recalctm;
> ndi->ndi.chlim = nd_ifinfo[ifp->if_index].chlim;
> ndi->ndi.receivedra = nd_ifinfo[ifp->if_index].receivedra;
> break;
1458a1487,1488
> struct in6_ifaddr *ia, *ia_next;
>
1460,1461c1490,1504
< if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
< in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
---
>
> if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
> continue; /* XXX */
>
> /* do we really have to remove addresses as well? */
> for (ia = in6_ifaddr; ia; ia = ia_next) {
> /* ia might be removed. keep the next ptr. */
> ia_next = ia->ia_next;
>
> if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
> continue;
>
> if (ia->ia6_ndpr == pr)
> in6_purgeaddr(&ia->ia_ifa);
> }
1580c1623,1626
< } else
---
> } else {
> /* do nothing if static ndp is set */
> if (rt->rt_flags & RTF_STATIC)
> return NULL;
1581a1628
> }
1587c1634
< nd6_free(rt);
---
> (void)nd6_free(rt);
1650c1697,1704
< rt->rt_flags &= ~RTF_REJECT;
---
> /*
> * XXX: since nd6_output() below will cause
> * state tansition to DELAY and reset the timer,
> * we must set the timer now, although it is actually
> * meaningless.
> */
> ln->ln_expire = time_second + nd6_gctimer;
>
1652,1655d1705
< #ifdef OLDIP6OUTPUT
< (*ifp->if_output)(ifp, ln->ln_hold,
< rt_key(rt), rt);
< #else
1663,1664c1713
< #endif
< ln->ln_hold = 0;
---
> ln->ln_hold = NULL;
1745,1746c1794,1795
< register int i;
< register struct nd_ifinfo *nd6if;
---
> int i;
> struct nd_ifinfo *nd6if;
1748c1797,1798
< timeout(nd6_slowtimo, (caddr_t)0, ND6_SLOWTIMER_INTERVAL * hz);
---
> callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
> nd6_slowtimo, NULL);
1771c1821
< register struct ifnet *ifp;
---
> struct ifnet *ifp;
1777,1778c1827,1828
< register struct mbuf *m = m0;
< register struct rtentry *rt = rt0;
---
> struct mbuf *m = m0;
> struct rtentry *rt = rt0;
1786,1799c1836
< /*
< * XXX: we currently do not make neighbor cache on any interface
< * other than ARCnet, Ethernet, FDDI and GIF.
< *
< * draft-ietf-ngtrans-mech-06.txt says:
< * - unidirectional tunnels needs no ND
< */
< switch (ifp->if_type) {
< case IFT_ARCNET:
< case IFT_ETHER:
< case IFT_FDDI:
< case IFT_GIF: /* XXX need more cases? */
< break;
< default:
---
> if (nd6_need_cache(ifp) == 0)
1801d1837
< }
1827c1863
< * of view, regardless the value of the value of
---
> * of view, regardless the value of the
1835,1837d1870
< if (rt->rt_flags & RTF_REJECT)
< senderr(EHOSTDOWN);
<
1858,1859d1890
< if (rt->rt_flags & RTF_REJECT)
< senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
1897c1928
< ln->ln_state < ND6_LLINFO_REACHABLE)
---
> ln->ln_state < ND6_LLINFO_REACHABLE) {
1898a1930,1931
> ln->ln_expire = time_second + nd6_gctimer;
> }
1929,1930c1962
< if (ln->ln_state == ND6_LLINFO_WAITDELETE ||
< ln->ln_state == ND6_LLINFO_NOSTATE)
---
> if (ln->ln_state == ND6_LLINFO_NOSTATE)
1936d1967
< rt->rt_flags &= ~RTF_REJECT;
1949,1950c1980
< #ifdef FAKE_LOOPBACK_IF
< if (ifp->if_flags & IFF_LOOPBACK) {
---
> if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
1954d1983
< #endif
1964a1994,2019
> nd6_need_cache(ifp)
> struct ifnet *ifp;
> {
> /*
> * XXX: we currently do not make neighbor cache on any interface
> * other than ARCnet, Ethernet, FDDI and GIF.
> *
> * RFC2893 says:
> * - unidirectional tunnels needs no ND
> */
> switch (ifp->if_type) {
> case IFT_ARCNET:
> case IFT_ETHER:
> case IFT_FDDI:
> case IFT_IEEE1394:
> #ifdef IFT_IEEE80211
> case IFT_IEEE80211:
> #endif
> case IFT_GIF: /* XXX need more cases? */
> return(1);
> default:
> return(0);
> }
> }
>
> int
1971a2027
> int i;
1977c2033,2036
< case IFT_FDDI:
---
> case IFT_FDDI:
> #ifdef IFT_IEEE80211
> case IFT_IEEE80211:
> #endif
1981c2040,2043
< break;
---
> case IFT_IEEE1394:
> for (i = 0; i < ifp->if_addrlen; i++)
> desten[i] = ~0;
> return(1);
1992c2054
< /* This could happen if we could not allocate memory */
---
> /* this could happen, if we could not allocate memory */
1997c2059
< printf("nd6_storelladdr: something odd happened\n");
---
> printf("nd6_storelladdr: something odd happens\n");
2011a2074,2199
>
> static int nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS);
> static int nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS);
> #ifdef SYSCTL_DECL
> SYSCTL_DECL(_net_inet6_icmp6);
> #endif
> SYSCTL_NODE(_net_inet6_icmp6, ICMPV6CTL_ND6_DRLIST, nd6_drlist,
> CTLFLAG_RD, nd6_sysctl_drlist, "");
> SYSCTL_NODE(_net_inet6_icmp6, ICMPV6CTL_ND6_PRLIST, nd6_prlist,
> CTLFLAG_RD, nd6_sysctl_prlist, "");
>
> static int
> nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS)
> {
> int error;
> char buf[1024];
> struct in6_defrouter *d, *de;
> struct nd_defrouter *dr;
>
> if (req->newptr)
> return EPERM;
> error = 0;
>
> for (dr = TAILQ_FIRST(&nd_defrouter);
> dr;
> dr = TAILQ_NEXT(dr, dr_entry)) {
> d = (struct in6_defrouter *)buf;
> de = (struct in6_defrouter *)(buf + sizeof(buf));
>
> if (d + 1 <= de) {
> bzero(d, sizeof(*d));
> d->rtaddr.sin6_family = AF_INET6;
> d->rtaddr.sin6_len = sizeof(d->rtaddr);
> if (in6_recoverscope(&d->rtaddr, &dr->rtaddr,
> dr->ifp) != 0)
> log(LOG_ERR,
> "scope error in "
> "default router list (%s)\n",
> ip6_sprintf(&dr->rtaddr));
> d->flags = dr->flags;
> d->rtlifetime = dr->rtlifetime;
> d->expire = dr->expire;
> d->if_index = dr->ifp->if_index;
> } else
> panic("buffer too short");
>
> error = SYSCTL_OUT(req, buf, sizeof(*d));
> if (error)
> break;
> }
> return error;
> }
>
> static int
> nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS)
> {
> int error;
> char buf[1024];
> struct in6_prefix *p, *pe;
> struct nd_prefix *pr;
>
> if (req->newptr)
> return EPERM;
> error = 0;
>
> for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
> u_short advrtrs;
> size_t advance;
> struct sockaddr_in6 *sin6, *s6;
> struct nd_pfxrouter *pfr;
>
> p = (struct in6_prefix *)buf;
> pe = (struct in6_prefix *)(buf + sizeof(buf));
>
> if (p + 1 <= pe) {
> bzero(p, sizeof(*p));
> sin6 = (struct sockaddr_in6 *)(p + 1);
>
> p->prefix = pr->ndpr_prefix;
> if (in6_recoverscope(&p->prefix,
> &p->prefix.sin6_addr, pr->ndpr_ifp) != 0)
> log(LOG_ERR,
> "scope error in prefix list (%s)\n",
> ip6_sprintf(&p->prefix.sin6_addr));
> p->raflags = pr->ndpr_raf;
> p->prefixlen = pr->ndpr_plen;
> p->vltime = pr->ndpr_vltime;
> p->pltime = pr->ndpr_pltime;
> p->if_index = pr->ndpr_ifp->if_index;
> p->expire = pr->ndpr_expire;
> p->refcnt = pr->ndpr_refcnt;
> p->flags = pr->ndpr_stateflags;
> p->origin = PR_ORIG_RA;
> advrtrs = 0;
> for (pfr = pr->ndpr_advrtrs.lh_first;
> pfr;
> pfr = pfr->pfr_next) {
> if ((void *)&sin6[advrtrs + 1] >
> (void *)pe) {
> advrtrs++;
> continue;
> }
> s6 = &sin6[advrtrs];
> bzero(s6, sizeof(*s6));
> s6->sin6_family = AF_INET6;
> s6->sin6_len = sizeof(*sin6);
> if (in6_recoverscope(s6,
> &pfr->router->rtaddr,
> pfr->router->ifp) != 0)
> log(LOG_ERR,
> "scope error in "
> "prefix list (%s)\n",
> ip6_sprintf(&pfr->router->rtaddr));
> advrtrs++;
> }
> p->advrtrs = advrtrs;
> } else
> panic("buffer too short");
>
> advance = sizeof(*p) + sizeof(*sin6) * advrtrs;
> error = SYSCTL_OUT(req, buf, advance);
> if (error)
> break;
> }
> return error;
> }