git: 1941d370bf89 - main - pf: pass struct pf_pdesc to pf_walk_option6() and pf_walk_header6()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 14 Jan 2025 10:37:58 UTC
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=1941d370bf89ea9a1c3aab5ce33e04d6ba0f635d commit 1941d370bf89ea9a1c3aab5ce33e04d6ba0f635d Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2025-01-09 11:02:39 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2025-01-14 08:54:19 +0000 pf: pass struct pf_pdesc to pf_walk_option6() and pf_walk_header6() This makes their argument list shorter. Also fix a bug where pf_walk_option6() used the outer header in the pd2 case. ok henning@ mikeb@ Obtained from: OpenBSD, bluhm <bluhm@openbsd.org>, dfff4707a1 Sponsored by: Rubicon Communications, LLC ("Netgate") --- sys/net/pfvar.h | 6 +-- sys/netpfil/pf/pf.c | 143 +++++++++++++++++++++++++--------------------------- 2 files changed, 72 insertions(+), 77 deletions(-) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 3432f8dc99e1..3f109d31ccde 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1626,6 +1626,9 @@ struct pf_pdesc { u_int32_t off; /* protocol header offset */ u_int32_t hdrlen; /* protocol header length */ u_int32_t p_len; /* total length of protocol payload */ + u_int32_t extoff; /* extentsion header offset */ + u_int32_t fragoff; /* fragment header offset */ + u_int32_t jumbolen; /* length from v6 jumbo header */ u_int32_t badopts; /* v4 options or v6 routing headers */ u_int16_t *ip_sum; @@ -1634,7 +1637,6 @@ struct pf_pdesc { #define PFDESC_TCP_NORM 0x0001 /* TCP shall be statefully scrubbed */ u_int16_t virtual_proto; #define PF_VPROTO_FRAGMENT 256 - int extoff; sa_family_t af; sa_family_t naf; u_int8_t proto; @@ -2391,8 +2393,6 @@ int pf_normalize_ip(struct mbuf **, u_short *, struct pf_pdesc *); #endif /* INET */ #ifdef INET6 -int pf_walk_header6(struct mbuf *, struct ip6_hdr *, int *, int *, int *, - uint8_t *, uint32_t *, u_short *); int pf_normalize_ip6(struct mbuf **, int, u_short *, struct pf_pdesc *); void pf_poolmask(struct pf_addr *, struct pf_addr*, struct pf_addr *, struct pf_addr *, sa_family_t); diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 3d1ba8e8deb4..11b6be239ca7 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -367,7 +367,9 @@ static u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t, int, u_int16_t); static int pf_check_proto_cksum(struct mbuf *, int, int, u_int8_t, sa_family_t); -static int pf_walk_option6(struct mbuf *, int, int, uint32_t *, +static int pf_walk_option6(struct pf_pdesc *, struct ip6_hdr *, + int, int, u_short *); +static int pf_walk_header6(struct pf_pdesc *, struct ip6_hdr *, u_short *); static void pf_print_state_parts(struct pf_kstate *, struct pf_state_key *, struct pf_state_key *); @@ -7850,8 +7852,6 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, #endif /* INET */ #ifdef INET6 struct ip6_hdr h2_6; - int fragoff2, extoff2; - u_int32_t jumbolen; #endif /* INET6 */ int ipoff2 = 0; @@ -7904,9 +7904,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, return (PF_DROP); } pd2.off = ipoff2; - if (pf_walk_header6(pd->m, &h2_6, &pd2.off, &extoff2, - &fragoff2, &pd2.proto, &jumbolen, - reason) != PF_PASS) + if (pf_walk_header6(&pd2, &h2_6, reason) != PF_PASS) return (PF_DROP); pd2.src = (struct pf_addr *)&h2_6.ip6_src; @@ -9655,16 +9653,15 @@ pf_dummynet_route(struct pf_pdesc *pd, struct pf_kstate *s, #ifdef INET6 static int -pf_walk_option6(struct mbuf *m, int off, int end, uint32_t *jumbolen, +pf_walk_option6(struct pf_pdesc *pd, struct ip6_hdr *h, int off, int end, u_short *reason) { struct ip6_opt opt; struct ip6_opt_jumbo jumbo; - struct ip6_hdr *h = mtod(m, struct ip6_hdr *); while (off < end) { - if (!pf_pull_hdr(m, off, &opt.ip6o_type, sizeof(opt.ip6o_type), - NULL, reason, AF_INET6)) { + if (!pf_pull_hdr(pd->m, off, &opt.ip6o_type, + sizeof(opt.ip6o_type), NULL, reason, AF_INET6)) { DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short opt type")); return (PF_DROP); } @@ -9672,8 +9669,8 @@ pf_walk_option6(struct mbuf *m, int off, int end, uint32_t *jumbolen, off++; continue; } - if (!pf_pull_hdr(m, off, &opt, sizeof(opt), NULL, reason, - AF_INET6)) { + if (!pf_pull_hdr(pd->m, off, &opt, sizeof(opt), NULL, + reason, AF_INET6)) { DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short opt")); return (PF_DROP); } @@ -9684,7 +9681,7 @@ pf_walk_option6(struct mbuf *m, int off, int end, uint32_t *jumbolen, } switch (opt.ip6o_type) { case IP6OPT_JUMBO: - if (*jumbolen != 0) { + if (pd->jumbolen != 0) { DPFPRINTF(PF_DEBUG_MISC, ("IPv6 multiple jumbo")); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); @@ -9694,15 +9691,15 @@ pf_walk_option6(struct mbuf *m, int off, int end, uint32_t *jumbolen, REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } - if (!pf_pull_hdr(m, off, &jumbo, sizeof(jumbo), NULL, + if (!pf_pull_hdr(pd->m, off, &jumbo, sizeof(jumbo), NULL, reason, AF_INET6)) { DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short jumbo")); return (PF_DROP); } - memcpy(jumbolen, jumbo.ip6oj_jumbo_len, - sizeof(*jumbolen)); - *jumbolen = ntohl(*jumbolen); - if (*jumbolen < IPV6_MAXPACKET) { + memcpy(&pd->jumbolen, jumbo.ip6oj_jumbo_len, + sizeof(pd->jumbolen)); + pd->jumbolen = ntohl(pd->jumbolen); + if (pd->jumbolen < IPV6_MAXPACKET) { DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short jumbolen")); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); @@ -9718,43 +9715,41 @@ pf_walk_option6(struct mbuf *m, int off, int end, uint32_t *jumbolen, } int -pf_walk_header6(struct mbuf *m, struct ip6_hdr *h, int *off, int *extoff, - int *fragoff, uint8_t *nxt, uint32_t *jumbolen, u_short *reason) +pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) { struct ip6_frag frag; struct ip6_ext ext; struct ip6_rthdr rthdr; int rthdr_cnt = 0; - *off += sizeof(struct ip6_hdr); - *extoff = *fragoff = 0; - *nxt = h->ip6_nxt; - *jumbolen = 0; + pd->off += sizeof(struct ip6_hdr); + pd->fragoff = pd->extoff = pd->jumbolen = 0; + pd->proto = h->ip6_nxt; for (;;) { - switch (*nxt) { + switch (pd->proto) { case IPPROTO_FRAGMENT: - if (*fragoff != 0) { + if (pd->fragoff != 0) { DPFPRINTF(PF_DEBUG_MISC, ("IPv6 multiple fragment")); REASON_SET(reason, PFRES_FRAG); return (PF_DROP); } /* jumbo payload packets cannot be fragmented */ - if (*jumbolen != 0) { + if (pd->jumbolen != 0) { DPFPRINTF(PF_DEBUG_MISC, ("IPv6 fragmented jumbo")); REASON_SET(reason, PFRES_FRAG); return (PF_DROP); } - if (!pf_pull_hdr(m, *off, &frag, sizeof(frag), NULL, - reason, AF_INET6)) { + if (!pf_pull_hdr(pd->m, pd->off, &frag, sizeof(frag), + NULL, reason, AF_INET6)) { DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short fragment")); return (PF_DROP); } - *fragoff = *off; + pd->fragoff = pd->off; /* stop walking over non initial fragments */ if ((frag.ip6f_offlg & IP6F_OFF_MASK) != 0) return (PF_PASS); - *off += sizeof(frag); - *nxt = frag.ip6f_nxt; + pd->off += sizeof(frag); + pd->proto = frag.ip6f_nxt; break; case IPPROTO_ROUTING: if (rthdr_cnt++) { @@ -9762,12 +9757,12 @@ pf_walk_header6(struct mbuf *m, struct ip6_hdr *h, int *off, int *extoff, REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } - if (!pf_pull_hdr(m, *off, &rthdr, sizeof(rthdr), NULL, - reason, AF_INET6)) { + if (!pf_pull_hdr(pd->m, pd->off, &rthdr, sizeof(rthdr), + NULL, reason, AF_INET6)) { /* fragments may be short */ - if (*fragoff != 0) { - *off = *fragoff; - *nxt = IPPROTO_FRAGMENT; + if (pd->fragoff != 0) { + pd->off = pd->fragoff; + pd->proto = IPPROTO_FRAGMENT; return (PF_PASS); } DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short rthdr")); @@ -9782,50 +9777,51 @@ pf_walk_header6(struct mbuf *m, struct ip6_hdr *h, int *off, int *extoff, case IPPROTO_AH: case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: - if (!pf_pull_hdr(m, *off, &ext, sizeof(ext), NULL, - reason, AF_INET6)) { + if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext), + NULL, reason, AF_INET6)) { /* fragments may be short */ - if (*fragoff != 0) { - *off = *fragoff; - *nxt = IPPROTO_FRAGMENT; + if (pd->fragoff != 0) { + pd->off = pd->fragoff; + pd->proto = IPPROTO_FRAGMENT; return (PF_PASS); } DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short exthdr")); return (PF_DROP); } /* reassembly needs the ext header before the frag */ - if (*fragoff == 0) - *extoff = *off; - if (*nxt == IPPROTO_HOPOPTS && *fragoff == 0) { - if (pf_walk_option6(m, *off + sizeof(ext), - *off + (ext.ip6e_len + 1) * 8, jumbolen, - reason) != PF_PASS) + if (pd->fragoff == 0) + pd->extoff = pd->off; + if (pd->proto == IPPROTO_HOPOPTS && pd->fragoff == 0) { + if (pf_walk_option6(pd, h, + pd->off + sizeof(ext), + pd->off + (ext.ip6e_len + 1) * 8, reason) + != PF_PASS) return (PF_DROP); - if (ntohs(h->ip6_plen) == 0 && *jumbolen != 0) { + if (ntohs(h->ip6_plen) == 0 && pd->jumbolen != 0) { DPFPRINTF(PF_DEBUG_MISC, ("IPv6 missing jumbo")); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } } - if (*nxt == IPPROTO_AH) - *off += (ext.ip6e_len + 2) * 4; + if (pd->proto == IPPROTO_AH) + pd->off += (ext.ip6e_len + 2) * 4; else - *off += (ext.ip6e_len + 1) * 8; - *nxt = ext.ip6e_nxt; + pd->off += (ext.ip6e_len + 1) * 8; + pd->proto = ext.ip6e_nxt; break; case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_SCTP: case IPPROTO_ICMPV6: /* fragments may be short, ignore inner header then */ - if (*fragoff != 0 && ntohs(h->ip6_plen) < *off + - (*nxt == IPPROTO_TCP ? sizeof(struct tcphdr) : - *nxt == IPPROTO_UDP ? sizeof(struct udphdr) : - *nxt == IPPROTO_SCTP ? sizeof(struct sctphdr) : + if (pd->fragoff != 0 && ntohs(h->ip6_plen) < pd->off + + (pd->proto == IPPROTO_TCP ? sizeof(struct tcphdr) : + pd->proto == IPPROTO_UDP ? sizeof(struct udphdr) : + pd->proto == IPPROTO_SCTP ? sizeof(struct sctphdr) : sizeof(struct icmp6_hdr))) { - *off = *fragoff; - *nxt = IPPROTO_FRAGMENT; + pd->off = pd->fragoff; + pd->proto = IPPROTO_FRAGMENT; } /* FALLTHROUGH */ default: @@ -9913,9 +9909,6 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, #ifdef INET6 case AF_INET6: { struct ip6_hdr *h; - int fragoff; - uint32_t jumbolen; - uint8_t nxt; if (__predict_false((*m0)->m_len < sizeof(struct ip6_hdr)) && (pd->m = *m0 = m_pullup(*m0, sizeof(struct ip6_hdr))) == NULL) { @@ -9929,8 +9922,7 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, h = mtod(pd->m, struct ip6_hdr *); pd->off = 0; - if (pf_walk_header6(pd->m, h, &pd->off, &pd->extoff, &fragoff, &nxt, - &jumbolen, reason) != PF_PASS) { + if (pf_walk_header6(pd, h, reason) != PF_PASS) { *action = PF_DROP; return (-1); } @@ -9945,7 +9937,7 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, pd->virtual_proto = pd->proto = h->ip6_nxt; pd->act.rtableid = -1; - if (fragoff != 0) + if (pd->fragoff != 0) pd->virtual_proto = PF_VPROTO_FRAGMENT; /* @@ -9958,7 +9950,7 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, } /* We do IP header normalization and packet reassembly here */ - if (pf_normalize_ip6(m0, fragoff, reason, pd) != + if (pf_normalize_ip6(m0, pd->fragoff, reason, pd) != PF_PASS) { *action = PF_DROP; return (-1); @@ -9975,20 +9967,23 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, pd->src = (struct pf_addr *)&h->ip6_src; pd->dst = (struct pf_addr *)&h->ip6_dst; - /* - * Reassembly may have changed the next protocol from fragment - * to something else, so update. - */ - pd->virtual_proto = pd->proto = h->ip6_nxt; pd->off = 0; - if (pf_walk_header6(pd->m, h, &pd->off, &pd->extoff, &fragoff, &nxt, - &jumbolen, reason) != PF_PASS) { + if (pf_walk_header6(pd, h, reason) != PF_PASS) { *action = PF_DROP; return (-1); } - if (fragoff != 0) + if (m_tag_find(pd->m, PACKET_TAG_PF_REASSEMBLED, NULL) != NULL) { + /* + * Reassembly may have changed the next protocol from + * fragment to something else, so update. + */ + pd->virtual_proto = pd->proto; + MPASS(pd->fragoff == 0); + } + + if (pd->fragoff != 0) pd->virtual_proto = PF_VPROTO_FRAGMENT; break;