Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf.c
Show First 20 Lines • Show All 6,444 Lines • ▼ Show 20 Lines | pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) | ||||
if (kif->pfik_flags & PFI_IFLAG_SKIP) | if (kif->pfik_flags & PFI_IFLAG_SKIP) | ||||
return (PF_PASS); | return (PF_PASS); | ||||
if (m->m_flags & M_SKIP_FIREWALL) | if (m->m_flags & M_SKIP_FIREWALL) | ||||
return (PF_PASS); | return (PF_PASS); | ||||
pd.pf_mtag = pf_find_mtag(m); | pd.pf_mtag = pf_find_mtag(m); | ||||
if (ip_dn_io_ptr != NULL && pd.pf_mtag != NULL && | |||||
pd.pf_mtag->flags & PF_TAG_DUMMYNET) { | |||||
/* Dummynet re-injects packets after they've | |||||
* completed their delay. We've already | |||||
* processed them, so pass unconditionally. */ | |||||
/* But only once. We may see the packet multiple times (e.g. | |||||
* PFIL_IN/PFIL_OUT). */ | |||||
pd.pf_mtag->flags &= ~PF_TAG_DUMMYNET; | |||||
return (PF_PASS); | |||||
} | |||||
PF_RULES_RLOCK(); | PF_RULES_RLOCK(); | ||||
if ((__predict_false(ip_divert_ptr != NULL) || ip_dn_io_ptr != NULL) && | if (__predict_false(ip_divert_ptr != NULL) && | ||||
((ipfwtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) { | ((ipfwtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) { | ||||
struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(ipfwtag+1); | struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(ipfwtag+1); | ||||
if ((rr->info & IPFW_IS_DIVERT && rr->rulenum == 0) || | if (rr->info & IPFW_IS_DIVERT && rr->rulenum == 0) { | ||||
(rr->info & IPFW_IS_DUMMYNET)) { | |||||
if (pd.pf_mtag == NULL && | if (pd.pf_mtag == NULL && | ||||
((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { | ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { | ||||
action = PF_DROP; | action = PF_DROP; | ||||
goto done; | goto done; | ||||
} | } | ||||
pd.pf_mtag->flags |= PF_PACKET_LOOPED; | pd.pf_mtag->flags |= PF_PACKET_LOOPED; | ||||
m_tag_delete(m, ipfwtag); | m_tag_delete(m, ipfwtag); | ||||
if (rr->info & IPFW_IS_DUMMYNET) { | |||||
/* Dummynet re-injects packets after they've | |||||
* completed their delay. We've already | |||||
* processed them, so pass unconditionally. */ | |||||
PF_RULES_RUNLOCK(); | |||||
return (PF_PASS); | |||||
} | } | ||||
} | |||||
if (pd.pf_mtag && pd.pf_mtag->flags & PF_FASTFWD_OURS_PRESENT) { | if (pd.pf_mtag && pd.pf_mtag->flags & PF_FASTFWD_OURS_PRESENT) { | ||||
m->m_flags |= M_FASTFWD_OURS; | m->m_flags |= M_FASTFWD_OURS; | ||||
pd.pf_mtag->flags &= ~PF_FASTFWD_OURS_PRESENT; | pd.pf_mtag->flags &= ~PF_FASTFWD_OURS_PRESENT; | ||||
} | } | ||||
} else if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) { | } else if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) { | ||||
/* We do IP header normalization and packet reassembly here */ | /* We do IP header normalization and packet reassembly here */ | ||||
action = PF_DROP; | action = PF_DROP; | ||||
goto done; | goto done; | ||||
▲ Show 20 Lines • Show All 382 Lines • ▼ Show 20 Lines | if (s && (s->dnpipe || s->dnrpipe)) { | ||||
pd.act.dnrpipe = s->dnrpipe; | pd.act.dnrpipe = s->dnrpipe; | ||||
pd.act.flags = s->state_flags; | pd.act.flags = s->state_flags; | ||||
} else if (r->dnpipe || r->dnrpipe) { | } else if (r->dnpipe || r->dnrpipe) { | ||||
pd.act.dnpipe = r->dnpipe; | pd.act.dnpipe = r->dnpipe; | ||||
pd.act.dnrpipe = r->dnrpipe; | pd.act.dnrpipe = r->dnrpipe; | ||||
pd.act.flags = r->free_flags; | pd.act.flags = r->free_flags; | ||||
} | } | ||||
if (pd.act.dnpipe || pd.act.dnrpipe) { | if (pd.act.dnpipe || pd.act.dnrpipe) { | ||||
struct ip_fw_args dnflow; | |||||
if (ip_dn_io_ptr == NULL) { | if (ip_dn_io_ptr == NULL) { | ||||
m_freem(*m0); | m_freem(*m0); | ||||
*m0 = NULL; | *m0 = NULL; | ||||
action = PF_DROP; | action = PF_DROP; | ||||
REASON_SET(&reason, PFRES_MEMORY); | REASON_SET(&reason, PFRES_MEMORY); | ||||
} else { | break; | ||||
struct ip_fw_args dnflow; | } | ||||
if (pd.pf_mtag == NULL && | |||||
((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { | |||||
m_freem(*m0); | |||||
*m0 = NULL; | |||||
action = PF_DROP; | |||||
REASON_SET(&reason, PFRES_MEMORY); | |||||
break; | |||||
} | |||||
if (pf_pdesc_to_dnflow(dir, &pd, r, s, &dnflow)) { | if (pf_pdesc_to_dnflow(dir, &pd, r, s, &dnflow)) { | ||||
pd.pf_mtag->flags |= PF_TAG_DUMMYNET; | |||||
ip_dn_io_ptr(m0, &dnflow); | ip_dn_io_ptr(m0, &dnflow); | ||||
if (*m0 == NULL) | if (*m0 == NULL) | ||||
action = PF_DROP; | action = PF_DROP; | ||||
} | } | ||||
} | } | ||||
} | |||||
break; | break; | ||||
} | } | ||||
SDT_PROBE4(pf, ip, test, done, action, reason, r, s); | SDT_PROBE4(pf, ip, test, done, action, reason, r, s); | ||||
if (s) | if (s) | ||||
PF_STATE_UNLOCK(s); | PF_STATE_UNLOCK(s); | ||||
return (action); | return (action); | ||||
} | } | ||||
#endif /* INET */ | #endif /* INET */ | ||||
#ifdef INET6 | #ifdef INET6 | ||||
int | int | ||||
pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) | pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) | ||||
{ | { | ||||
struct pfi_kkif *kif; | struct pfi_kkif *kif; | ||||
u_short action, reason = 0, log = 0; | u_short action, reason = 0, log = 0; | ||||
struct mbuf *m = *m0, *n = NULL; | struct mbuf *m = *m0, *n = NULL; | ||||
struct m_tag *mtag; | struct m_tag *mtag; | ||||
struct m_tag *ipfwtag; | |||||
struct ip6_hdr *h = NULL; | struct ip6_hdr *h = NULL; | ||||
struct pf_krule *a = NULL, *r = &V_pf_default_rule, *tr, *nr; | struct pf_krule *a = NULL, *r = &V_pf_default_rule, *tr, *nr; | ||||
struct pf_kstate *s = NULL; | struct pf_kstate *s = NULL; | ||||
struct pf_kruleset *ruleset = NULL; | struct pf_kruleset *ruleset = NULL; | ||||
struct pf_pdesc pd; | struct pf_pdesc pd; | ||||
int off, terminal = 0, dirndx, rh_cnt = 0, pqid = 0; | int off, terminal = 0, dirndx, rh_cnt = 0, pqid = 0; | ||||
PF_RULES_RLOCK_TRACKER; | PF_RULES_RLOCK_TRACKER; | ||||
Show All 16 Lines | if (kif == NULL) { | ||||
return (PF_DROP); | return (PF_DROP); | ||||
} | } | ||||
if (kif->pfik_flags & PFI_IFLAG_SKIP) | if (kif->pfik_flags & PFI_IFLAG_SKIP) | ||||
return (PF_PASS); | return (PF_PASS); | ||||
if (m->m_flags & M_SKIP_FIREWALL) | if (m->m_flags & M_SKIP_FIREWALL) | ||||
return (PF_PASS); | return (PF_PASS); | ||||
PF_RULES_RLOCK(); | if (ip_dn_io_ptr != NULL && pd.pf_mtag != NULL && | ||||
pd.pf_mtag->flags & PF_TAG_DUMMYNET) { | |||||
/* We do IP header normalization and packet reassembly here */ | pd.pf_mtag->flags &= ~PF_TAG_DUMMYNET; | ||||
if (ip_dn_io_ptr != NULL && | |||||
((ipfwtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) { | |||||
struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(ipfwtag+1); | |||||
if (rr->info & IPFW_IS_DUMMYNET) { | |||||
if (pd.pf_mtag == NULL && | |||||
((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { | |||||
action = PF_DROP; | |||||
goto done; | |||||
} | |||||
pd.pf_mtag->flags |= PF_PACKET_LOOPED; | |||||
m_tag_delete(m, ipfwtag); | |||||
if (rr->info & IPFW_IS_DUMMYNET) { | |||||
/* Dummynet re-injects packets after they've | /* Dummynet re-injects packets after they've | ||||
* completed their delay. We've already | * completed their delay. We've already | ||||
* processed them, so pass unconditionally. */ | * processed them, so pass unconditionally. */ | ||||
PF_RULES_RUNLOCK(); | |||||
return (PF_PASS); | return (PF_PASS); | ||||
} | } | ||||
} | |||||
} else if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) { | PF_RULES_RLOCK(); | ||||
/* We do IP header normalization and packet reassembly here */ | |||||
if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) { | |||||
action = PF_DROP; | action = PF_DROP; | ||||
goto done; | goto done; | ||||
} | } | ||||
m = *m0; /* pf_normalize messes with m0 */ | m = *m0; /* pf_normalize messes with m0 */ | ||||
h = mtod(m, struct ip6_hdr *); | h = mtod(m, struct ip6_hdr *); | ||||
/* | /* | ||||
* we do not support jumbogram. if we keep going, zero ip6_plen | * we do not support jumbogram. if we keep going, zero ip6_plen | ||||
▲ Show 20 Lines • Show All 349 Lines • ▼ Show 20 Lines | if (s && (s->dnpipe || s->dnrpipe)) { | ||||
pd.act.dnrpipe = s->dnrpipe; | pd.act.dnrpipe = s->dnrpipe; | ||||
pd.act.flags = s->state_flags; | pd.act.flags = s->state_flags; | ||||
} else { | } else { | ||||
pd.act.dnpipe = r->dnpipe; | pd.act.dnpipe = r->dnpipe; | ||||
pd.act.dnrpipe = r->dnrpipe; | pd.act.dnrpipe = r->dnrpipe; | ||||
pd.act.flags = r->free_flags; | pd.act.flags = r->free_flags; | ||||
} | } | ||||
if (pd.act.dnpipe || pd.act.dnrpipe) { | if (pd.act.dnpipe || pd.act.dnrpipe) { | ||||
struct ip_fw_args dnflow; | |||||
if (ip_dn_io_ptr == NULL) { | if (ip_dn_io_ptr == NULL) { | ||||
m_freem(*m0); | m_freem(*m0); | ||||
*m0 = NULL; | *m0 = NULL; | ||||
action = PF_DROP; | action = PF_DROP; | ||||
REASON_SET(&reason, PFRES_MEMORY); | REASON_SET(&reason, PFRES_MEMORY); | ||||
} else { | break; | ||||
struct ip_fw_args dnflow; | } | ||||
if (pd.pf_mtag == NULL && | if (pd.pf_mtag == NULL && | ||||
((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { | ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { | ||||
m_freem(*m0); | m_freem(*m0); | ||||
*m0 = NULL; | *m0 = NULL; | ||||
action = PF_DROP; | action = PF_DROP; | ||||
REASON_SET(&reason, PFRES_MEMORY); | REASON_SET(&reason, PFRES_MEMORY); | ||||
if (s) | break; | ||||
PF_STATE_UNLOCK(s); | |||||
return (action); | |||||
} | } | ||||
if (pf_pdesc_to_dnflow(dir, &pd, r, s, &dnflow)) { | if (pf_pdesc_to_dnflow(dir, &pd, r, s, &dnflow)) { | ||||
pd.pf_mtag->flags |= PF_TAG_DUMMYNET; | |||||
ip_dn_io_ptr(m0, &dnflow); | ip_dn_io_ptr(m0, &dnflow); | ||||
if (*m0 == NULL) | if (*m0 == NULL) | ||||
action = PF_DROP; | action = PF_DROP; | ||||
} | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
if (s) | if (s) | ||||
PF_STATE_UNLOCK(s); | PF_STATE_UNLOCK(s); | ||||
Show All 10 Lines |