summaryrefslogtreecommitdiff
path: root/sys/netinet6/nd6.c
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-04-17 04:44:52 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-04-17 04:44:52 +0000
commit21c2e6c965d401f6359663687069efbf69376e00 (patch)
tree324898ea862ad4e4badb4620d5d2e6159627b0f0 /sys/netinet6/nd6.c
parentfe45f154d1f286c742242fe504ccad68e20378f9 (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.c119
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);