diff options
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r-- | sys/net/pf.c | 80 |
1 files changed, 44 insertions, 36 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c index 594f73ceea5..dd409468abd 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.743 2011/05/13 14:31:16 oga Exp $ */ +/* $OpenBSD: pf.c,v 1.744 2011/05/22 13:21:24 claudio Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -175,7 +175,7 @@ void pf_rule_to_actions(struct pf_rule *, int pf_test_rule(struct pf_rule **, struct pf_state **, int, struct pfi_kif *, struct mbuf *, int, struct pf_pdesc *, struct pf_rule **, - struct pf_ruleset **, struct ifqueue *, int); + struct pf_ruleset **, int); static __inline int pf_create_state(struct pf_rule *, struct pf_rule *, struct pf_pdesc *, struct pf_state_key **, struct pf_state_key **, struct mbuf *, int, @@ -2716,7 +2716,7 @@ int pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, struct pfi_kif *kif, struct mbuf *m, int off, struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm, - struct ifqueue *ifq, int hdrlen) + int hdrlen) { struct pf_rule *lastr = NULL; sa_family_t af = pd->af; @@ -2728,6 +2728,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, struct tcphdr *th = pd->hdr.tcp; struct pf_state_key *skw = NULL, *sks = NULL; struct pf_rule_actions act; + struct ifqueue *ifq = &ipintrq; u_short reason; int rewrite = 0; int tag = -1; @@ -2745,6 +2746,9 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, act.rtableid = pd->rdomain; SLIST_INIT(&rules); + if (af == AF_INET6) + ifq = &ip6intrq; + if (direction == PF_IN && pf_check_congestion(ifq)) { REASON_SET(&reason, PFRES_CONGEST); return (PF_DROP); @@ -2885,7 +2889,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, goto cleanup; } if (r->log || act.log & PF_LOG_MATCHES) - PFLOG_PACKET(kif, h, m, af, + PFLOG_PACKET(kif, h, m, direction, reason, r, a, ruleset, pd); } else { @@ -2894,7 +2898,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, *am = a; *rsm = ruleset; if (act.log & PF_LOG_MATCHES) - PFLOG_PACKET(kif, h, m, af, + PFLOG_PACKET(kif, h, m, direction, reason, r, a, ruleset, pd); } @@ -2923,7 +2927,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, REASON_SET(&reason, PFRES_MATCH); if (r->log || act.log & PF_LOG_MATCHES) - PFLOG_PACKET(kif, h, m, af, direction, reason, + PFLOG_PACKET(kif, h, m, direction, reason, r, a, ruleset, pd); if ((r->action == PF_DROP) && @@ -3447,8 +3451,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif, REASON_SET(&reason, PFRES_MATCH); if (r->log) - PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset, - pd); + PFLOG_PACKET(kif, h, m, direction, reason, r, a, ruleset, pd); if (r->action == PF_DROP) return (PF_DROP); @@ -5798,9 +5801,15 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED_PACKET) return (PF_PASS); + if (m->m_pkthdr.pf.flags & PF_TAG_REFRAGMENTED) { + m->m_pkthdr.pf.flags &= ~PF_TAG_REFRAGMENTED; + return (PF_PASS); + } + /* packet reassembly here if 1) enabled 2) we deal with a fragment */ h = mtod(m, struct ip *); - if (pf_status.reass && (h->ip_off & htons(IP_MF | IP_OFFMASK)) && + if (pf_status.reass && + (h->ip_off & htons(IP_MF | IP_OFFMASK)) && pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) { action = PF_DROP; goto done; @@ -5825,7 +5834,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, goto done; } - switch (h->ip_p) { + switch (pd.proto) { case IPPROTO_TCP: { if ((pd.hdr.tcp->th_flags & TH_ACK) && pd.p_len == 0) @@ -5844,7 +5853,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, pd.pflog |= s->log; } else if (s == NULL) action = pf_test_rule(&r, &s, dir, kif, - m, off, &pd, &a, &ruleset, &ipintrq, hdrlen); + m, off, &pd, &a, &ruleset, hdrlen); if (s) { if (s->max_mss) @@ -5866,7 +5875,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, pd.pflog |= s->log; } else if (s == NULL) action = pf_test_rule(&r, &s, dir, kif, - m, off, &pd, &a, &ruleset, &ipintrq, hdrlen); + m, off, &pd, &a, &ruleset, hdrlen); break; } @@ -5882,7 +5891,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, pd.pflog |= s->log; } else if (s == NULL) action = pf_test_rule(&r, &s, dir, kif, - m, off, &pd, &a, &ruleset, &ipintrq, hdrlen); + m, off, &pd, &a, &ruleset, hdrlen); break; } @@ -5904,7 +5913,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, pd.pflog |= s->log; } else if (s == NULL) action = pf_test_rule(&r, &s, dir, kif, m, off, - &pd, &a, &ruleset, &ipintrq, hdrlen); + &pd, &a, &ruleset, hdrlen); break; } @@ -5982,12 +5991,12 @@ done: struct pf_rule_item *ri; if (pd.pflog & PF_LOG_FORCE || r->log & PF_LOG_ALL) - PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, a, + PFLOG_PACKET(kif, h, m, dir, reason, r, a, ruleset, &pd); if (s) { SLIST_FOREACH(ri, &s->match_rules, entry) if (ri->r->log & PF_LOG_ALL) - PFLOG_PACKET(kif, h, m, AF_INET, dir, + PFLOG_PACKET(kif, h, m, dir, reason, ri->r, a, ruleset, &pd); } } @@ -6128,7 +6137,7 @@ pf_test6(int fwdir, struct ifnet *ifp, struct mbuf **m0, pd.pflog |= s->log; } else if (s == NULL) action = pf_test_rule(&r, &s, dir, kif, - m, off, &pd, &a, &ruleset, &ip6intrq, hdrlen); + m, off, &pd, &a, &ruleset, hdrlen); if (s) { if (s->max_mss) @@ -6150,7 +6159,7 @@ pf_test6(int fwdir, struct ifnet *ifp, struct mbuf **m0, pd.pflog |= s->log; } else if (s == NULL) action = pf_test_rule(&r, &s, dir, kif, - m, off, &pd, &a, &ruleset, &ip6intrq, hdrlen); + m, off, &pd, &a, &ruleset, hdrlen); break; } @@ -6162,8 +6171,8 @@ pf_test6(int fwdir, struct ifnet *ifp, struct mbuf **m0, } case IPPROTO_ICMPV6: { - action = pf_test_state_icmp(&s, dir, kif, - m, off, &pd, &reason); + action = pf_test_state_icmp(&s, dir, kif, m, off, &pd, + &reason); if (action == PF_PASS) { #if NPFSYNC > 0 pfsync_update_state(s); @@ -6173,7 +6182,7 @@ pf_test6(int fwdir, struct ifnet *ifp, struct mbuf **m0, pd.pflog |= s->log; } else if (s == NULL) action = pf_test_rule(&r, &s, dir, kif, - m, off, &pd, &a, &ruleset, &ip6intrq, hdrlen); + m, off, &pd, &a, &ruleset, hdrlen); break; } @@ -6188,24 +6197,25 @@ pf_test6(int fwdir, struct ifnet *ifp, struct mbuf **m0, pd.pflog |= s->log; } else if (s == NULL) action = pf_test_rule(&r, &s, dir, kif, m, off, - &pd, &a, &ruleset, &ip6intrq, hdrlen); + &pd, &a, &ruleset, hdrlen); break; } done: - /* handle dangerous IPv6 extension headers. */ - if (action == PF_PASS && pd.rh_cnt && - !((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) { - action = PF_DROP; - REASON_SET(&reason, PFRES_IPOPTIONS); - pd.pflog |= PF_LOG_FORCE; - DPFPRINTF(LOG_NOTICE, - "dropping packet with dangerous v6 headers"); - } - if (action != PF_DROP) { if (s) { + /* handle dangerous IPv6 extension headers. */ + if (action == PF_PASS && pd.rh_cnt && + !(s->state_flags & PFSTATE_ALLOWOPTS)) { + action = PF_DROP; + REASON_SET(&reason, PFRES_IPOPTIONS); + pd.pflog |= PF_LOG_FORCE; + DPFPRINTF(LOG_NOTICE, "dropping packet with " + "dangerous v6 headers"); + } + pf_scrub_ip6(m, s->min_ttl); + pf_tag_packet(m, s->tag, s->rtableid[pd.didx]); if (pqid || (pd.tos & IPTOS_LOWDELAY)) qid = s->pqid; else @@ -6218,8 +6228,6 @@ done: qid = r->qid; } } - if (s && s->tag) - pf_tag_packet(m, s ? s->tag : 0, s->rtableid[pd.didx]); if (dir == PF_IN && s && s->key[PF_SK_STACK]) m->m_pkthdr.pf.statekey = s->key[PF_SK_STACK]; @@ -6262,12 +6270,12 @@ done: struct pf_rule_item *ri; if (pd.pflog & PF_LOG_FORCE || r->log & PF_LOG_ALL) - PFLOG_PACKET(kif, h, m, AF_INET6, dir, reason, r, a, + PFLOG_PACKET(kif, h, m, dir, reason, r, a, ruleset, &pd); if (s) { SLIST_FOREACH(ri, &s->match_rules, entry) if (ri->r->log & PF_LOG_ALL) - PFLOG_PACKET(kif, h, m, AF_INET6, dir, + PFLOG_PACKET(kif, h, m, dir, reason, ri->r, a, ruleset, &pd); } } |