diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-04-17 04:44:52 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-04-17 04:44:52 +0000 |
commit | 21c2e6c965d401f6359663687069efbf69376e00 (patch) | |
tree | 324898ea862ad4e4badb4620d5d2e6159627b0f0 /sys/netinet6/nd6.c | |
parent | fe45f154d1f286c742242fe504ccad68e20378f9 (diff) |
revisit in6_ifattach(). (1) make it more persistent about initializaing an
interface (2) cleanup interface id selection.
run NUD on p2p interface (required by spec for bidir p2p interface).
add "ndp -i interface" (can tweak per-interface ND flag).
(sync with more recent kame)
Diffstat (limited to 'sys/netinet6/nd6.c')
-rw-r--r-- | sys/netinet6/nd6.c | 119 |
1 files changed, 81 insertions, 38 deletions
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 30f7120001a..ac3bfb845d0 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1,10 +1,10 @@ -/* $OpenBSD: nd6.c,v 1.10 2000/04/13 16:27:26 itojun Exp $ */ -/* $KAME: nd6.c,v 1.41 2000/02/24 16:34:50 itojun Exp $ */ +/* $OpenBSD: nd6.c,v 1.11 2000/04/17 04:44:51 itojun Exp $ */ +/* $KAME: nd6.c,v 1.55 2000/04/16 14:08:30 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -16,7 +16,7 @@ * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -158,12 +158,18 @@ nd6_ifattach(ifp) } #define ND nd_ifinfo[ifp->if_index] + + /* don't initialize if called twice */ + if (ND.linkmtu) + return; + ND.linkmtu = ifindex2ifnet[ifp->if_index]->if_mtu; ND.chlim = IPV6_DEFHLIM; ND.basereachable = REACHABLE_TIME; ND.reachable = ND_COMPUTE_RTIME(ND.basereachable); ND.retrans = RETRANS_TIMER; ND.receivedra = 0; + ND.flags = ND6_IFF_PERFORMNUD; nd6_setmtu(ifp); #undef ND } @@ -339,7 +345,7 @@ nd6_options(ndopts) * Unknown options must be silently ignored, * to accomodate future extension to the protocol. */ - log(LOG_INFO, + log(LOG_DEBUG, "nd6_options: unsupported option %d - " "option ignored\n", nd_opt->nd_opt_type); } @@ -383,6 +389,8 @@ nd6_timer(ignored_arg) struct ifnet *ifp; struct sockaddr_in6 *dst; struct llinfo_nd6 *next = ln->ln_next; + /* XXX: used for the DELAY case only: */ + struct nd_ifinfo *ndi = NULL; if ((rt = ln->ln_rt) == NULL) { ln = next; @@ -392,6 +400,7 @@ nd6_timer(ignored_arg) ln = next; continue; } + ndi = &nd_ifinfo[ifp->if_index]; dst = (struct sockaddr_in6 *)rt_key(rt); if (ln->ln_expire > time_second) { @@ -402,6 +411,9 @@ nd6_timer(ignored_arg) /* sanity check */ if (!rt) panic("rt=0 in nd6_timer(ln=%p)\n", ln); + if (rt->rt_llinfo && (struct llinfo_nd6 *)rt->rt_llinfo != ln) + panic("rt_llinfo(%p) is not equal to ln(%p)\n", + rt->rt_llinfo, ln); if (!dst) panic("dst=0 in nd6_timer(ln=%p)\n", ln); @@ -437,19 +449,24 @@ nd6_timer(ignored_arg) if (ln->ln_expire) ln->ln_state = ND6_LLINFO_STALE; break; - /* + /* * ND6_LLINFO_STALE state requires nothing for timer * routine. */ case ND6_LLINFO_DELAY: - ln->ln_asked = 1; - ln->ln_state = ND6_LLINFO_PROBE; - ln->ln_expire = time_second + - nd_ifinfo[ifp->if_index].retrans / 1000; - nd6_ns_output(ifp, &dst->sin6_addr, &dst->sin6_addr, - ln, 0); + if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) { + /* We need NUD */ + ln->ln_asked = 1; + ln->ln_state = ND6_LLINFO_PROBE; + ln->ln_expire = time_second + + ndi->retrans / 1000; + nd6_ns_output(ifp, &dst->sin6_addr, + &dst->sin6_addr, + ln, 0); + } + else + ln->ln_state = ND6_LLINFO_STALE; /* XXX */ break; - case ND6_LLINFO_PROBE: if (ln->ln_asked < nd6_umaxtries) { ln->ln_asked++; @@ -639,7 +656,7 @@ nd6_lookup(addr6, create, ifp) if (rt && (rt->rt_flags & RTF_LLINFO) == 0) { /* * This is the case for the default route. - * If we want to create a neighbor cache for the address, we + * If we want to create a neighbor cache for the address, we * should free the route for the destination and allocate an * interface route. */ @@ -650,6 +667,8 @@ nd6_lookup(addr6, create, ifp) } if (!rt) { if (create && ifp) { + int e; + /* * If no route is available and create is set, * we allocate a host route for the destination @@ -666,17 +685,19 @@ nd6_lookup(addr6, create, ifp) * Create a new route. RTF_LLINFO is necessary * to create a Neighbor Cache entry for the * destination in nd6_rtrequest which will be - * called in rtequest via ifa->ifa_rtrequest. + * called in rtequest via ifa->ifa_rtrequest. */ - if (rtrequest(RTM_ADD, (struct sockaddr *)&sin6, - ifa->ifa_addr, - (struct sockaddr *)&all1_sa, - (ifa->ifa_flags | - RTF_HOST | RTF_LLINFO) & ~RTF_CLONING, - &rt)) + if ((e = rtrequest(RTM_ADD, (struct sockaddr *)&sin6, + ifa->ifa_addr, + (struct sockaddr *)&all1_sa, + (ifa->ifa_flags | + RTF_HOST | RTF_LLINFO) & + ~RTF_CLONING, + &rt)) != 0) log(LOG_ERR, "nd6_lookup: failed to add route for a " - "neighbor(%s)\n", ip6_sprintf(addr6)); + "neighbor(%s), errno=%d\n", + ip6_sprintf(addr6), e); if (rt == NULL) return(NULL); if (rt->rt_llinfo) { @@ -711,7 +732,7 @@ nd6_lookup(addr6, create, ifp) /* * Detect if a given IPv6 address identifies a neighbor on a given link. - * XXX: should take care of the destination of a p2p link? + * XXX: should take care of the destination of a p2p link? */ int nd6_is_addr_neighbor(addr, ifp) @@ -1058,14 +1079,21 @@ nd6_rtrequest(req, rt, sa) #endif /* FALLTHROUGH */ case RTM_RESOLVE: - if (gate->sa_family != AF_LINK || - gate->sa_len < sizeof(null_sdl)) { - log(LOG_DEBUG, "nd6_rtrequest: bad gateway value\n"); - break; + if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { + /* + * Address resolution isn't necessary for a point to + * point link, so we can skip this test for a p2p link. + */ + if (gate->sa_family != AF_LINK || + gate->sa_len < sizeof(null_sdl)) { + log(LOG_DEBUG, + "nd6_rtrequest: bad gateway value\n"); + break; + } + SDL(gate)->sdl_type = ifp->if_type; + SDL(gate)->sdl_index = ifp->if_index; } - SDL(gate)->sdl_type = ifp->if_type; - SDL(gate)->sdl_index = ifp->if_index; - if (ln != 0) + if (ln != NULL) break; /* This happens on a route change */ /* * Case 2: This route may come from cloning, or a manual route @@ -1090,7 +1118,7 @@ nd6_rtrequest(req, rt, sa) */ ln->ln_state = ND6_LLINFO_REACHABLE; } else { - /* + /* * When req == RTM_RESOLVE, rt is created and * initialized in rtrequest(), so rt_expire is 0. */ @@ -1364,6 +1392,10 @@ nd6_ioctl(cmd, data, ifp) case SIOCGIFINFO_IN6: ndi->ndi = nd_ifinfo[ifp->if_index]; break; + case SIOCSIFINFO_FLAGS: + /* XXX: almost all other fields of ndi->ndi is unused */ + nd_ifinfo[ifp->if_index].flags = ndi->ndi.flags; + break; case SIOCSNDFLUSH_IN6: /* XXX: the ioctl name is confusing... */ /* flush default router list */ /* @@ -1585,7 +1617,7 @@ fail: nd6_output(ifp, ln->ln_hold, (struct sockaddr_in6 *)rt_key(rt), rt); -#endif +#endif ln->ln_hold = 0; } } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { @@ -1634,9 +1666,8 @@ fail: case ND_REDIRECT: /* * If the icmp is a redirect to a better router, always set the - * is_router flag. Otherwise, if the entry is newly created, + * is_router flag. Otherwise, if the entry is newly created, * clear the flag. [RFC 2461, sec 8.3] - * */ if (code == ND_REDIRECT_ROUTER) ln->ln_router = 1; @@ -1708,19 +1739,27 @@ nd6_output(ifp, m0, dst, rt0) /* * XXX: we currently do not make neighbor cache on any interface - * other than ARCnet, Ethernet and FDDI. + * other than ARCnet, Ethernet, FDDI and GIF. + * + * draft-ietf-ngtrans-mech-04.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: goto sendpkt; } + if ((ifp->if_flags & IFF_POINTOPOINT) != 0 && + (nd_ifinfo[ifp->if_index].flags & ND6_IFF_PERFORMNUD) == 0) + goto sendpkt; + /* - * next hop determination. This routine is derived from ether_outpout. + * next hop determination. This routine is derived from ether_outpout. */ if (rt) { if ((rt->rt_flags & RTF_UP) == 0) { @@ -1730,7 +1769,7 @@ nd6_output(ifp, m0, dst, rt0) rt->rt_refcnt--; if (rt->rt_ifp != ifp) return nd6_output(ifp, m0, dst, rt); /* XXX: loop care? */ - } else + } else senderr(EHOSTUNREACH); } if (rt->rt_flags & RTF_GATEWAY) { @@ -1768,6 +1807,10 @@ nd6_output(ifp, m0, dst, rt0) senderr(EIO); /* XXX: good error? */ } + /* We don't have to do link-layer address resolution on a p2p link. */ + if ((ifp->if_flags & IFF_POINTOPOINT) != 0 && + ln->ln_state < ND6_LLINFO_REACHABLE) + ln->ln_state = ND6_LLINFO_STALE; /* * The first time we send a packet to a neighbor whose entry is @@ -1818,7 +1861,7 @@ nd6_output(ifp, m0, dst, rt0) sendpkt: return((*ifp->if_output)(ifp, m, (struct sockaddr *)dst, rt)); - + bad: if (m) m_freem(m); |