diff options
author | Kristof Provost <kp@FreeBSD.org> | 2024-09-16 11:58:49 +0000 |
---|---|---|
committer | Kristof Provost <kp@FreeBSD.org> | 2024-10-01 07:55:14 +0000 |
commit | 1b745d8b23e465872e171579cfc944bd57e5501a (patch) | |
tree | 12087f24b57bf0e2ad3af3f5fa131662a334882c | |
parent | 288bec2b2bd10d80cdc35a687e8a373f5931c80d (diff) | |
download | src-1b745d8b23e465872e171579cfc944bd57e5501a.tar.gz src-1b745d8b23e465872e171579cfc944bd57e5501a.zip |
pf: move normalisation into pf_setup_pdesc()
This simplifies the code slightly, and brings us closer to the OpenBSD code.
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D46707
-rw-r--r-- | sys/netpfil/pf/pf.c | 111 |
1 files changed, 60 insertions, 51 deletions
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index ccfe1a0fcd96..51b4cebc88e9 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -8462,12 +8462,16 @@ pf_dummynet_route(struct pf_pdesc *pd, struct pf_kstate *s, } static int -pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf *m, +pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, u_short *action, u_short *reason, struct pfi_kkif *kif, struct pf_krule **a, struct pf_krule **r, struct pf_kstate **s, struct pf_kruleset **ruleset, int *off, int *hdrlen, struct inpcb *inp, struct pf_rule_actions *default_actions) { + struct mbuf *m = *m0; + + memset(pd, 0, sizeof(*pd)); + pd->dir = dir; TAILQ_INIT(&pd->sctp_multihome_jobs); if (default_actions != NULL) @@ -8486,6 +8490,22 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf *m, case AF_INET: { struct ip *h; + if (__predict_false(m->m_len < sizeof(struct ip)) && + (m = *m0 = m_pullup(*m0, sizeof(struct ip))) == NULL) { + DPFPRINTF(PF_DEBUG_URGENT, + ("pf_test: m_len < sizeof(struct ip), pullup failed\n")); + *action = PF_DROP; + REASON_SET(reason, PFRES_SHORT); + return (-1); + } + + if (pf_normalize_ip(m0, kif, reason, pd) != PF_PASS) { + /* We do IP header normalization and packet reassembly here */ + *action = PF_DROP; + return (-1); + } + m = *m0; + h = mtod(m, struct ip *); *off = h->ip_hl << 2; if (*off < (int)sizeof(*h)) { @@ -8533,6 +8553,23 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf *m, struct ip6_hdr *h; int terminal = 0; + if (__predict_false(m->m_len < sizeof(struct ip6_hdr)) && + (m = *m0 = m_pullup(*m0, sizeof(struct ip6_hdr))) == NULL) { + DPFPRINTF(PF_DEBUG_URGENT, + ("pf_test6: m_len < sizeof(struct ip6_hdr)" + ", pullup failed\n")); + *action = PF_DROP; + REASON_SET(reason, PFRES_SHORT); + return (-1); + } + + /* We do IP header normalization and packet reassembly here */ + if (pf_normalize_ip6(m0, kif, reason, pd) != PF_PASS) { + *action = PF_DROP; + return (-1); + } + m = *m0; + h = mtod(m, struct ip6_hdr *); pd->src = (struct pf_addr *)&h->ip6_src; pd->dst = (struct pf_addr *)&h->ip6_dst; @@ -8855,65 +8892,44 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 return (PF_PASS); } +#ifdef INET6 + /* + * If we end up changing IP addresses (e.g. binat) the stack may get + * confused and fail to send the icmp6 packet too big error. Just send + * it here, before we do any NAT. + */ + if (af == AF_INET6 && dir == PF_OUT && pflags & PFIL_FWD && + IN6_LINKMTU(ifp) < pf_max_frag_size(m)) { + PF_RULES_RUNLOCK(); + *m0 = NULL; + icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, IN6_LINKMTU(ifp)); + return (PF_DROP); + } +#endif + if (__predict_false(! M_WRITABLE(*m0))) { m = *m0 = m_unshare(*m0, M_NOWAIT); if (*m0 == NULL) return (PF_DROP); } - memset(&pd, 0, sizeof(pd)); - pd.dir = dir; + if (pf_setup_pdesc(af, dir, &pd, m0, &action, &reason, kif, &a, &r, + &s, &ruleset, &off, &hdrlen, inp, default_actions) == -1) { + if (action != PF_PASS) + pd.act.log |= PF_LOG_FORCE; + goto done; + } + m = *m0; switch (af) { #ifdef INET case AF_INET: - if (__predict_false(m->m_len < sizeof(struct ip)) && - (m = *m0 = m_pullup(*m0, sizeof(struct ip))) == NULL) { - DPFPRINTF(PF_DEBUG_URGENT, - ("pf_test: m_len < sizeof(struct ip), pullup failed\n")); - PF_RULES_RUNLOCK(); - return (PF_DROP); - } - - if (pf_normalize_ip(m0, kif, &reason, &pd) != PF_PASS) { - /* We do IP header normalization and packet reassembly here */ - action = PF_DROP; - goto done; - } - m = *m0; /* pf_normalize messes with m0 */ h = mtod(m, struct ip *); ttl = h->ip_ttl; break; #endif #ifdef INET6 case AF_INET6: - /* - * If we end up changing IP addresses (e.g. binat) the stack may get - * confused and fail to send the icmp6 packet too big error. Just send - * it here, before we do any NAT. - */ - if (dir == PF_OUT && pflags & PFIL_FWD && IN6_LINKMTU(ifp) < pf_max_frag_size(m)) { - PF_RULES_RUNLOCK(); - *m0 = NULL; - icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, IN6_LINKMTU(ifp)); - return (PF_DROP); - } - - if (__predict_false(m->m_len < sizeof(struct ip6_hdr)) && - (m = *m0 = m_pullup(*m0, sizeof(struct ip6_hdr))) == NULL) { - DPFPRINTF(PF_DEBUG_URGENT, - ("pf_test6: m_len < sizeof(struct ip6_hdr)" - ", pullup failed\n")); - PF_RULES_RUNLOCK(); - return (PF_DROP); - } - - /* We do IP header normalization and packet reassembly here */ - if (pf_normalize_ip6(m0, kif, &reason, &pd) != PF_PASS) { - action = PF_DROP; - goto done; - } - m = *m0; /* pf_normalize messes with m0 */ h6 = mtod(m, struct ip6_hdr *); ttl = h6->ip6_hlim; break; @@ -8922,13 +8938,6 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 panic("Unknown af %d", af); } - if (pf_setup_pdesc(af, dir, &pd, m, &action, &reason, kif, &a, &r, - &s, &ruleset, &off, &hdrlen, inp, default_actions) == -1) { - if (action != PF_PASS) - pd.act.log |= PF_LOG_FORCE; - goto done; - } - if (pd.pf_mtag != NULL && (pd.pf_mtag->flags & PF_MTAG_FLAG_ROUTE_TO)) { pd.pf_mtag->flags &= ~PF_MTAG_FLAG_ROUTE_TO; |