Page MenuHomeFreeBSD

D1469.id3066.diff
No OneTemporary

D1469.id3066.diff

Index: sys/net/if_arcsubr.c
===================================================================
--- sys/net/if_arcsubr.c
+++ sys/net/if_arcsubr.c
@@ -169,8 +169,13 @@
case AF_INET6:
if ((m->m_flags & M_MCAST) != NULL)
adst = arcbroadcastaddr; /* ARCnet broadcast address */
- else
- error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, NULL);
+ else {
+ is_gw = 0;
+ if (ro != NULL && ro->ro_rt != NULL &&
+ (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
+ is_gw = 1;
+ error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL);
+ }
if (error)
return (error);
atype = ARCTYPE_INET6;
Index: sys/net/if_ethersubr.c
===================================================================
--- sys/net/if_ethersubr.c
+++ sys/net/if_ethersubr.c
@@ -225,7 +225,7 @@
if (lle != NULL && (pflags & LLE_VALID))
memcpy(edst, &lle->ll_addr.mac16, sizeof(edst));
else
- error = nd6_storelladdr(ifp, m, dst, (u_char *)edst,
+ error = nd6_resolve(ifp, is_gw, m, dst, (u_char *)edst,
&pflags);
if (error)
return error;
Index: sys/net/if_fddisubr.c
===================================================================
--- sys/net/if_fddisubr.c
+++ sys/net/if_fddisubr.c
@@ -161,7 +161,11 @@
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
+ is_gw = 0;
+ if (ro != NULL && ro->ro_rt != NULL &&
+ (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
+ is_gw = 1;
+ error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL);
if (error)
return (error); /* Something bad happened */
type = htons(ETHERTYPE_IPV6);
Index: sys/net/if_fwsubr.c
===================================================================
--- sys/net/if_fwsubr.c
+++ sys/net/if_fwsubr.c
@@ -173,7 +173,11 @@
#ifdef INET6
case AF_INET6:
if (unicast) {
- error = nd6_storelladdr(fc->fc_ifp, m, dst,
+ is_gw = 0;
+ if (ro != NULL && ro->ro_rt != NULL &&
+ (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
+ is_gw = 1;
+ error = nd6_resolve(fc->fc_ifp, is_gw, m, dst,
(u_char *) destfw, NULL);
if (error)
return (error);
Index: sys/net/if_iso88025subr.c
===================================================================
--- sys/net/if_iso88025subr.c
+++ sys/net/if_iso88025subr.c
@@ -293,7 +293,7 @@
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
+ error = nd6_resolve(ifp, m, dst, edst, NULL);
if (error)
return (error);
snap_type = ETHERTYPE_IPV6;
Index: sys/netinet6/ip6_forward.c
===================================================================
--- sys/netinet6/ip6_forward.c
+++ sys/netinet6/ip6_forward.c
@@ -584,7 +584,7 @@
}
pass:
- error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
+ error = nd6_output_ifp(rt->rt_ifp, origifp, m, dst);
if (error) {
in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
IP6STAT_INC(ip6s_cantforward);
Index: sys/netinet6/ip6_output.c
===================================================================
--- sys/netinet6/ip6_output.c
+++ sys/netinet6/ip6_output.c
@@ -882,7 +882,7 @@
m->m_pkthdr.len);
ifa_free(&ia6->ia_ifa);
}
- error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
+ error = nd6_output_ifp(ifp, origifp, m, dst);
goto done;
}
@@ -1038,7 +1038,7 @@
counter_u64_add(ia->ia_ifa.ifa_obytes,
m->m_pkthdr.len);
}
- error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
+ error = nd6_output_ifp(ifp, origifp, m, dst);
} else
m_freem(m);
}
Index: sys/netinet6/nd6.h
===================================================================
--- sys/netinet6/nd6.h
+++ sys/netinet6/nd6.h
@@ -391,33 +391,30 @@
#endif
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
void nd6_ifdetach(struct nd_ifinfo *);
-int nd6_is_addr_neighbor(struct sockaddr_in6 *, struct ifnet *);
+int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *);
void nd6_option_init(void *, int, union nd_opts *);
struct nd_opt_hdr *nd6_option(union nd_opts *);
int nd6_options(union nd_opts *);
-struct llentry *nd6_lookup(struct in6_addr *, int, struct ifnet *);
+struct llentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *);
void nd6_setmtu(struct ifnet *);
void nd6_llinfo_settimer(struct llentry *, long);
void nd6_llinfo_settimer_locked(struct llentry *, long);
void nd6_timer(void *);
void nd6_purge(struct ifnet *);
void nd6_nud_hint(struct rtentry *, struct in6_addr *, int);
-int nd6_resolve(struct ifnet *, struct rtentry *, struct mbuf *,
- struct sockaddr *, u_char *);
int nd6_ioctl(u_long, caddr_t, struct ifnet *);
struct llentry *nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
char *, int, int, int);
-int nd6_output(struct ifnet *, struct ifnet *, struct mbuf *,
- struct sockaddr_in6 *, struct rtentry *);
void nd6_grab_holdchain(struct llentry *, struct mbuf **,
struct sockaddr_in6 *);
int nd6_flush_holdchain(struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *);
-int nd6_need_cache(struct ifnet *);
int nd6_add_ifa_lle(struct in6_ifaddr *);
void nd6_rem_ifa_lle(struct in6_ifaddr *);
-int nd6_storelladdr(struct ifnet *, struct mbuf *,
- const struct sockaddr *, u_char *, uint32_t *);
+int nd6_output_ifp(struct ifnet *, struct ifnet *, struct mbuf *,
+ struct sockaddr_in6 *);
+int nd6_resolve(struct ifnet *, int, struct mbuf *,
+ const struct sockaddr *, u_char *, uint32_t *);
/* nd6_nbr.c */
void nd6_na_input(struct mbuf *, int, int);
Index: sys/netinet6/nd6.c
===================================================================
--- sys/netinet6/nd6.c
+++ sys/netinet6/nd6.c
@@ -125,7 +125,7 @@
int (*send_sendso_input_hook)(struct mbuf *, struct ifnet *, int, int);
-static int nd6_is_new_addr_neighbor(struct sockaddr_in6 *,
+static int nd6_is_new_addr_neighbor(const struct sockaddr_in6 *,
struct ifnet *);
static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *);
static void nd6_slowtimo(void *);
@@ -134,10 +134,9 @@
static void nd6_llinfo_timer(void *);
static void clear_llinfo_pqueue(struct llentry *);
static void nd6_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
-static int nd6_output_lle(struct ifnet *, struct ifnet *, struct mbuf *,
- struct sockaddr_in6 *);
-static int nd6_output_ifp(struct ifnet *, struct ifnet *, struct mbuf *,
- struct sockaddr_in6 *);
+static int nd6_resolve_slow(struct ifnet *, struct mbuf *,
+ const struct sockaddr_in6 *, u_char *, uint32_t *);
+static int nd6_need_cache(struct ifnet *);
static VNET_DEFINE(struct callout, nd6_slowtimo_ch);
#define V_nd6_slowtimo_ch VNET(nd6_slowtimo_ch)
@@ -846,7 +845,7 @@
* Returns the llentry locked
*/
struct llentry *
-nd6_lookup(struct in6_addr *addr6, int flags, struct ifnet *ifp)
+nd6_lookup(const struct in6_addr *addr6, int flags, struct ifnet *ifp)
{
struct sockaddr_in6 sin6;
struct llentry *ln;
@@ -878,7 +877,7 @@
* to not reenter the routing code from within itself.
*/
static int
-nd6_is_new_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
+nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
{
struct nd_prefix *pr;
struct ifaddr *dstaddr;
@@ -979,7 +978,7 @@
* XXX: should take care of the destination of a p2p link?
*/
int
-nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
+nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
{
struct llentry *lle;
int rc = 0;
@@ -1831,7 +1830,7 @@
}
}
-static int
+int
nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
struct sockaddr_in6 *dst)
{
@@ -1877,31 +1876,73 @@
}
/*
- * IPv6 packet output - light version.
- * Checks if destination LLE exists and is in proper state
- * (e.g no modification required). If not true, fall back to
- * "heavy" version.
+ * Do L2 address resolution for @sa_dst address. Stores found
+ * address in @desten buffer. Copy of lle ln_flags can be also
+ * saved in @pflags if @pflags is non-NULL.
+ *
+ * If destination LLE does not exists or lle state modification
+ * is required, call "slow" version.
+ *
+ * Return values:
+ * - 0 on success (address copied to buffer).
+ * - EWOULDBLOCK (no local error, but address is still unresolved)
+ * - other errors (alloc failure, etc)
*/
int
-nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
- struct sockaddr_in6 *dst, struct rtentry *rt0)
+nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
+ const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags)
{
struct llentry *ln = NULL;
+ const struct sockaddr_in6 *dst6;
+
+ if (pflags != NULL)
+ *pflags = 0;
+
+ dst6 = (const struct sockaddr_in6 *)sa_dst;
/* discard the packet if IPv6 operation is disabled on the interface */
if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
- m_freem(m);
+ if (m != NULL)
+ m_freem(m);
return (ENETDOWN); /* better error? */
}
- if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
- goto sendpkt;
+ if (m != NULL && m->m_flags & M_MCAST) {
+ int i;
- if (nd6_need_cache(ifp) == 0)
- goto sendpkt;
+ switch (ifp->if_type) {
+ case IFT_ETHER:
+ case IFT_FDDI:
+#ifdef IFT_L2VLAN
+ case IFT_L2VLAN:
+#endif
+#ifdef IFT_IEEE80211
+ case IFT_IEEE80211:
+#endif
+ case IFT_BRIDGE:
+ case IFT_ISO88025:
+ ETHER_MAP_IPV6_MULTICAST(&dst6->sin6_addr,
+ desten);
+ return (0);
+ case IFT_IEEE1394:
+ /*
+ * netbsd can use if_broadcastaddr, but we don't do so
+ * to reduce # of ifdef.
+ */
+ for (i = 0; i < ifp->if_addrlen; i++)
+ desten[i] = ~0;
+ return (0);
+ case IFT_ARCNET:
+ *desten = 0;
+ return (0);
+ default:
+ m_freem(m);
+ return (EAFNOSUPPORT);
+ }
+ }
IF_AFDATA_RLOCK(ifp);
- ln = nd6_lookup(&dst->sin6_addr, 0, ifp);
+ ln = nd6_lookup(&dst6->sin6_addr, 0, ifp);
IF_AFDATA_RUNLOCK(ifp);
/*
@@ -1917,46 +1958,33 @@
/* Fall back to slow processing path */
if (ln != NULL)
LLE_RUNLOCK(ln);
- return (nd6_output_lle(ifp, origifp, m, dst));
+ return (nd6_resolve_slow(ifp, m, dst6, desten, pflags));
}
-sendpkt:
- if (ln != NULL)
- LLE_RUNLOCK(ln);
-
- return (nd6_output_ifp(ifp, origifp, m, dst));
+ bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
+ if (pflags != NULL)
+ *pflags = ln->la_flags;
+ LLE_RUNLOCK(ln);
+ return (0);
}
/*
- * Output IPv6 packet - heavy version.
- * Function assume that either
- * 1) destination LLE does not exist, is invalid or stale, so
- * ND6_EXCLUSIVE lock needs to be acquired
- * 2) destination lle is provided (with ND6_EXCLUSIVE lock),
- * in that case packets are queued in &chain.
+ * Do L2 address resolution for @sa_dst address. Stores found
+ * address in @desten buffer. Copy of lle ln_flags can be also
+ * saved in @pflags if @pflags is non-NULL.
*
+ * Heavy version.
+ * Function assume that destination LLE does not exist,
+ * is invalid or stale, so ND6_EXCLUSIVE lock needs to be acquired.
*/
static int
-nd6_output_lle(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
- struct sockaddr_in6 *dst)
+nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
+ const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags)
{
struct llentry *lle = NULL;
int flags = 0;
- KASSERT(m != NULL, ("NULL mbuf, nothing to send"));
- /* discard the packet if IPv6 operation is disabled on the interface */
- if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
- m_freem(m);
- return (ENETDOWN); /* better error? */
- }
-
- if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
- goto sendpkt;
-
- if (nd6_need_cache(ifp) == 0)
- goto sendpkt;
-
/*
* Address resolution or Neighbor Unreachability Detection
* for the next hop.
@@ -1980,28 +2008,20 @@
}
}
if (lle == NULL) {
- if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
- !(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
+ if (!(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
char ip6buf[INET6_ADDRSTRLEN];
log(LOG_DEBUG,
- "nd6_output: can't allocate llinfo for %s "
- "(ln=%p)\n",
- ip6_sprintf(ip6buf, &dst->sin6_addr), lle);
- m_freem(m);
- return (ENOBUFS);
+ "nd6_resolve_slow: can't allocate llinfo for %s\n",
+ ip6_sprintf(ip6buf, &dst->sin6_addr));
}
- goto sendpkt; /* send anyway */
+
+ if (m != NULL)
+ m_freem(m);
+ return (ENOBUFS);
}
LLE_WLOCK_ASSERT(lle);
- /* We don't have to do link-layer address resolution on a p2p link. */
- if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
- lle->ln_state < ND6_LLINFO_REACHABLE) {
- lle->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer_locked(lle, (long)V_nd6_gctimer * hz);
- }
-
/*
* The first time we send a packet to a neighbor whose entry is
* STALE, we have to change the state to DELAY and a sets a timer to
@@ -2020,8 +2040,13 @@
* (i.e. its link-layer address is already resolved), just
* send the packet.
*/
- if (lle->ln_state > ND6_LLINFO_INCOMPLETE)
- goto sendpkt;
+ if (lle->ln_state > ND6_LLINFO_INCOMPLETE) {
+ bcopy(&lle->ll_addr, desten, ifp->if_addrlen);
+ if (pflags != NULL)
+ *pflags = lle->la_flags;
+ LLE_WUNLOCK(lle);
+ return (0);
+ }
/*
* There is a neighbor cache entry, but no ethernet address
@@ -2071,13 +2096,7 @@
LLE_WUNLOCK(lle);
}
- return (0);
-
- sendpkt:
- if (lle != NULL)
- LLE_WUNLOCK(lle);
-
- return (nd6_output_ifp(ifp, origifp, m, dst));
+ return (EWOULDBLOCK);
}
@@ -2103,15 +2122,13 @@
/*
* XXX
- * note that intermediate errors are blindly ignored - but this is
- * the same convention as used with nd6_output when called by
- * nd6_cache_lladdr
+ * note that intermediate errors are blindly ignored
*/
return (error);
}
-int
+static int
nd6_need_cache(struct ifnet *ifp)
{
/*
@@ -2199,65 +2216,6 @@
(struct sockaddr *)&mask, LLE_STATIC);
}
-/*
- * the callers of this function need to be re-worked to drop
- * the lle lock, drop here for now
- */
-int
-nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
- const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
-{
- struct llentry *ln;
-
- if (pflags != NULL)
- *pflags = 0;
- IF_AFDATA_UNLOCK_ASSERT(ifp);
- if (m != NULL && m->m_flags & M_MCAST) {
- switch (ifp->if_type) {
- case IFT_ETHER:
- case IFT_FDDI:
-#ifdef IFT_L2VLAN
- case IFT_L2VLAN:
-#endif
-#ifdef IFT_IEEE80211
- case IFT_IEEE80211:
-#endif
- case IFT_BRIDGE:
- case IFT_ISO88025:
- ETHER_MAP_IPV6_MULTICAST(&SIN6(dst)->sin6_addr,
- desten);
- return (0);
- default:
- m_freem(m);
- return (EAFNOSUPPORT);
- }
- }
-
-
- /*
- * the entry should have been created in nd6_store_lladdr
- */
- IF_AFDATA_RLOCK(ifp);
- ln = lla_lookup(LLTABLE6(ifp), 0, dst);
- IF_AFDATA_RUNLOCK(ifp);
- if ((ln == NULL) || !(ln->la_flags & LLE_VALID)) {
- if (ln != NULL)
- LLE_RUNLOCK(ln);
- /* this could happen, if we could not allocate memory */
- m_freem(m);
- return (1);
- }
-
- bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
- if (pflags != NULL)
- *pflags = ln->la_flags;
- LLE_RUNLOCK(ln);
- /*
- * A *small* use after free race exists here
- */
- return (0);
-}
-
static void
clear_llinfo_pqueue(struct llentry *ln)
{
Index: sys/netpfil/pf/pf.c
===================================================================
--- sys/netpfil/pf/pf.c
+++ sys/netpfil/pf/pf.c
@@ -5444,7 +5444,7 @@
if (IN6_IS_SCOPE_EMBED(&dst.sin6_addr))
dst.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu)
- nd6_output(ifp, ifp, m0, &dst, NULL);
+ nd6_output_ifp(ifp, ifp, m0, &dst);
else {
in6_ifstat_inc(ifp, ifs6_in_toobig);
if (r->rt != PF_DUPTO)
Index: sys/ofed/drivers/infiniband/core/addr.c
===================================================================
--- sys/ofed/drivers/infiniband/core/addr.c
+++ sys/ofed/drivers/infiniband/core/addr.c
@@ -472,7 +472,7 @@
#endif
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, NULL, dst_in, (u_char *)edst,NULL);
+ error = nd6_resolve(ifp, is_gw, NULL, dst_in, edst, NULL);
break;
#endif
default:
Index: sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
===================================================================
--- sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1332,7 +1332,7 @@
else if (m->m_flags & M_MCAST)
ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst);
else
- error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
+ error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL);
if (error)
return error;
type = htons(ETHERTYPE_IPV6);

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 17, 11:17 AM (18 m, 5 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31656515
Default Alt Text
D1469.id3066.diff (16 KB)

Event Timeline