This is the companion diff to the ether_output() one. Since bluhm@
mentioned it, here it is!
The idea is, once again, to stop inserting cloned route entries in L2
functions. The only place that insert cloned route entries should be
inside rtalloc(9) when RT_RESOLVE is passed.
Index: net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.971
diff -u -p -r1.971 pf.c
--- net/pf.c 23 May 2016 12:26:28 -0000 1.971
+++ net/pf.c 23 May 2016 12:39:54 -0000
@@ -5506,6 +5506,7 @@ pf_route(struct mbuf **m, struct pf_rule
int error = 0;
unsigned int rtableid;
+
if (m == NULL || *m == NULL || r == NULL ||
(dir != PF_IN && dir != PF_OUT) || oifp == NULL)
panic("pf_route: invalid parameters");
@@ -5665,11 +5666,13 @@ pf_route6(struct mbuf **m, struct pf_rul
{
struct mbuf *m0;
struct sockaddr_in6 *dst, sin6;
+ struct rtentry *rt = NULL;
struct ip6_hdr *ip6;
struct ifnet *ifp = NULL;
struct pf_addr naddr;
struct pf_src_node *sns[PF_SN_MAX];
struct m_tag *mtag;
+ unsigned int rtableid;
if (m == NULL || *m == NULL || r == NULL ||
(dir != PF_IN && dir != PF_OUT) || oifp == NULL)
@@ -5702,6 +5705,7 @@ pf_route6(struct mbuf **m, struct pf_rul
dst->sin6_family = AF_INET6;
dst->sin6_len = sizeof(*dst);
dst->sin6_addr = ip6->ip6_dst;
+ rtableid = m0->m_pkthdr.ph_rtableid;
if (!r->rt) {
m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
@@ -5754,7 +5758,13 @@ pf_route6(struct mbuf **m, struct pf_rul
if ((mtag = m_tag_find(m0, PACKET_TAG_PF_REASSEMBLED, NULL))) {
(void) pf_refragment6(&m0, mtag, dst, ifp);
} else if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
- nd6_output(ifp, m0, dst, NULL);
+ rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid);
+ if (rt == NULL) {
+ ip6stat.ip6s_noroute++;
+ goto bad;
+ }
+ nd6_output(ifp, m0, dst, rt);
+ rtfree(rt);
} else {
icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
}
Index: net/pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.183
diff -u -p -r1.183 pf_norm.c
--- net/pf_norm.c 24 Nov 2015 13:37:16 -0000 1.183
+++ net/pf_norm.c 23 May 2016 12:39:55 -0000
@@ -750,7 +750,15 @@ pf_refragment6(struct mbuf **m0, struct
if (ifp == NULL) {
ip6_forward(m, 0);
} else if ((u_long)m->m_pkthdr.len <= ifp->if_mtu) {
- nd6_output(ifp, m, dst, NULL);
+ struct rtentry *rt;
+ rt = rtalloc(sin6tosa(dst), RT_RESOLVE,
+ m->m_pkthdr.ph_rtableid);
+ if (rt == NULL) {
+ ip6stat.ip6s_noroute++;
+ } else {
+ nd6_output(ifp, m, dst, rt);
+ rtfree(rt);
+ }
} else {
icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0,
ifp->if_mtu);
Index: netinet6/nd6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6.c,v
retrieving revision 1.179
diff -u -p -r1.179 nd6.c
--- netinet6/nd6.c 17 May 2016 08:29:14 -0000 1.179
+++ netinet6/nd6.c 23 May 2016 12:39:55 -0000
@@ -1507,20 +1507,15 @@ nd6_output(struct ifnet *ifp, struct mbu
struct mbuf *m = m0;
struct rtentry *rt = rt0;
struct llinfo_nd6 *ln = NULL;
- int created = 0, error = 0;
+ int error = 0;
if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
goto sendpkt;
- /*
- * next hop determination.
- */
- if (rt0 != NULL) {
- error = rt_checkgate(rt0, &rt);
- if (error) {
- m_freem(m);
- return (error);
- }
+ error = rt_checkgate(rt0, &rt);
+ if (error) {
+ m_freem(m);
+ return (error);
}
if (nd6_need_cache(ifp) == 0)
@@ -1532,42 +1527,17 @@ nd6_output(struct ifnet *ifp, struct mbu
* At this point, the destination of the packet must be a unicast
* or an anycast address(i.e. not a multicast).
*/
-
- /* Look up the neighbor cache for the nexthop */
- if (rt != NULL && (rt->rt_flags & RTF_LLINFO) != 0)
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- else {
- /*
- * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
- * the condition below is not very efficient. But we believe
- * it is tolerable, because this should be a rare case.
- */
- if (nd6_is_addr_neighbor(dst, ifp)) {
- rt = nd6_lookup(&dst->sin6_addr, 1, ifp,
- ifp->if_rdomain);
- if (rt != NULL) {
- created = 1;
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- }
- }
+ if (!ISSET(rt->rt_flags, RTF_LLINFO)) {
+ char addr[INET6_ADDRSTRLEN];
+ log(LOG_DEBUG, "%s: %s: route contains no ND information\n",
+ __func__, inet_ntop(AF_INET6,
+ &satosin6(rt_key(rt))->sin6_addr, addr, sizeof(addr)));
+ m_freem(m);
+ return (EINVAL);
}
- if (ln == NULL || rt == NULL) {
- if ((ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD) == 0) {
- char addr[INET6_ADDRSTRLEN];
-
- log(LOG_DEBUG, "%s: can't allocate llinfo for %s "
- "(ln=%p, rt=%p)\n", __func__,
- inet_ntop(AF_INET6, &dst->sin6_addr,
- addr, sizeof(addr)),
- ln, rt);
- m_freem(m);
- if (created)
- rtfree(rt);
- return (EIO); /* XXX: good error? */
- }
- goto sendpkt; /* send anyway */
- }
+ ln = (struct llinfo_nd6 *)rt->rt_llinfo;
+ KASSERT(ln != NULL);
/*
* Move this entry to the head of the queue so that it is less likely
@@ -1617,14 +1587,10 @@ nd6_output(struct ifnet *ifp, struct mbu
(long)ND_IFINFO(ifp)->retrans * hz / 1000);
nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
}
- if (created)
- rtfree(rt);
return (0);
sendpkt:
error = ifp->if_output(ifp, m, sin6tosa(dst), rt);
- if (created)
- rtfree(rt);
return (error);
}