diff options
Diffstat (limited to 'sys/netpfil')
| -rw-r--r-- | sys/netpfil/pf/pf.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index c7d5e923d50b..10e73ce1e7b9 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -9981,6 +9981,21 @@ pf_route(struct pf_krule *r, struct ifnet *oifp, } /* + * If the output interface does not accept unmapped mbufs, convert + * them to mapped mbufs. + */ + if ((ifp->if_capenable & IFCAP_MEXTPG) == 0) { + error = mb_unmapped_to_ext(m0, &md); + if (error) + goto done; + /* + * The first mbuf should not be reallocated because it is + * always mapped. + */ + MPASS(m0 == md); + } + + /* * If small enough for interface, or the interface will take * care of the fragmentation for us, we can just send directly. */ @@ -10321,6 +10336,11 @@ pf_route6(struct pf_krule *r, struct ifnet *oifp, } if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) { + if ((ifp->if_capenable & IFCAP_MEXTPG) == 0) { + if (mb_unmapped_to_ext(m0, &md) != 0) + goto done; + MPASS(m0 == md); + } md = m0; pf_dummynet_route(pd, s, r, ifp, sintosa(&dst), &md); if (md != NULL) { @@ -11585,6 +11605,7 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 { struct pfi_kkif *kif; u_short action, reason = 0; + struct mbuf *m; struct m_tag *mtag; struct pf_krule *a = NULL, *r = &V_pf_default_rule; struct pf_kstate *s = NULL; @@ -11620,6 +11641,12 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 } if (__predict_false(! M_WRITABLE(*m0))) { + /* Need to convert unmapped mbufs before calling m_unshare(). */ + if (mb_unmapped_to_ext(*m0, &m) != 0) { + *m0 = NULL; + return (PF_DROP); + } + MPASS(*m0 == m); *m0 = m_unshare(*m0, M_NOWAIT); if (*m0 == NULL) { return (PF_DROP); @@ -11639,6 +11666,14 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 *m0 = NULL; return (PF_PASS); } + + /* + * No need to call mb_unmapped_to_ext() here because it had + * already been called in pf_route()/pf_route6() and dummynet + * re-injected this packet. + */ + + M_ASSERTMAPPED(*m0); (ifp->if_output)(ifp, *m0, sintosa(&pd.pf_mtag->dst), NULL); *m0 = NULL; return (PF_PASS); |
