svn commit: r274089 - in projects/routing/sys: contrib/ipfilter/netinet dev/cxgbe/tom net netgraph netinet netinet6 netipsec netpfil/ipfw netpfil/pf
Alexander V. Chernikov
melifaro at FreeBSD.org
Tue Nov 4 15:40:01 UTC 2014
Author: melifaro
Date: Tue Nov 4 15:39:56 2014
New Revision: 274089
URL: https://svnweb.freebsd.org/changeset/base/274089
Log:
Convert netinet6/ to use new routing API.
* Remove &ifpp from ip6_output() in favor of ri->ri_nh_info
* Provide different wrappers to in6_selectsrc:
Currently it is used by 2 differenct type of customers:
- socket-based one, which all are unsure about provided
address scope and
- in-kernel ones (ND code mostly), which don't have
any sockets, options, crededentials, etc.
So, we provide two different wrappers to in6_selectsrc()
returning select source.
* Make different versions of selectroute():
Currenly selectroute() is used in two scenarios:
- SAS, via in6_selecsrc() -> in6_selectif() -> selectroute()
- output, via in6_output -> wrapper -> selectroute()
Provide different versions for each customer:
- fib6_lookup_nh_basic()-based in6_selectif() which is
capable of returning interface only, without MTU/NHOP/L2
calculations
- full-blown fib6_selectroute() with cached route/multipath/
MTU/L2
* Stop using routing table for link-local address lookups
* Add in6_ifawithifp_lla() to make for-us check faster for link-local
* Add in6_splitscope / in6_setllascope for faster embed/deembed scopes
Modified:
projects/routing/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
projects/routing/sys/dev/cxgbe/tom/t4_listen.c
projects/routing/sys/net/rt_nhops.c
projects/routing/sys/net/rt_nhops.h
projects/routing/sys/netgraph/ng_ipfw.c
projects/routing/sys/netinet/ip_carp.c
projects/routing/sys/netinet/ip_divert.c
projects/routing/sys/netinet/ip_output.c
projects/routing/sys/netinet/sctp_os_bsd.h
projects/routing/sys/netinet/tcp_offload.c
projects/routing/sys/netinet/tcp_output.c
projects/routing/sys/netinet/tcp_subr.c
projects/routing/sys/netinet/tcp_syncache.c
projects/routing/sys/netinet/tcp_timewait.c
projects/routing/sys/netinet6/icmp6.c
projects/routing/sys/netinet6/in6.c
projects/routing/sys/netinet6/in6.h
projects/routing/sys/netinet6/in6_gif.c
projects/routing/sys/netinet6/in6_pcb.c
projects/routing/sys/netinet6/in6_src.c
projects/routing/sys/netinet6/ip6_mroute.c
projects/routing/sys/netinet6/ip6_output.c
projects/routing/sys/netinet6/ip6_var.h
projects/routing/sys/netinet6/mld6.c
projects/routing/sys/netinet6/nd6_nbr.c
projects/routing/sys/netinet6/raw_ip6.c
projects/routing/sys/netinet6/scope6.c
projects/routing/sys/netinet6/scope6_var.h
projects/routing/sys/netinet6/udp6_usrreq.c
projects/routing/sys/netipsec/ipsec_output.c
projects/routing/sys/netpfil/ipfw/ip_dn_io.c
projects/routing/sys/netpfil/ipfw/ip_fw2.c
projects/routing/sys/netpfil/ipfw/ip_fw_dynamic.c
projects/routing/sys/netpfil/pf/pf.c
Modified: projects/routing/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
==============================================================================
--- projects/routing/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -750,7 +750,7 @@ ipf_fastroute(m0, mpp, fin, fdp)
* currently "to <if>" and "to <if>:ip#" are not supported
* for IPv6
*/
- return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+ return ip6_output(m, NULL, NULL, 0, NULL, NULL);
}
#endif
Modified: projects/routing/sys/dev/cxgbe/tom/t4_listen.c
==============================================================================
--- projects/routing/sys/dev/cxgbe/tom/t4_listen.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/dev/cxgbe/tom/t4_listen.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -1140,7 +1140,7 @@ get_l2te_for_nexthop(struct port_info *p
}
/* TODO: Multipath */
- if (fib6_lookup_nh_ext(inc->inc_fibnum, inc->inc6_faddr,
+ if (fib6_lookup_nh_ext(inc->inc_fibnum, &inc->inc6_faddr,
0, 0, 0, &nhu.u.nh6) != 0)
return (NULL);
((struct sockaddr_in6 *)dst)->sin6_addr = nhu.u.nh6.nh_addr;
Modified: projects/routing/sys/net/rt_nhops.c
==============================================================================
--- projects/routing/sys/net/rt_nhops.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/net/rt_nhops.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -66,6 +66,10 @@
#include <netinet/ip_mroute.h>
#include <netinet/ip6.h>
#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+#include <netinet6/scope6_var.h>
+
+#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <netinet/if_ether.h>
@@ -117,11 +121,20 @@ static void fib4_rte_to_nh_extended(stru
static void fib4_rte_to_nh_basic(struct rtentry *rte, struct in_addr dst,
struct nhop4_basic *pnh4);
#endif
-#ifdef INET
-static void fib6_rte_to_nh_extended(struct rtentry *rte, struct in6_addr dst,
+#ifdef INET6
+static void fib6_rte_to_nh_extended(struct rtentry *rte, struct in6_addr *dst,
struct nhop6_extended *pnh6);
-static void fib6_rte_to_nh_basic(struct rtentry *rte, struct in6_addr dst,
+static void fib6_rte_to_nh_basic(struct rtentry *rte, struct in6_addr *dst,
struct nhop6_basic *pnh6);
+static int fib6_storelladdr(struct ifnet *ifp, struct in6_addr *dst,
+ int mm_flags, u_char *desten);
+static uint16_t fib6_get_ifa(struct rtentry *rte);
+static int fib6_lla_to_nh_basic(struct in6_addr *dst, uint32_t scopeid,
+ struct nhop6_basic *pnh6);
+static int fib6_lla_to_nh_extended(struct in6_addr *dst, uint32_t scopeid,
+ struct nhop6_extended *pnh6);
+static int fib6_lla_to_nh(struct in6_addr *dst, uint32_t scopeid,
+ struct nhop_prepend *nh, struct ifnet **lifp);
#endif
MALLOC_DEFINE(M_RTFIB, "rtfib", "routing fwd");
@@ -292,8 +305,11 @@ fib4_lookup_prepend(uint32_t fibnum, str
* Currently all we have is rte ifp.
* Simply use it.
*/
- lifp = rte->rt_ifp;
+ /* Save interface address ifp */
+ lifp = rte->rt_ifa->ifa_ifp;
+ nh->aifp_idx = lifp->if_index;
/* Save both logical and transmit interface indexes */
+ lifp = rte->rt_ifp;
nh->lifp_idx = lifp->if_index;
nh->i.ifp_idx = nh->lifp_idx;
@@ -407,6 +423,7 @@ fib4_rte_to_nh_basic(struct rtentry *rte
gw = (struct sockaddr_in *)rt_key(rte);
if (gw->sin_addr.s_addr == 0)
pnh4->nh_flags |= NHF_DEFAULT;
+ /* XXX: Set RTF_BROADCAST if GW address is broadcast */
}
static void
@@ -428,6 +445,7 @@ fib4_rte_to_nh_extended(struct rtentry *
gw = (struct sockaddr_in *)rt_key(rte);
if (gw->sin_addr.s_addr == 0)
pnh4->nh_flags |= NHF_DEFAULT;
+ /* XXX: Set RTF_BROADCAST if GW address is broadcast */
ia = ifatoia(rte->rt_ifa);
pnh4->nh_src = IA_SIN(ia)->sin_addr;
@@ -561,19 +579,335 @@ fib6_choose_prepend(uint32_t fibnum, str
*/
}
+/*
+ * Temporary function to copy ethernet address from valid lle
+ */
+static int
+fib6_storelladdr(struct ifnet *ifp, struct in6_addr *dst, int mm_flags,
+ u_char *desten)
+{
+ struct llentry *ln;
+ struct sockaddr_in6 dst_sa;
+
+ if (mm_flags & M_MCAST) {
+ ETHER_MAP_IPV6_MULTICAST(&dst, desten);
+ return (0);
+ }
+
+ memset(&dst_sa, 0, sizeof(dst_sa));
+ dst_sa.sin6_family = AF_INET6;
+ dst_sa.sin6_len = sizeof(dst_sa);
+ dst_sa.sin6_addr = *dst;
+ dst_sa.sin6_scope_id = ifp->if_index;
+
+
+ /*
+ * the entry should have been created in nd6_store_lladdr
+ */
+ IF_AFDATA_RLOCK(ifp);
+ ln = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&dst_sa);
+
+ /*
+ * Perform fast path for the following cases:
+ * 1) lle state is REACHABLE
+ * 2) lle state is DELAY (NS message sentNS message sent)
+ *
+ * Every other case involves lle modification, so we handle
+ * them separately.
+ */
+ if (ln == NULL || (ln->ln_state != ND6_LLINFO_REACHABLE &&
+ ln->ln_state != ND6_LLINFO_DELAY)) {
+ if (ln != NULL)
+ LLE_RUNLOCK(ln);
+ IF_AFDATA_RUNLOCK(ifp);
+ return (1);
+ }
+ bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
+ LLE_RUNLOCK(ln);
+ IF_AFDATA_RUNLOCK(ifp);
+
+ return (0);
+}
+
+int
+fib6_lookup_prepend(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
+ struct mbuf *m, struct nhop_prepend *nh, struct nhop6_extended *nh_ext)
+{
+ struct radix_node_head *rnh;
+ struct radix_node *rn;
+ struct sockaddr_in6 sin6, *gw_sa;
+ struct in6_addr gw6;
+ struct rtentry *rte;
+ struct ifnet *lifp;
+ struct ether_header *eh;
+ uint32_t flags;
+ int error;
+
+ if (IN6_IS_SCOPE_LINKLOCAL(dst)) {
+ /* Do not lookup link-local addresses in rtable */
+ error = fib6_lla_to_nh(dst, scopeid, nh, &lifp);
+ if (error != 0)
+ return (error);
+ /* */
+ gw6 = *dst;
+ goto do_l2;
+ }
+
+
+ KASSERT((fibnum < rt_numfibs), ("fib6_lookup_prepend: bad fibnum"));
+ rnh = rt_tables_get_rnh(fibnum, AF_INET6);
+ if (rnh == NULL)
+ return (ENOENT);
+
+ /* Prepare lookup key */
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_addr = *dst;
+ sin6.sin6_scope_id = scopeid;
+ sa6_embedscope(&sin6, 0);
+
+
+ RADIX_NODE_HEAD_RLOCK(rnh);
+ rn = rnh->rnh_matchaddr((void *)&sin6, rnh);
+ rte = RNTORT(rn);
+ if (rn == NULL || ((rn->rn_flags & RNF_ROOT) != 0) ||
+ RT_LINK_IS_UP(rte->rt_ifp) == 0) {
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
+ return (EHOSTUNREACH);
+ }
+
+ /* Explicitly zero nexthop */
+ memset(nh, 0, sizeof(*nh));
+ flags = 0;
+ nh->nh_mtu = min(rte->rt_mtu, IN6_LINKMTU(rte->rt_ifp));
+ if (rte->rt_flags & RTF_GATEWAY) {
+ gw_sa = (struct sockaddr_in6 *)rte->rt_gateway;
+ gw6 = gw_sa->sin6_addr;
+ in6_clearscope(&gw6);
+ } else
+ gw6 = *dst;
+ /* Set flags */
+ flags = fib_rte_to_nh_flags(rte->rt_flags);
+ gw_sa = (struct sockaddr_in6 *)rt_key(rte);
+ if (IN6_IS_ADDR_UNSPECIFIED(&gw_sa->sin6_addr))
+ flags |= NHF_DEFAULT;
+
+ /*
+ * TODO: nh L2/L3 resolve.
+ * Currently all we have is rte ifp.
+ * Simply use it.
+ */
+ /* Save interface address ifp */
+ nh->aifp_idx = fib6_get_ifa(rte);
+ /* Save both logical and transmit interface indexes */
+ lifp = rte->rt_ifp;
+ nh->lifp_idx = lifp->if_index;
+ nh->i.ifp_idx = nh->lifp_idx;
+
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
+
+ nh->nh_flags = flags;
+do_l2:
+ /*
+ * Try to lookup L2 info.
+ * Do this using separate LLE locks.
+ * TODO: move this under radix lock.
+ */
+ if (lifp->if_type == IFT_ETHER) {
+ eh = (struct ether_header *)nh->d.data;
+
+ /*
+ * Fill in ethernet header.
+ * It should be already presented if we're
+ * sending data via known gateway.
+ */
+ error = fib6_storelladdr(lifp, &gw6, m ? m->m_flags : 0,
+ eh->ether_dhost);
+ if (error == 0) {
+ memcpy(&eh->ether_shost, IF_LLADDR(lifp), ETHER_ADDR_LEN);
+ eh->ether_type = htons(ETHERTYPE_IPV6);
+ nh->nh_count = ETHER_HDR_LEN;
+ return (0);
+ }
+ }
+
+ /* Notify caller that no L2 info is linked */
+ nh->nh_count = 0;
+ nh->nh_flags |= NHF_L2_INCOMPLETE;
+ /* ..And save gateway address */
+ nh->d.gw6 = gw6;
+ return (0);
+}
+
+int
+fib6_sendmbuf(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
+ struct nhop_prepend *nh)
+{
+ int error;
+
+ if (nh != NULL && (nh->nh_flags & NHF_L2_INCOMPLETE) == 0) {
+
+ /*
+ * Fast path case. Most packets should
+ * be sent from here.
+ * TODO: Make special ifnet
+ * 'if_output_frame' handler for that.
+ */
+ struct route_compat rc;
+ struct ether_header *eh;
+ rc.ro_flags = AF_INET6 << 8 | RT_NHOP;
+ rc.ro_nh = nh;
+
+ M_PREPEND(m, nh->nh_count, M_NOWAIT);
+ if (m == NULL)
+ return (ENOBUFS);
+ eh = mtod(m, struct ether_header *);
+ memcpy(eh, nh->d.data, nh->nh_count);
+ error = (*ifp->if_output)(ifp, m,
+ NULL, (struct route *)&rc);
+ } else {
+ /* We need to perform ND lookup */
+ struct sockaddr_in6 gw_out;
+
+ memset(&gw_out, 0, sizeof(gw_out));
+ gw_out.sin6_family = AF_INET6;
+ gw_out.sin6_len = sizeof(gw_out);
+ gw_out.sin6_addr = nh->d.gw6;
+ gw_out.sin6_scope_id = ifp->if_index;
+ sa6_embedscope(&gw_out, 0);
+
+ error = nd6_output(ifp, origifp, m, &gw_out, NULL);
+ }
+
+ return (error);
+}
+
+static uint16_t
+fib6_get_ifa(struct rtentry *rte)
+{
+ struct ifnet *ifp;
+ struct sockaddr_dl *sdl;
+
+ ifp = rte->rt_ifp;
+ if ((ifp->if_flags & IFF_LOOPBACK) &&
+ rte->rt_gateway->sa_family == AF_LINK) {
+ sdl = (struct sockaddr_dl *)rte->rt_gateway;
+ return (sdl->sdl_index);
+ }
+
+ return (ifp->if_index);
+#if 0
+ /* IPv6 case */
+ /* Alternative way to get interface address ifp */
+ /*
+ * Adjust the "outgoing" interface. If we're going to loop
+ * the packet back to ourselves, the ifp would be the loopback
+ * interface. However, we'd rather know the interface associated
+ * to the destination address (which should probably be one of
+ * our own addresses.)
+ */
+ if (rt) {
+ if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) &&
+ (rt->rt_gateway->sa_family == AF_LINK))
+ *retifp =
+ ifnet_byindex(((struct sockaddr_dl *)
+ rt->rt_gateway)->sdl_index);
+ }
+ /* IPv4 case */
+ //pnh6->nh_ifp = rte->rt_ifa->ifa_ifp;
+#endif
+}
+
+static int
+fib6_lla_to_nh_basic(struct in6_addr *dst, uint32_t scopeid,
+ struct nhop6_basic *pnh6)
+{
+ struct ifnet *ifp;
+
+ ifp = ifnet_byindex_locked(scopeid);
+ if (ifp == NULL)
+ return (ENOENT);
+
+ /* Do explicit nexthop zero unless we're copying it */
+ memset(pnh6, 0, sizeof(*pnh6));
+
+ pnh6->nh_ifp = ifp;
+ pnh6->nh_mtu = IN6_LINKMTU(ifp);
+ /* No flags set */
+ pnh6->nh_addr = *dst;
+
+ return (0);
+}
+
+static int
+fib6_lla_to_nh_extended(struct in6_addr *dst, uint32_t scopeid,
+ struct nhop6_extended *pnh6)
+{
+ struct ifnet *ifp;
+
+ ifp = ifnet_byindex_locked(scopeid);
+ if (ifp == NULL)
+ return (ENOENT);
+
+ /* Do explicit nexthop zero unless we're copying it */
+ memset(pnh6, 0, sizeof(*pnh6));
+
+ pnh6->nh_ifp = ifp;
+ pnh6->nh_mtu = IN6_LINKMTU(ifp);
+ /* No flags set */
+ pnh6->nh_addr = *dst;
+
+ return (0);
+}
+
+static int
+fib6_lla_to_nh(struct in6_addr *dst, uint32_t scopeid,
+ struct nhop_prepend *nh, struct ifnet **lifp)
+{
+ struct ifnet *ifp;
+
+ ifp = ifnet_byindex_locked(scopeid);
+ if (ifp == NULL)
+ return (ENOENT);
+
+ /* Do explicit nexthop zero unless we're copying it */
+ memset(nh, 0, sizeof(*nh));
+ /* No flags set */
+ nh->nh_mtu = IN6_LINKMTU(ifp);
+
+ /* Save lifp */
+ *lifp = ifp;
+
+ nh->aifp_idx = scopeid;
+ nh->lifp_idx = scopeid;
+ /* Check id this is for-us address */
+ if (in6_ifawithifp_lla(ifp, dst)) {
+ if ((ifp = V_loif) != NULL)
+ nh->lifp_idx = ifp->if_index;
+ }
+
+ return (0);
+}
+
+
static void
-fib6_rte_to_nh_basic(struct rtentry *rte, struct in6_addr dst,
+fib6_rte_to_nh_basic(struct rtentry *rte, struct in6_addr *dst,
struct nhop6_basic *pnh6)
{
struct sockaddr_in6 *gw;
- pnh6->nh_ifp = rte->rt_ifa->ifa_ifp;
- pnh6->nh_mtu = min(rte->rt_mtu, rte->rt_ifp->if_mtu);
+ /* Do explicit nexthop zero unless we're copying it */
+ memset(pnh6, 0, sizeof(*pnh6));
+
+ pnh6->nh_ifp = ifnet_byindex(fib6_get_ifa(rte));
+
+ pnh6->nh_mtu = min(rte->rt_mtu, IN6_LINKMTU(rte->rt_ifp));
if (rte->rt_flags & RTF_GATEWAY) {
gw = (struct sockaddr_in6 *)rte->rt_gateway;
pnh6->nh_addr = gw->sin6_addr;
+ in6_clearscope(&pnh6->nh_addr);
} else
- pnh6->nh_addr = dst;
+ pnh6->nh_addr = *dst;
/* Set flags */
pnh6->nh_flags = fib_rte_to_nh_flags(rte->rt_flags);
gw = (struct sockaddr_in6 *)rt_key(rte);
@@ -582,19 +916,23 @@ fib6_rte_to_nh_basic(struct rtentry *rte
}
static void
-fib6_rte_to_nh_extended(struct rtentry *rte, struct in6_addr dst,
+fib6_rte_to_nh_extended(struct rtentry *rte, struct in6_addr *dst,
struct nhop6_extended *pnh6)
{
struct sockaddr_in6 *gw;
struct in6_ifaddr *ia;
- pnh6->nh_ifp = rte->rt_ifa->ifa_ifp;
- pnh6->nh_mtu = min(rte->rt_mtu, rte->rt_ifp->if_mtu);
+ /* Do explicit nexthop zero unless we're copying it */
+ memset(pnh6, 0, sizeof(*pnh6));
+
+ pnh6->nh_ifp = ifnet_byindex(fib6_get_ifa(rte));
+ pnh6->nh_mtu = min(rte->rt_mtu, IN6_LINKMTU(rte->rt_ifp));
if (rte->rt_flags & RTF_GATEWAY) {
gw = (struct sockaddr_in6 *)rte->rt_gateway;
pnh6->nh_addr = gw->sin6_addr;
+ in6_clearscope(&pnh6->nh_addr);
} else
- pnh6->nh_addr = dst;
+ pnh6->nh_addr = *dst;
/* Set flags */
pnh6->nh_flags = fib_rte_to_nh_flags(rte->rt_flags);
gw = (struct sockaddr_in6 *)rt_key(rte);
@@ -602,18 +940,22 @@ fib6_rte_to_nh_extended(struct rtentry *
pnh6->nh_flags |= NHF_DEFAULT;
ia = ifatoia6(rte->rt_ifa);
- pnh6->nh_src = IA6_SIN6(ia)->sin6_addr;
}
int
-fib6_lookup_nh_basic(uint32_t fibnum, struct in6_addr dst, uint32_t flowid,
- struct nhop6_basic *pnh6)
+fib6_lookup_nh_basic(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
+ uint32_t flowid, struct nhop6_basic *pnh6)
{
struct radix_node_head *rnh;
struct radix_node *rn;
struct sockaddr_in6 sin6;
struct rtentry *rte;
+ if (IN6_IS_SCOPE_LINKLOCAL(dst)) {
+ /* Do not lookup link-local addresses in rtable */
+ return (fib6_lla_to_nh_basic(dst, scopeid, pnh6));
+ }
+
KASSERT((fibnum < rt_numfibs), ("fib6_lookup_nh_basic: bad fibnum"));
rnh = rt_tables_get_rnh(fibnum, AF_INET6);
if (rnh == NULL)
@@ -621,7 +963,9 @@ fib6_lookup_nh_basic(uint32_t fibnum, st
/* Prepare lookup key */
memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_addr = dst;
+ sin6.sin6_addr = *dst;
+ sin6.sin6_scope_id = scopeid;
+ sa6_embedscope(&sin6, 0);
RADIX_NODE_HEAD_RLOCK(rnh);
rn = rnh->rnh_matchaddr((void *)&sin6, rnh);
@@ -649,7 +993,7 @@ fib6_lookup_nh_basic(uint32_t fibnum, st
* - mtu from logical transmit interface will be returned.
*/
int
-fib6_lookup_nh_ext(uint32_t fibnum, struct in6_addr dst, uint32_t scopeid,
+fib6_lookup_nh_ext(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
uint32_t flowid, uint32_t flags, struct nhop6_extended *pnh6)
{
struct radix_node_head *rnh;
@@ -657,6 +1001,12 @@ fib6_lookup_nh_ext(uint32_t fibnum, stru
struct sockaddr_in6 sin6;
struct rtentry *rte;
+ if (IN6_IS_SCOPE_LINKLOCAL(dst)) {
+ /* Do not lookup link-local addresses in rtable */
+ /* XXX: Do lwref on egress ifp */
+ return (fib6_lla_to_nh_extended(dst, scopeid, pnh6));
+ }
+
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_ext: bad fibnum"));
rnh = rt_tables_get_rnh(fibnum, AF_INET6);
if (rnh == NULL)
@@ -665,7 +1015,9 @@ fib6_lookup_nh_ext(uint32_t fibnum, stru
/* Prepare lookup key */
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_len = sizeof(struct sockaddr_in6);
- sin6.sin6_addr = dst;
+ sin6.sin6_addr = *dst;
+ sin6.sin6_scope_id = scopeid;
+ sa6_embedscope(&sin6, 0);
RADIX_NODE_HEAD_RLOCK(rnh);
rn = rnh->rnh_matchaddr((void *)&sin6, rnh);
Modified: projects/routing/sys/net/rt_nhops.h
==============================================================================
--- projects/routing/sys/net/rt_nhops.h Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/net/rt_nhops.h Tue Nov 4 15:39:56 2014 (r274089)
@@ -74,7 +74,8 @@ struct nhop_prepend {
uint16_t ifp_idx; /* Transmit interface index */
uint16_t nhop_idx; /* L2 multipath nhop index */
} i;
- uint16_t spare1[3];
+ uint16_t aifp_idx; /* Interface address index */
+ uint16_t spare1[2];
union {
char data[MAX_PREPEND_LEN]; /* data to prepend */
#ifdef INET
@@ -102,6 +103,7 @@ struct nhop_prepend {
#define NH_LIFP(nh) ifnet_byindex_locked((nh)->lifp_idx)
#define NH_TIFP(nh) ifnet_byindex_locked((nh)->i.ifp_idx)
+#define NH_AIFP(nh) ifnet_byindex_locked((nh)->aifp_idx)
/* L2/L3 recursive nexthop */
struct nhop_multi {
@@ -173,7 +175,6 @@ struct nhop6_extended {
uint16_t nh_flags; /* nhop flags */
uint8_t spare[4];
struct in6_addr nh_addr; /* GW/DST IPv6 address */
- struct in6_addr nh_src; /* default source IPv6 address */
uint64_t spare2[2];
};
@@ -186,9 +187,10 @@ struct nhopu_extended {
struct route_info {
struct nhop_prepend *ri_nh; /* Desired nexthop to use */
- struct nhop64_basic *ri_nh_info; /* Get selected route info */
- uint16_t ri_mtu;
- uint16_t spare[3];
+ struct nhopu_basic *ri_nh_info; /* Get selected route info */
+ uint16_t ri_mtu; /* Get selected route MTU */
+ uint16_t spare;
+ uint32_t scopeid; /* Desired scope id to use */
};
struct route_compat {
@@ -206,9 +208,9 @@ void fib4_free_nh_ext(uint32_t fibnum, s
#define NHOP_LOOKUP_REF 0x01
-int fib6_lookup_nh_basic(uint32_t fibnum, struct in6_addr dst, uint32_t flowid,
- struct nhop6_basic *pnh6);
-int fib6_lookup_nh_ext(uint32_t fibnum, struct in6_addr dst,
+int fib6_lookup_nh_basic(uint32_t fibnum, struct in6_addr *dst,
+ uint32_t scopeid, uint32_t flowid, struct nhop6_basic *pnh6);
+int fib6_lookup_nh_ext(uint32_t fibnum, struct in6_addr *dst,
uint32_t scopeid, uint32_t flowid, uint32_t flags,
struct nhop6_extended *pnh6);
void fib6_free_nh_ext(uint32_t fibnum, struct nhop6_extended *pnh6);
@@ -228,6 +230,11 @@ int fib4_sendmbuf(struct ifnet *ifp, str
void fib6_free_nh_prepend(uint32_t fibnum, struct nhop_prepend *nh);
void fib6_choose_prepend(uint32_t fibnum, struct nhop_prepend *nh_src,
uint32_t flowid, struct nhop_prepend *nh, struct nhop6_extended *nh_ext);
+int fib6_lookup_prepend(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
+ struct mbuf *m, struct nhop_prepend *nh, struct nhop6_extended *nh_ext);
+
+int fib6_sendmbuf(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
+ struct nhop_prepend *nh);
#define FWD_INET 0
#define FWD_INET6 1
Modified: projects/routing/sys/netgraph/ng_ipfw.c
==============================================================================
--- projects/routing/sys/netgraph/ng_ipfw.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netgraph/ng_ipfw.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -271,8 +271,7 @@ ng_ipfw_rcvdata(hook_p hook, item_p item
#endif
#ifdef INET6
case IPV6_VERSION >> 4:
- return (ip6_output(m, NULL, NULL, 0, NULL,
- NULL, NULL));
+ return (ip6_output(m, NULL, NULL, 0, NULL, NULL));
#endif
}
}
Modified: projects/routing/sys/netinet/ip_carp.c
==============================================================================
--- projects/routing/sys/netinet/ip_carp.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet/ip_carp.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -930,7 +930,7 @@ carp_send_ad_locked(struct carp_softc *s
CARPSTATS_INC(carps_opackets6);
carp_send_ad_error(sc, ip6_output(m, NULL, NULL, 0,
- &sc->sc_carpdev->if_carp->cif_im6o, NULL, NULL));
+ &sc->sc_carpdev->if_carp->cif_im6o, NULL));
}
#endif /* INET6 */
Modified: projects/routing/sys/netinet/ip_divert.c
==============================================================================
--- projects/routing/sys/netinet/ip_divert.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet/ip_divert.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -456,7 +456,7 @@ div_output(struct socket *so, struct mbu
break;
#ifdef INET6
case IPV6_VERSION >> 4:
- error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+ error = ip6_output(m, NULL, NULL, 0, NULL, NULL);
break;
#endif
}
Modified: projects/routing/sys/netinet/ip_output.c
==============================================================================
--- projects/routing/sys/netinet/ip_output.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet/ip_output.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -110,9 +110,13 @@ extern struct protosw inetsw[];
* header (with len, off, ttl, proto, tos, src, dst).
* The mbuf chain containing the packet will be freed.
* The mbuf opt, if present, will not be freed.
- * If route ro is present and has ro_rt initialized, route lookup would be
- * skipped and ro->ro_rt would be used. If ro is present but ro->ro_rt is NULL,
- * then result of route lookup is stored in ro->ro_rt.
+ *
+ * If @ri is present:
+ * - if ri->ri_nh is not null, route will be calculated using ri_nh.
+ * - if ri->ri_nh_info is set, nhop4_basic route info will be stored on
+ * successful transmit (error=0).
+ * - ri->ri_mtu will be set if packet fails to be transmitted due to MTU
+ * issues
*
* In the IP forwarding case, the packet will arrive with options already
* inserted, so must have a NULL opt pointer.
@@ -364,21 +368,12 @@ again:
nh = &local_nh;
ifp = NH_LIFP(nh);
mtu = nh->nh_mtu;
- if (nh->nh_flags & (RTF_HOST|RTF_GATEWAY)) {
- /* XXX: Set RTF_BROADCAST if GW address is broadcast */
+ if (nh->nh_flags & (RTF_HOST|RTF_GATEWAY))
isbroadcast = (nh->nh_flags & RTF_BROADCAST);
- } else
+ else
isbroadcast = in_broadcast(dst, ifp);
}
- /*
- * XXX: Move somewhere to sendit
- */
- if (ri != NULL) {
- ri->ri_mtu = mtu;
- }
-
-
/* Catch a possible divide by zero later. */
KASSERT(mtu > 0, ("%s: mtu %d <= 0, rte=%p (rt_flags=0x%08x) ifp=%p",
__func__, mtu, nh, (nh != NULL) ? nh->nh_flags : 0, ifp));
@@ -607,6 +602,20 @@ sendit:
goto again;
}
+ if (ri != NULL) {
+ ri->ri_mtu = mtu;
+ if (ri->ri_nh_info != NULL) {
+ struct nhop4_basic *pnh4;
+
+ pnh4 = &ri->ri_nh_info->u.nh4;
+ pnh4->nh_ifp = ifp;
+ pnh4->nh_flags = nh ? nh->nh_flags : 0;
+ pnh4->nh_mtu = mtu;
+ /* XXX: This is not always correct. */
+ pnh4->nh_addr = dst;
+ }
+ }
+
passout:
/* 127/8 must not appear on wire - RFC1122. */
if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
Modified: projects/routing/sys/netinet/sctp_os_bsd.h
==============================================================================
--- projects/routing/sys/netinet/sctp_os_bsd.h Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet/sctp_os_bsd.h Tue Nov 4 15:39:56 2014 (r274089)
@@ -452,9 +452,9 @@ typedef struct rtentry sctp_rtentry_t;
if (local_stcb && local_stcb->sctp_ep) \
result = ip6_output(o_pak, \
((struct in6pcb *)(local_stcb->sctp_ep))->in6p_outputopts, \
- (ro), 0, 0, ifp, NULL); \
+ NULL, 0, NULL, NULL); \
else \
- result = ip6_output(o_pak, NULL, (ro), 0, 0, ifp, NULL); \
+ result = ip6_output(o_pak, NULL, NULL, 0, NULL, NULL); \
}
struct mbuf *
Modified: projects/routing/sys/netinet/tcp_offload.c
==============================================================================
--- projects/routing/sys/netinet/tcp_offload.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet/tcp_offload.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#define TCPOUTFLAGS
#include <netinet/tcp_fsm.h>
#include <netinet/toecore.h>
+#include <netinet6/scope6_var.h>
int registered_toedevs;
@@ -86,11 +87,13 @@ tcp_offload_connect(struct socket *so, s
goto done;
} else if (af == AF_INET6) {
struct sockaddr_in6 *sin6;
+ struct in6_addr dst;
+ uint32_t scopeid;
sin6 = (struct sockaddr_in6 *)nam;
+ in6_splitscope(&sin6->sin6_addr, &dst, &scopeid);
- if (fib6_lookup_nh_ext(fibnum,
- sin6->sin6_addr, sin6->sin6_scope_id,
+ if (fib6_lookup_nh_ext(fibnum, &dst, scopeid,
0, NHOP_LOOKUP_REF, &nhu_ext.u.nh6) != 0)
return (EHOSTUNREACH);
Modified: projects/routing/sys/netinet/tcp_output.c
==============================================================================
--- projects/routing/sys/netinet/tcp_output.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet/tcp_output.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -1257,9 +1257,9 @@ send:
*/
#ifdef INET6
if (isipv6) {
- struct route_in6 ro;
+ struct route_info ri;
- bzero(&ro, sizeof(ro));
+ bzero(&ri, sizeof(ri));
/*
* we separately set hoplimit for every segment, since the
* user might want to change the value via setsockopt.
@@ -1281,13 +1281,12 @@ send:
TCP_PROBE5(send, NULL, tp, ip6, tp, th);
/* TODO: IPv6 IP6TOS_ECT bit on */
- error = ip6_output(m, tp->t_inpcb->in6p_outputopts, &ro,
+ error = ip6_output(m, tp->t_inpcb->in6p_outputopts, &ri,
((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0),
- NULL, NULL, tp->t_inpcb);
+ NULL, tp->t_inpcb);
- if (error == EMSGSIZE && ro.ro_rt != NULL)
- mtu = ro.ro_rt->rt_mtu;
- RO_RTFREE(&ro);
+ if (error == EMSGSIZE)
+ mtu = ri.ri_mtu;
}
#endif /* INET6 */
#if defined(INET) && defined(INET6)
@@ -1324,7 +1323,7 @@ send:
TCP_PROBE5(send, NULL, tp, ip, tp, th);
error = ip_output(m, tp->t_inpcb->inp_options, &ri,
- ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), 0,
+ ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), NULL,
tp->t_inpcb);
if (error == EMSGSIZE)
Modified: projects/routing/sys/netinet/tcp_subr.c
==============================================================================
--- projects/routing/sys/netinet/tcp_subr.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet/tcp_subr.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -725,7 +725,7 @@ tcp_respond(struct tcpcb *tp, void *ipge
TCP_PROBE5(send, NULL, tp, mtod(m, const char *), tp, nth);
#ifdef INET6
if (isipv6)
- (void) ip6_output(m, NULL, NULL, ipflags, NULL, NULL, inp);
+ (void) ip6_output(m, NULL, NULL, ipflags, NULL, inp);
#endif /* INET6 */
#if defined(INET) && defined(INET6)
else
Modified: projects/routing/sys/netinet/tcp_syncache.c
==============================================================================
--- projects/routing/sys/netinet/tcp_syncache.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet/tcp_syncache.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -1571,7 +1571,7 @@ syncache_respond(struct syncache *sc, st
return (error);
}
#endif
- error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+ error = ip6_output(m, NULL, NULL, 0, NULL, NULL);
}
#endif
#if defined(INET6) && defined(INET)
Modified: projects/routing/sys/netinet/tcp_timewait.c
==============================================================================
--- projects/routing/sys/netinet/tcp_timewait.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet/tcp_timewait.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -596,7 +596,7 @@ tcp_twrespond(struct tcptw *tw, int flag
sizeof(struct tcphdr) + optlen, IPPROTO_TCP, 0);
ip6->ip6_hlim = in6_selecthlim(inp, NULL);
error = ip6_output(m, inp->in6p_outputopts, NULL,
- (tw->tw_so_options & SO_DONTROUTE), NULL, NULL, inp);
+ (tw->tw_so_options & SO_DONTROUTE), NULL, inp);
}
#endif
#if defined(INET6) && defined(INET)
Modified: projects/routing/sys/netinet6/icmp6.c
==============================================================================
--- projects/routing/sys/netinet6/icmp6.c Tue Nov 4 11:29:49 2014 (r274088)
+++ projects/routing/sys/netinet6/icmp6.c Tue Nov 4 15:39:56 2014 (r274089)
@@ -2142,7 +2142,12 @@ icmp6_reflect(struct mbuf *m, size_t off
int plen;
int type, code;
struct ifnet *outif = NULL;
- struct in6_addr origdst, src, *srcp = NULL;
+ struct in6_addr origdst, src, dst;
+ struct route_info ri;
+ struct nhop6_basic nh6;
+ uint32_t scopeid;
+ int e;
+
/* too short to reflect */
if (off < sizeof(struct ip6_hdr)) {
@@ -2206,11 +2211,13 @@ icmp6_reflect(struct mbuf *m, size_t off
* procedure of an outgoing packet of our own, in which case we need
* to search in the ifaddr list.
*/
+ memset(&src, 0, sizeof(src));
if (!IN6_IS_ADDR_MULTICAST(&origdst)) {
if ((ia = ip6_getdstifaddr(m))) {
if (!(ia->ia6_flags &
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)))
- srcp = &ia->ia_addr.sin6_addr;
+ src = ia->ia_addr.sin6_addr;
+ ifa_free(&ia->ia_ifa);
} else {
struct sockaddr_in6 d;
@@ -2223,54 +2230,53 @@ icmp6_reflect(struct mbuf *m, size_t off
if (ia &&
!(ia->ia6_flags &
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY))) {
- srcp = &ia->ia_addr.sin6_addr;
+ src = ia->ia_addr.sin6_addr;
+ ifa_free(&ia->ia_ifa);
}
}
}
- if (srcp == NULL) {
- int e;
- struct sockaddr_in6 sin6;
- struct route_in6 ro;
+
+ ip6->ip6_src = src;
+ ip6->ip6_flow = 0;
+ ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
+ ip6->ip6_vfc |= IPV6_VERSION;
+ ip6->ip6_nxt = IPPROTO_ICMPV6;
+ if (outif)
+ ip6->ip6_hlim = ND_IFINFO(outif)->chlim;
+ else if (m->m_pkthdr.rcvif) {
+ /* XXX: This may not be the outgoing interface */
+ ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
+ } else
+ ip6->ip6_hlim = V_ip6_defhlim;
+
+
+ /*
+ * Deembed scope
+ */
+ in6_splitscope(&ip6->ip6_dst, &dst, &scopeid);
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&src)) {
/*
* This case matches to multicasts, our anycast, or unicasts
* that we do not own. Select a source address based on the
* source address of the erroneous packet.
*/
- bzero(&sin6, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- sin6.sin6_len = sizeof(sin6);
- sin6.sin6_addr = ip6->ip6_dst; /* zone ID should be embedded */
-
- bzero(&ro, sizeof(ro));
- e = in6_selectsrc(&sin6, NULL, NULL, &ro, NULL, &outif, &src);
- if (ro.ro_rt)
- RTFREE(ro.ro_rt); /* XXX: we could use this */
+
+ e = in6_selectsrc_addr(M_GETFIB(m), &dst, scopeid, &src);
if (e) {
char ip6buf[INET6_ADDRSTRLEN];
nd6log((LOG_DEBUG,
"icmp6_reflect: source can't be determined: "
"dst=%s, error=%d\n",
- ip6_sprintf(ip6buf, &sin6.sin6_addr), e));
+ ip6_sprintf(ip6buf, &dst), e));
goto bad;
}
- srcp = &src;
+ ip6->ip6_src = src;
}
- ip6->ip6_src = *srcp;
- ip6->ip6_flow = 0;
- ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
- ip6->ip6_vfc |= IPV6_VERSION;
- ip6->ip6_nxt = IPPROTO_ICMPV6;
- if (outif)
- ip6->ip6_hlim = ND_IFINFO(outif)->chlim;
- else if (m->m_pkthdr.rcvif) {
- /* XXX: This may not be the outgoing interface */
- ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
- } else
- ip6->ip6_hlim = V_ip6_defhlim;
-
+ /* finalize header */
icmp6->icmp6_cksum = 0;
icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
sizeof(struct ip6_hdr), plen);
@@ -2281,17 +2287,20 @@ icmp6_reflect(struct mbuf *m, size_t off
m->m_flags &= ~(M_BCAST|M_MCAST);
- ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
- if (outif)
- icmp6_ifoutstat_inc(outif, type, code);
+ memset(&ri, 0, sizeof(ri));
+ ri.ri_nh_info = (struct nhopu_basic *)&nh6;
+ ri.scopeid = scopeid;
+
+ e = ip6_output(m, NULL, &ri, 0, NULL, NULL);
+ if (e == 0) {
+ /* XXX: Possible use after free */
+ outif = nh6.nh_ifp;
+ //icmp6_ifoutstat_inc(outif, type, code);
+ }
- if (ia != NULL)
- ifa_free(&ia->ia_ifa);
return;
bad:
- if (ia != NULL)
- ifa_free(&ia->ia_ifa);
m_freem(m);
return;
}
@@ -2387,11 +2396,11 @@ icmp6_redirect_input(struct mbuf *m, int
}
{
/* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
- struct nhop6_extended nh_ext;
+ struct nhop6_basic nh6;
- if (fib6_lookup_nh_ext(RT_DEFAULT_FIB, reddst6, 0, 0, 0, &nh_ext) == 0){
+ if (fib6_lookup_nh_basic(RT_DEFAULT_FIB, &reddst6, 0, 0, &nh6)==0) {
/* XXX: Think about AF_LINK GW */
- if ((nh_ext.nh_flags & NHF_GATEWAY) == 0) {
+ if ((nh6.nh_flags & NHF_GATEWAY) == 0) {
nd6log((LOG_ERR,
"ICMP6 redirect rejected; no route "
"with inet6 gateway found for redirect dst: %s\n",
@@ -2399,12 +2408,12 @@ icmp6_redirect_input(struct mbuf *m, int
goto bad;
}
- if (bcmp(&src6, &nh_ext.nh_addr, sizeof(struct in6_addr)) != 0){
+ if (IN6_ARE_ADDR_EQUAL(&src6, &nh6.nh_addr) == 0) {
nd6log((LOG_ERR,
"ICMP6 redirect rejected; "
"not equal to gw-for-src=%s (must be same): "
"%s\n",
- ip6_sprintf(ip6buf, &nh_ext.nh_addr),
+ ip6_sprintf(ip6buf, &nh6.nh_addr),
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
goto bad;
}
@@ -2526,6 +2535,9 @@ icmp6_redirect_output(struct mbuf *m0, s
u_char *p;
struct ifnet *outif = NULL;
struct sockaddr_in6 src_sa;
+ struct route_info ri;
+ struct nhop6_basic nh6;
+ int e;
icmp6_errcount(ND_REDIRECT, 0);
@@ -2784,9 +2796,14 @@ noredhdropt:;
m_tag_prepend(m, mtag);
}
+ memset(&ri, 0, sizeof(ri));
+ memset(&nh6, 0, sizeof(nh6));
+ ri.ri_nh_info = (struct nhopu_basic *)&nh6;
+
/* send the packet to outside... */
- ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
- if (outif) {
+ e = ip6_output(m, NULL, &ri, 0, NULL, NULL);
+ if (e == 0) {
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list