Page MenuHomeFreeBSD

D46586.diff
No OneTemporary

D46586.diff

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1610,6 +1610,7 @@
struct pf_rule_actions act;
u_int32_t p_len; /* total length of payload */
+ u_int32_t rh_cnt; /* Route header count */
u_int16_t *ip_sum;
u_int16_t *proto_sum;
@@ -2350,8 +2351,15 @@
extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
sa_family_t);
void pf_free_rule(struct pf_krule *);
+int pf_setup_pdesc(sa_family_t, int,
+ struct pf_pdesc *, struct mbuf *,
+ u_short *, u_short *, struct pfi_kkif *,
+ struct pf_krule **, struct pf_krule **,
+ struct pf_kruleset **, int *, int *,
+ struct pf_rule_actions *);
int pf_test_eth(int, int, struct ifnet *, struct mbuf **, struct inpcb *);
+int pf_scan_sctp(struct mbuf *, int, struct pf_pdesc *, struct pfi_kkif *);
#ifdef INET
int pf_test(int, int, struct ifnet *, struct mbuf **, struct inpcb *,
struct pf_rule_actions *);
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -324,7 +324,7 @@
static int pf_test_rule(struct pf_krule **, struct pf_kstate **,
struct pfi_kkif *, struct mbuf *, int,
struct pf_pdesc *, struct pf_krule **,
- struct pf_kruleset **, struct inpcb *);
+ struct pf_kruleset **, struct inpcb *, int);
static int pf_create_state(struct pf_krule *, struct pf_krule *,
struct pf_krule *, struct pf_pdesc *,
struct pf_ksrc_node *, struct pf_state_key *,
@@ -4865,7 +4865,7 @@
static int
pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, struct pfi_kkif *kif,
struct mbuf *m, int off, struct pf_pdesc *pd, struct pf_krule **am,
- struct pf_kruleset **rsm, struct inpcb *inp)
+ struct pf_kruleset **rsm, struct inpcb *inp, int hdrlen)
{
struct pf_krule *nr = NULL;
struct pf_addr * const saddr = pd->src;
@@ -4879,7 +4879,7 @@
struct tcphdr *th = &pd->hdr.tcp;
struct pf_state_key *sk = NULL, *nk = NULL;
u_short reason, transerror;
- int rewrite = 0, hdrlen = 0;
+ int rewrite = 0;
int tag = -1;
int asd = 0;
int match = 0;
@@ -4905,23 +4905,19 @@
case IPPROTO_TCP:
sport = th->th_sport;
dport = th->th_dport;
- hdrlen = sizeof(*th);
break;
case IPPROTO_UDP:
sport = pd->hdr.udp.uh_sport;
dport = pd->hdr.udp.uh_dport;
- hdrlen = sizeof(pd->hdr.udp);
break;
case IPPROTO_SCTP:
sport = pd->hdr.sctp.src_port;
dport = pd->hdr.sctp.dest_port;
- hdrlen = sizeof(pd->hdr.sctp);
break;
#ifdef INET
case IPPROTO_ICMP:
if (pd->af != AF_INET)
break;
- hdrlen = sizeof(pd->hdr.icmp);
icmptype = pd->hdr.icmp.icmp_type;
icmpcode = pd->hdr.icmp.icmp_code;
state_icmp = pf_icmp_mapping(pd, icmptype,
@@ -4939,7 +4935,6 @@
case IPPROTO_ICMPV6:
if (af != AF_INET6)
break;
- hdrlen = sizeof(pd->hdr.icmp6);
icmptype = pd->hdr.icmp6.icmp6_type;
icmpcode = pd->hdr.icmp6.icmp6_code;
state_icmp = pf_icmp_mapping(pd, icmptype,
@@ -4955,7 +4950,7 @@
break;
#endif /* INET6 */
default:
- sport = dport = hdrlen = 0;
+ sport = dport = 0;
break;
}
@@ -6662,7 +6657,8 @@
* That's why we pass V_pfi_all rather than kif.
*/
ret = pf_test_rule(&r, &sm, V_pfi_all,
- j->m, off, &j->pd, &ra, &rs, NULL);
+ j->m, off, &j->pd, &ra, &rs, NULL,
+ sizeof(j->pd.hdr.sctp));
PF_RULES_RUNLOCK();
SDT_PROBE4(pf, sctp, multihome, test, kif, r, j->m, ret);
if (ret != PF_DROP && sm != NULL) {
@@ -8540,6 +8536,290 @@
return (0);
}
+int
+pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf *m,
+ u_short *action, u_short *reason, struct pfi_kkif *kif, struct pf_krule **a,
+ struct pf_krule **r, struct pf_kruleset **ruleset, int *off, int *hdrlen,
+ struct pf_rule_actions *default_actions)
+{
+
+ TAILQ_INIT(&pd->sctp_multihome_jobs);
+ if (default_actions != NULL)
+ memcpy(&pd->act, default_actions, sizeof(pd->act));
+ pd->pf_mtag = pf_find_mtag(m);
+
+ if (pd->pf_mtag && pd->pf_mtag->dnpipe) {
+ pd->act.dnpipe = pd->pf_mtag->dnpipe;
+ pd->act.flags = pd->pf_mtag->dnflags;
+ }
+
+ pd->af = af;
+
+ switch (af) {
+#ifdef INET
+ case AF_INET: {
+ struct ip *h;
+
+ h = mtod(m, struct ip *);
+ *off = h->ip_hl << 2;
+ if (*off < (int)sizeof(*h)) {
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+ pd->src = (struct pf_addr *)&h->ip_src;
+ pd->dst = (struct pf_addr *)&h->ip_dst;
+ pd->sport = pd->dport = NULL;
+ pd->ip_sum = &h->ip_sum;
+ pd->proto_sum = NULL;
+ pd->proto = h->ip_p;
+ pd->dir = dir;
+ pd->sidx = (dir == PF_IN) ? 0 : 1;
+ pd->didx = (dir == PF_IN) ? 1 : 0;
+ pd->tos = h->ip_tos;
+ pd->tot_len = ntohs(h->ip_len);
+ pd->act.rtableid = -1;
+
+ /* fragments not reassembled handled later */
+ if (h->ip_off & htons(IP_MF | IP_OFFMASK))
+ return (0);
+
+ switch (h->ip_p) {
+ case IPPROTO_TCP: {
+ struct tcphdr *th = &pd->hdr.tcp;
+
+ if (!pf_pull_hdr(m, *off, th, sizeof(*th), action,
+ reason, AF_INET))
+ return (-1);
+ *hdrlen = sizeof(*th);
+ pd->p_len = pd->tot_len - *off - (th->th_off << 2);
+ pd->sport = &th->th_sport;
+ pd->dport = &th->th_dport;
+ break;
+ }
+ case IPPROTO_UDP: {
+ struct udphdr *uh = &pd->hdr.udp;
+
+ if (!pf_pull_hdr(m, *off, uh, sizeof(*uh), action,
+ reason, AF_INET))
+ return (-1);
+ *hdrlen = sizeof(*uh);
+ if (uh->uh_dport == 0 ||
+ ntohs(uh->uh_ulen) > m->m_pkthdr.len - *off ||
+ ntohs(uh->uh_ulen) < sizeof(struct udphdr)) {
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+ pd->sport = &uh->uh_sport;
+ pd->dport = &uh->uh_dport;
+ break;
+ }
+ case IPPROTO_SCTP: {
+ if (!pf_pull_hdr(m, *off, &pd->hdr.sctp, sizeof(pd->hdr.sctp),
+ action, reason, AF_INET)) {
+ return (-1);
+ }
+ *hdrlen = sizeof(pd->hdr.sctp);
+ pd->p_len = pd->tot_len - *off;
+
+ pd->sport = &pd->hdr.sctp.src_port;
+ pd->dport = &pd->hdr.sctp.dest_port;
+ if (pd->hdr.sctp.src_port == 0 || pd->hdr.sctp.dest_port == 0) {
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+ if (pf_scan_sctp(m, *off, pd, kif) != PF_PASS) {
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+ break;
+ }
+ case IPPROTO_ICMP: {
+ if (!pf_pull_hdr(m, *off, &pd->hdr.icmp, ICMP_MINLEN,
+ action, reason, AF_INET))
+ return (-1);
+ *hdrlen = ICMP_MINLEN;
+ break;
+ }
+ }
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct ip6_hdr *h;
+ int terminal = 0;
+
+ h = mtod(m, struct ip6_hdr *);
+ pd->src = (struct pf_addr *)&h->ip6_src;
+ pd->dst = (struct pf_addr *)&h->ip6_dst;
+ pd->sport = pd->dport = NULL;
+ pd->ip_sum = NULL;
+ pd->proto_sum = NULL;
+ pd->dir = dir;
+ pd->sidx = (dir == PF_IN) ? 0 : 1;
+ pd->didx = (dir == PF_IN) ? 1 : 0;
+ pd->tos = IPV6_DSCP(h);
+ pd->tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
+ *off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr);
+ pd->proto = h->ip6_nxt;
+ pd->act.rtableid = -1;
+
+ do {
+ switch (pd->proto) {
+ case IPPROTO_FRAGMENT:
+ if (kif == NULL || r == NULL) /* pflog */
+ *action = PF_DROP;
+ else
+ *action = pf_test_fragment(r, kif,
+ m, h, pd, a, ruleset);
+ if (*action == PF_DROP)
+ REASON_SET(reason, PFRES_FRAG);
+ return (-1);
+ case IPPROTO_ROUTING: {
+ struct ip6_rthdr rthdr;
+
+ if (pd->rh_cnt++) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 more than one rthdr"));
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (-1);
+ }
+ if (!pf_pull_hdr(m, *off, &rthdr, sizeof(rthdr),
+ NULL, reason, pd->af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 short rthdr"));
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+ if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 rthdr0"));
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (-1);
+ }
+ /* FALLTHROUGH */
+ }
+ case IPPROTO_AH:
+ case IPPROTO_HOPOPTS:
+ case IPPROTO_DSTOPTS: {
+ /* get next header and header length */
+ struct ip6_ext opt6;
+
+ if (!pf_pull_hdr(m, *off, &opt6, sizeof(opt6),
+ NULL, reason, pd->af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 short opt"));
+ *action = PF_DROP;
+ return (-1);
+ }
+ if (pd->proto == IPPROTO_AH)
+ *off += (opt6.ip6e_len + 2) * 4;
+ else
+ *off += (opt6.ip6e_len + 1) * 8;
+ pd->proto = opt6.ip6e_nxt;
+ /* goto the next header */
+ break;
+ }
+ default:
+ terminal++;
+ break;
+ }
+ } while (!terminal);
+
+ switch (pd->proto) {
+ case IPPROTO_TCP: {
+ struct tcphdr *th = &pd->hdr.tcp;
+
+ if (!pf_pull_hdr(m, *off, th, sizeof(*th), action,
+ reason, AF_INET6))
+ return (-1);
+ *hdrlen = sizeof(*th);
+ pd->p_len = pd->tot_len - *off - (th->th_off << 2);
+ pd->sport = &th->th_sport;
+ pd->dport = &th->th_dport;
+ break;
+ }
+ case IPPROTO_UDP: {
+ struct udphdr *uh = &pd->hdr.udp;
+
+ if (!pf_pull_hdr(m, *off, uh, sizeof(*uh), action,
+ reason, AF_INET6))
+ return (-1);
+ *hdrlen = sizeof(*uh);
+ if (uh->uh_dport == 0 ||
+ ntohs(uh->uh_ulen) > m->m_pkthdr.len - *off ||
+ ntohs(uh->uh_ulen) < sizeof(struct udphdr)) {
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+ pd->sport = &uh->uh_sport;
+ pd->dport = &uh->uh_dport;
+ break;
+ }
+ case IPPROTO_SCTP: {
+ if (!pf_pull_hdr(m, *off, &pd->hdr.sctp, sizeof(pd->hdr.sctp),
+ action, reason, AF_INET6)) {
+ return (-1);
+ }
+ *hdrlen = sizeof(pd->hdr.sctp);
+ pd->p_len = pd->tot_len - *off;
+
+ pd->sport = &pd->hdr.sctp.src_port;
+ pd->dport = &pd->hdr.sctp.dest_port;
+ if (pd->hdr.sctp.src_port == 0 || pd->hdr.sctp.dest_port == 0) {
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+ if (pf_scan_sctp(m, *off, pd, kif) != PF_PASS) {
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+ break;
+ }
+ case IPPROTO_ICMPV6: {
+ size_t icmp_hlen = sizeof(struct icmp6_hdr);
+
+ if (!pf_pull_hdr(m, *off, &pd->hdr.icmp6, icmp_hlen,
+ action, reason, AF_INET6))
+ return (-1);
+ /* ICMP headers we look further into to match state */
+ switch (pd->hdr.icmp6.icmp6_type) {
+ case MLD_LISTENER_QUERY:
+ case MLD_LISTENER_REPORT:
+ icmp_hlen = sizeof(struct mld_hdr);
+ break;
+ case ND_NEIGHBOR_SOLICIT:
+ case ND_NEIGHBOR_ADVERT:
+ icmp_hlen = sizeof(struct nd_neighbor_solicit);
+ break;
+ }
+ if (icmp_hlen > sizeof(struct icmp6_hdr) &&
+ !pf_pull_hdr(m, *off, &pd->hdr.icmp6, icmp_hlen,
+ action, reason, AF_INET6))
+ return (-1);
+ *hdrlen = icmp_hlen;
+ break;
+ }
+ }
+ break;
+ }
+#endif
+ default:
+ panic("pf_setup_pdesc called with illegal af %u", af);
+ }
+ return (0);
+}
+
#ifdef INET
int
pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0,
@@ -8554,7 +8834,7 @@
struct pf_kstate *s = NULL;
struct pf_kruleset *ruleset = NULL;
struct pf_pdesc pd;
- int off, dirndx, use_2nd_queue = 0;
+ int off, hdrlen, dirndx, use_2nd_queue = 0;
uint16_t tag;
uint8_t rt;
@@ -8591,11 +8871,31 @@
return (PF_DROP);
}
+ 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);
+ }
+
memset(&pd, 0, sizeof(pd));
- TAILQ_INIT(&pd.sctp_multihome_jobs);
- if (default_actions != NULL)
- memcpy(&pd.act, default_actions, sizeof(pd.act));
- pd.pf_mtag = pf_find_mtag(m);
+ pd.dir = dir;
+
+ 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 *);
+
+ if (pf_setup_pdesc(AF_INET, dir, &pd, m, &action, &reason, kif, &a, &r,
+ &ruleset, &off, &hdrlen, 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;
@@ -8614,11 +8914,6 @@
return (PF_PASS);
}
- if (pd.pf_mtag && pd.pf_mtag->dnpipe) {
- pd.act.dnpipe = pd.pf_mtag->dnpipe;
- pd.act.flags = pd.pf_mtag->dnflags;
- }
-
if (ip_dn_io_ptr != NULL && pd.pf_mtag != NULL &&
pd.pf_mtag->flags & PF_MTAG_FLAG_DUMMYNET) {
/* Dummynet re-injects packets after they've
@@ -8633,24 +8928,6 @@
return (PF_PASS);
}
- pd.sport = pd.dport = NULL;
- pd.proto_sum = NULL;
- pd.dir = dir;
- pd.sidx = (dir == PF_IN) ? 0 : 1;
- pd.didx = (dir == PF_IN) ? 1 : 0;
- pd.af = AF_INET;
- pd.act.rtableid = -1;
-
- 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);
- }
- h = mtod(m, struct ip *);
- off = h->ip_hl << 2;
-
if (__predict_false(ip_divert_ptr != NULL) &&
((mtag = m_tag_locate(m, MTAG_PF_DIVERT, 0, NULL)) != NULL)) {
struct pf_divert_mtag *dt = (struct pf_divert_mtag *)(mtag+1);
@@ -8672,28 +8949,7 @@
mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL);
if (mtag != NULL)
m_tag_delete(m, mtag);
- } else 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 *);
-
- off = h->ip_hl << 2;
- if (off < (int)sizeof(struct ip)) {
- action = PF_DROP;
- REASON_SET(&reason, PFRES_SHORT);
- pd.act.log = PF_LOG_FORCE;
- goto done;
- }
-
- pd.src = (struct pf_addr *)&h->ip_src;
- pd.dst = (struct pf_addr *)&h->ip_dst;
- pd.ip_sum = &h->ip_sum;
- pd.proto = h->ip_p;
- pd.tos = h->ip_tos & ~IPTOS_ECN_MASK;
- pd.tot_len = ntohs(h->ip_len);
/* handle fragments that didn't get reassembled by normalization */
if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
@@ -8703,16 +8959,6 @@
switch (h->ip_p) {
case IPPROTO_TCP: {
- if (!pf_pull_hdr(m, off, &pd.hdr.tcp, sizeof(pd.hdr.tcp),
- &action, &reason, AF_INET)) {
- if (action != PF_PASS)
- pd.act.log = PF_LOG_FORCE;
- goto done;
- }
- pd.p_len = pd.tot_len - off - (pd.hdr.tcp.th_off << 2);
-
- pd.sport = &pd.hdr.tcp.th_sport;
- pd.dport = &pd.hdr.tcp.th_dport;
/* Respond to SYN with a syncookie. */
if ((pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) == TH_SYN &&
@@ -8768,28 +9014,13 @@
break;
} else {
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp);
+ &a, &ruleset, inp, hdrlen);
}
}
break;
}
case IPPROTO_UDP: {
- if (!pf_pull_hdr(m, off, &pd.hdr.udp, sizeof(pd.hdr.udp),
- &action, &reason, AF_INET)) {
- if (action != PF_PASS)
- pd.act.log = PF_LOG_FORCE;
- goto done;
- }
- pd.sport = &pd.hdr.udp.uh_sport;
- pd.dport = &pd.hdr.udp.uh_dport;
- if (pd.hdr.udp.uh_dport == 0 ||
- ntohs(pd.hdr.udp.uh_ulen) > m->m_pkthdr.len - off ||
- ntohs(pd.hdr.udp.uh_ulen) < sizeof(struct udphdr)) {
- action = PF_DROP;
- REASON_SET(&reason, PFRES_SHORT);
- goto done;
- }
action = pf_test_state_udp(&s, kif, m, off, h, &pd);
if (action == PF_PASS) {
if (V_pfsync_update_state_ptr != NULL)
@@ -8798,26 +9029,11 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp);
+ &a, &ruleset, inp, hdrlen);
break;
}
case IPPROTO_SCTP: {
- if (!pf_pull_hdr(m, off, &pd.hdr.sctp, sizeof(pd.hdr.sctp),
- &action, &reason, AF_INET)) {
- if (action != PF_PASS)
- pd.act.log |= PF_LOG_FORCE;
- goto done;
- }
- pd.p_len = pd.tot_len - off;
-
- pd.sport = &pd.hdr.sctp.src_port;
- pd.dport = &pd.hdr.sctp.dest_port;
- if (pd.hdr.sctp.src_port == 0 || pd.hdr.sctp.dest_port == 0) {
- action = PF_DROP;
- REASON_SET(&reason, PFRES_SHORT);
- goto done;
- }
action = pf_normalize_sctp(dir, kif, m, 0, off, h, &pd);
if (action == PF_DROP)
goto done;
@@ -8830,18 +9046,12 @@
a = s->anchor.ptr;
} else if (s == NULL) {
action = pf_test_rule(&r, &s, kif, m, off,
- &pd, &a, &ruleset, inp);
+ &pd, &a, &ruleset, inp, hdrlen);
}
break;
}
case IPPROTO_ICMP: {
- if (!pf_pull_hdr(m, off, &pd.hdr.icmp, ICMP_MINLEN,
- &action, &reason, AF_INET)) {
- if (action != PF_PASS)
- pd.act.log = PF_LOG_FORCE;
- goto done;
- }
action = pf_test_state_icmp(&s, kif, m, off, h, &pd, &reason);
if (action == PF_PASS) {
if (V_pfsync_update_state_ptr != NULL)
@@ -8850,7 +9060,7 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp);
+ &a, &ruleset, inp, hdrlen);
break;
}
@@ -8870,7 +9080,7 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp);
+ &a, &ruleset, inp, hdrlen);
break;
}
@@ -9141,7 +9351,7 @@
struct pf_kstate *s = NULL;
struct pf_kruleset *ruleset = NULL;
struct pf_pdesc pd;
- int off, terminal = 0, dirndx, rh_cnt = 0, use_2nd_queue = 0;
+ int off, hdrlen, dirndx, use_2nd_queue = 0;
uint16_t tag;
uint8_t rt;
@@ -9189,11 +9399,33 @@
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);
+ }
+
memset(&pd, 0, sizeof(pd));
- TAILQ_INIT(&pd.sctp_multihome_jobs);
- if (default_actions != NULL)
- memcpy(&pd.act, default_actions, sizeof(pd.act));
- pd.pf_mtag = pf_find_mtag(m);
+ pd.dir = dir;
+
+ /* 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 */
+ h = mtod(m, struct ip6_hdr *);
+ off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr);
+
+ if (pf_setup_pdesc(AF_INET6, dir, &pd, m, &action, &reason, kif, &a, &r,
+ &ruleset, &off, &hdrlen, 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;
@@ -9213,11 +9445,6 @@
return (PF_PASS);
}
- if (pd.pf_mtag && pd.pf_mtag->dnpipe) {
- pd.act.dnpipe = pd.pf_mtag->dnpipe;
- pd.act.flags = pd.pf_mtag->dnflags;
- }
-
if (ip_dn_io_ptr != NULL && pd.pf_mtag != NULL &&
pd.pf_mtag->flags & PF_MTAG_FLAG_DUMMYNET) {
pf_dummynet_flag_remove(m, pd.pf_mtag);
@@ -9228,35 +9455,6 @@
return (PF_PASS);
}
- pd.sport = pd.dport = NULL;
- pd.ip_sum = NULL;
- pd.proto_sum = NULL;
- pd.dir = dir;
- pd.sidx = (dir == PF_IN) ? 0 : 1;
- pd.didx = (dir == PF_IN) ? 1 : 0;
- pd.af = AF_INET6;
- pd.act.rtableid = -1;
-
- 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);
- }
- h = mtod(m, struct ip6_hdr *);
- off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr);
-
- /* 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 */
- h = mtod(m, struct ip6_hdr *);
- off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr);
-
/*
* we do not support jumbogram. if we keep going, zero ip6_plen
* will do something bad, so drop the packet for now.
@@ -9267,94 +9465,12 @@
goto done;
}
- pd.src = (struct pf_addr *)&h->ip6_src;
- pd.dst = (struct pf_addr *)&h->ip6_dst;
- pd.tos = IPV6_DSCP(h);
- pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
-
- pd.proto = h->ip6_nxt;
- do {
- switch (pd.proto) {
- case IPPROTO_FRAGMENT:
- action = pf_test_fragment(&r, kif, m, h, &pd, &a,
- &ruleset);
- if (action == PF_DROP)
- REASON_SET(&reason, PFRES_FRAG);
- goto done;
- case IPPROTO_ROUTING: {
- struct ip6_rthdr rthdr;
-
- if (rh_cnt++) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("pf: IPv6 more than one rthdr\n"));
- action = PF_DROP;
- REASON_SET(&reason, PFRES_IPOPTIONS);
- pd.act.log = PF_LOG_FORCE;
- goto done;
- }
- if (!pf_pull_hdr(m, off, &rthdr, sizeof(rthdr), NULL,
- &reason, pd.af)) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("pf: IPv6 short rthdr\n"));
- action = PF_DROP;
- REASON_SET(&reason, PFRES_SHORT);
- pd.act.log = PF_LOG_FORCE;
- goto done;
- }
- if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("pf: IPv6 rthdr0\n"));
- action = PF_DROP;
- REASON_SET(&reason, PFRES_IPOPTIONS);
- pd.act.log = PF_LOG_FORCE;
- goto done;
- }
- /* FALLTHROUGH */
- }
- case IPPROTO_AH:
- case IPPROTO_HOPOPTS:
- case IPPROTO_DSTOPTS: {
- /* get next header and header length */
- struct ip6_ext opt6;
-
- if (!pf_pull_hdr(m, off, &opt6, sizeof(opt6),
- NULL, &reason, pd.af)) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("pf: IPv6 short opt\n"));
- action = PF_DROP;
- pd.act.log = PF_LOG_FORCE;
- goto done;
- }
- if (pd.proto == IPPROTO_AH)
- off += (opt6.ip6e_len + 2) * 4;
- else
- off += (opt6.ip6e_len + 1) * 8;
- pd.proto = opt6.ip6e_nxt;
- /* goto the next header */
- break;
- }
- default:
- terminal++;
- break;
- }
- } while (!terminal);
-
/* if there's no routing header, use unmodified mbuf for checksumming */
if (!n)
n = m;
switch (pd.proto) {
case IPPROTO_TCP: {
- if (!pf_pull_hdr(m, off, &pd.hdr.tcp, sizeof(pd.hdr.tcp),
- &action, &reason, AF_INET6)) {
- if (action != PF_PASS)
- pd.act.log |= PF_LOG_FORCE;
- goto done;
- }
- pd.p_len = pd.tot_len - off - (pd.hdr.tcp.th_off << 2);
- pd.sport = &pd.hdr.tcp.th_sport;
- pd.dport = &pd.hdr.tcp.th_dport;
-
/* Respond to SYN with a syncookie. */
if ((pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) == TH_SYN &&
pd.dir == PF_IN && pf_synflood_check(&pd)) {
@@ -9408,28 +9524,13 @@
break;
} else {
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp);
+ &a, &ruleset, inp, hdrlen);
}
}
break;
}
case IPPROTO_UDP: {
- if (!pf_pull_hdr(m, off, &pd.hdr.udp, sizeof(pd.hdr.udp),
- &action, &reason, AF_INET6)) {
- if (action != PF_PASS)
- pd.act.log |= PF_LOG_FORCE;
- goto done;
- }
- pd.sport = &pd.hdr.udp.uh_sport;
- pd.dport = &pd.hdr.udp.uh_dport;
- if (pd.hdr.udp.uh_dport == 0 ||
- ntohs(pd.hdr.udp.uh_ulen) > m->m_pkthdr.len - off ||
- ntohs(pd.hdr.udp.uh_ulen) < sizeof(struct udphdr)) {
- action = PF_DROP;
- REASON_SET(&reason, PFRES_SHORT);
- goto done;
- }
action = pf_test_state_udp(&s, kif, m, off, h, &pd);
if (action == PF_PASS) {
if (V_pfsync_update_state_ptr != NULL)
@@ -9438,24 +9539,11 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp);
+ &a, &ruleset, inp, hdrlen);
break;
}
case IPPROTO_SCTP: {
- if (!pf_pull_hdr(m, off, &pd.hdr.sctp, sizeof(pd.hdr.sctp),
- &action, &reason, AF_INET6)) {
- if (action != PF_PASS)
- pd.act.log |= PF_LOG_FORCE;
- goto done;
- }
- pd.sport = &pd.hdr.sctp.src_port;
- pd.dport = &pd.hdr.sctp.dest_port;
- if (pd.hdr.sctp.src_port == 0 || pd.hdr.sctp.dest_port == 0) {
- action = PF_DROP;
- REASON_SET(&reason, PFRES_SHORT);
- goto done;
- }
action = pf_normalize_sctp(dir, kif, m, 0, off, h, &pd);
if (action == PF_DROP)
goto done;
@@ -9468,7 +9556,7 @@
a = s->anchor.ptr;
} else if (s == NULL) {
action = pf_test_rule(&r, &s, kif, m, off,
- &pd, &a, &ruleset, inp);
+ &pd, &a, &ruleset, inp, hdrlen);
}
break;
}
@@ -9481,12 +9569,6 @@
}
case IPPROTO_ICMPV6: {
- if (!pf_pull_hdr(m, off, &pd.hdr.icmp6, sizeof(pd.hdr.icmp6),
- &action, &reason, AF_INET6)) {
- if (action != PF_PASS)
- pd.act.log |= PF_LOG_FORCE;
- goto done;
- }
action = pf_test_state_icmp(&s, kif, m, off, h, &pd, &reason);
if (action == PF_PASS) {
if (V_pfsync_update_state_ptr != NULL)
@@ -9495,7 +9577,7 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp);
+ &a, &ruleset, inp, hdrlen);
break;
}
@@ -9508,7 +9590,7 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp);
+ &a, &ruleset, inp, hdrlen);
break;
}
@@ -9520,7 +9602,7 @@
}
/* handle dangerous IPv6 extension headers. */
- if (action == PF_PASS && rh_cnt &&
+ if (action == PF_PASS && pd.rh_cnt &&
!((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_IPOPTIONS);
diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -2066,8 +2066,8 @@
return (0);
}
-static int
-pf_scan_sctp(struct mbuf *m, int ipoff, int off, struct pf_pdesc *pd,
+int
+pf_scan_sctp(struct mbuf *m, int off, struct pf_pdesc *pd,
struct pfi_kkif *kif)
{
struct sctp_chunkhdr ch = { };
@@ -2203,11 +2203,6 @@
PF_RULES_RASSERT();
- /* Unconditionally scan the SCTP packet, because we need to look for
- * things like shutdown and asconf chunks. */
- if (pf_scan_sctp(m, ipoff, off, pd, kif) != PF_PASS)
- goto sctp_drop;
-
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
/* Check if there any scrub rules. Lack of scrub rules means enforced
* packet normalization operation just like in OpenBSD. */

File Metadata

Mime Type
text/plain
Expires
Fri, May 2, 4:51 AM (17 h, 30 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17898683
Default Alt Text
D46586.diff (25 KB)

Event Timeline