From 8dcdc32e493242762d148fc5415f1e21365d883c Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Sat, 24 Sep 2016 19:54:07 +0200 Subject: [PATCH] dummynet: passin after dispatch Based on a patch originally found in m0n0wall, expanded to IPv6 and aligned with FreeBSD's IP input path. The limit may not be correctly accounted for on the WAN interface due to dummynet counting the packet again even though it was already processed. The problem here is that there's no proper way to reinject the packet at the point where it was previously removed from so we make the assumption that ip input was already done (including pfil) and more or less directly move to packet output processing. While here move the passin label up to take the extra check but avoiding a second label. Also remove the spurious tag read for forward check since we don't use it and we should really trust the mbuf flag. --- sys/netinet/ip_input.c | 14 ++++++++++++-- sys/netinet6/in6.h | 1 + sys/netinet6/ip6_input.c | 14 +++++++++++--- sys/netpfil/ipfw/ip_dn_io.c | 6 ++++++ 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 1b080aa65e4..5524f23f780 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -479,6 +479,16 @@ ip_input(struct mbuf *m) goto ours; } + if (m->m_flags & M_PASSIN) { + /* Dummynet reinjected this packet. */ + m->m_flags &= ~M_PASSIN; + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; + ip_len = ntohs(ip->ip_len); + ifp = m->m_pkthdr.rcvif; + goto passin; + } + IPSTAT_INC(ips_total); if (__predict_false(m->m_pkthdr.len < sizeof(struct ip))) @@ -633,8 +643,9 @@ tooshort: m->m_flags &= ~M_FASTFWD_OURS; goto ours; } +passin: if (m->m_flags & M_IP_NEXTHOP) { - if (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) { + { /* * Directly ship the packet on. This allows * forwarding packets originally destined to us @@ -644,7 +655,6 @@ tooshort: return; } } -passin: /* * Process options and, if not destined for us, diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index ce3bbea6b8e..43d189d6a35 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -659,6 +659,7 @@ struct ip6_mtuinfo { #define M_AUTHIPDGM M_PROTO7 #define M_RTALERT_MLD M_PROTO8 #define M_FRAGMENTED M_PROTO9 /* contained fragment header */ +#define M_PASSIN M_PROTO11 /* previously processed input */ #ifdef _KERNEL struct cmsghdr; diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index c5b9f9202ce..5e0005bdef3 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -561,6 +561,15 @@ ip6_input(struct mbuf *m) goto passin; } + if (m->m_flags & M_PASSIN) { + /* + * Dummynet reinjected this packet. + */ + m->m_flags &= ~M_PASSIN; + ip6 = mtod(m, struct ip6_hdr *); + goto passin; + } + /* * mbuf statistics */ @@ -739,8 +748,8 @@ ip6_input(struct mbuf *m) return; ip6 = mtod(m, struct ip6_hdr *); srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); - if ((m->m_flags & (M_IP6_NEXTHOP | M_FASTFWD_OURS)) == M_IP6_NEXTHOP && - m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) { +passin: + if ((m->m_flags & (M_IP6_NEXTHOP | M_FASTFWD_OURS)) == M_IP6_NEXTHOP) { /* * Directly ship the packet on. This allows forwarding * packets originally destined to us to some other directly @@ -750,7 +759,6 @@ ip6_input(struct mbuf *m) return; } -passin: /* * Disambiguate address scope zones (if there is ambiguity). * We first make sure that the original source or destination address diff --git a/sys/netpfil/ipfw/ip_dn_io.c b/sys/netpfil/ipfw/ip_dn_io.c index 3e6bd0e229b..1c691a2490c 100644 --- a/sys/netpfil/ipfw/ip_dn_io.c +++ b/sys/netpfil/ipfw/ip_dn_io.c @@ -788,11 +788,17 @@ dummynet_send(struct mbuf *m) break ; case DIR_IN : + m->m_flags |= M_PASSIN; + m_tag_delete(m, tag); + netisr_dispatch(NETISR_IP, m); break; #ifdef INET6 case DIR_IN | PROTO_IPV6: + m->m_flags |= M_PASSIN; + m_tag_delete(m, tag); + netisr_dispatch(NETISR_IPV6, m); break;