Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf.c
Show First 20 Lines • Show All 263 Lines • ▼ Show 20 Lines | |||||
static void pf_detach_state(struct pf_kstate *); | static void pf_detach_state(struct pf_kstate *); | ||||
static int pf_state_key_attach(struct pf_state_key *, | static int pf_state_key_attach(struct pf_state_key *, | ||||
struct pf_state_key *, struct pf_kstate *); | struct pf_state_key *, struct pf_kstate *); | ||||
static void pf_state_key_detach(struct pf_kstate *, int); | static void pf_state_key_detach(struct pf_kstate *, int); | ||||
static int pf_state_key_ctor(void *, int, void *, int); | static int pf_state_key_ctor(void *, int, void *, int); | ||||
static u_int32_t pf_tcp_iss(struct pf_pdesc *); | static u_int32_t pf_tcp_iss(struct pf_pdesc *); | ||||
void pf_rule_to_actions(struct pf_krule *, | void pf_rule_to_actions(struct pf_krule *, | ||||
struct pf_rule_actions *); | struct pf_rule_actions *); | ||||
static int pf_test_eth_rule(int, struct pfi_kkif *, | |||||
struct mbuf *); | |||||
static int pf_test_rule(struct pf_krule **, struct pf_kstate **, | static int pf_test_rule(struct pf_krule **, struct pf_kstate **, | ||||
int, struct pfi_kkif *, struct mbuf *, int, | int, struct pfi_kkif *, struct mbuf *, int, | ||||
struct pf_pdesc *, struct pf_krule **, | struct pf_pdesc *, struct pf_krule **, | ||||
struct pf_kruleset **, struct inpcb *); | struct pf_kruleset **, struct inpcb *); | ||||
static int pf_create_state(struct pf_krule *, struct pf_krule *, | static int pf_create_state(struct pf_krule *, struct pf_krule *, | ||||
struct pf_krule *, struct pf_pdesc *, | struct pf_krule *, struct pf_pdesc *, | ||||
struct pf_ksrc_node *, struct pf_state_key *, | struct pf_ksrc_node *, struct pf_state_key *, | ||||
struct pf_state_key *, struct mbuf *, int, | struct pf_state_key *, struct mbuf *, int, | ||||
▲ Show 20 Lines • Show All 3,280 Lines • ▼ Show 20 Lines | pf_tcp_iss(struct pf_pdesc *pd) | ||||
MD5Final((u_char *)digest, &ctx); | MD5Final((u_char *)digest, &ctx); | ||||
V_pf_tcp_iss_off += 4096; | V_pf_tcp_iss_off += 4096; | ||||
#define ISN_RANDOM_INCREMENT (4096 - 1) | #define ISN_RANDOM_INCREMENT (4096 - 1) | ||||
return (digest[0] + (arc4random() & ISN_RANDOM_INCREMENT) + | return (digest[0] + (arc4random() & ISN_RANDOM_INCREMENT) + | ||||
V_pf_tcp_iss_off); | V_pf_tcp_iss_off); | ||||
#undef ISN_RANDOM_INCREMENT | #undef ISN_RANDOM_INCREMENT | ||||
} | } | ||||
static bool | |||||
pf_match_eth_addr(const uint8_t *a, const struct pf_keth_rule_addr *r) | |||||
{ | |||||
/* Always matches if not set */ | |||||
if (! r->isset) | |||||
return (!r->neg); | |||||
if (memcmp(a, r->addr, ETHER_ADDR_LEN) == 0) | |||||
return (!r->neg); | |||||
return (r->neg); | |||||
} | |||||
static int | static int | ||||
pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf *m) | |||||
{ | |||||
struct ether_header *e; | |||||
struct pf_keth_rule *r, *rm; | |||||
struct pf_mtag *mtag; | |||||
uint8_t action; | |||||
PF_RULES_RLOCK_TRACKER; | |||||
MPASS(kif->pfik_ifp->if_vnet == curvnet); | |||||
NET_EPOCH_ASSERT(); | |||||
e = mtod(m, struct ether_header *); | |||||
PF_RULES_RLOCK(); | |||||
r = TAILQ_FIRST(&V_pf_keth->rules); | |||||
rm = NULL; | |||||
while (r != NULL) { | |||||
counter_u64_add(r->evaluations, 1); | |||||
if (pfi_kkif_match(r->kif, kif) == r->ifnot) | |||||
r = r->skip[PFE_SKIP_IFP].ptr; | |||||
else if (r->direction && r->direction != dir) | |||||
r = r->skip[PFE_SKIP_DIR].ptr; | |||||
else if (r->proto && r->proto != ntohs(e->ether_type)) | |||||
r = r->skip[PFE_SKIP_PROTO].ptr; | |||||
else if (! pf_match_eth_addr(e->ether_shost, &r->src)) | |||||
r = r->skip[PFE_SKIP_SRC_ADDR].ptr; | |||||
else if (! pf_match_eth_addr(e->ether_dhost, &r->dst)) { | |||||
r = TAILQ_NEXT(r, entries); | |||||
} | |||||
else { | |||||
/* Rule matches */ | |||||
rm = r; | |||||
if (r->quick) | |||||
break; | |||||
r = TAILQ_NEXT(r, entries); | |||||
} | |||||
} | |||||
r = rm; | |||||
/* Default to pass. */ | |||||
if (r == NULL) { | |||||
PF_RULES_RUNLOCK(); | |||||
return (PF_PASS); | |||||
} | |||||
/* Execute action. */ | |||||
counter_u64_add(r->packets[dir == PF_OUT], 1); | |||||
counter_u64_add(r->bytes[dir == PF_OUT], m_length(m, NULL)); | |||||
/* Shortcut. Don't tag if we're just going to drop anyway. */ | |||||
if (r->action == PF_DROP) { | |||||
PF_RULES_RUNLOCK(); | |||||
return (PF_DROP); | |||||
} | |||||
if (r->tag > 0) { | |||||
mtag = pf_get_mtag(m); | |||||
if (mtag == NULL) { | |||||
counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1); | |||||
PF_RULES_RUNLOCK(); | |||||
return (PF_DROP); | |||||
} | |||||
mtag->tag = r->tag; | |||||
} | |||||
if (r->qid != 0) { | |||||
mtag = pf_get_mtag(m); | |||||
if (mtag == NULL) { | |||||
counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1); | |||||
PF_RULES_RUNLOCK(); | |||||
return (PF_DROP); | |||||
} | |||||
mtag->qid = r->qid; | |||||
} | |||||
action = r->action; | |||||
PF_RULES_RUNLOCK(); | |||||
return (action); | |||||
} | |||||
static int | |||||
pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, int direction, | pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, int direction, | ||||
struct pfi_kkif *kif, struct mbuf *m, int off, struct pf_pdesc *pd, | 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_krule **am, struct pf_kruleset **rsm, struct inpcb *inp) | ||||
{ | { | ||||
struct pf_krule *nr = NULL; | struct pf_krule *nr = NULL; | ||||
struct pf_addr * const saddr = pd->src; | struct pf_addr * const saddr = pd->src; | ||||
struct pf_addr * const daddr = pd->dst; | struct pf_addr * const daddr = pd->dst; | ||||
sa_family_t af = pd->af; | sa_family_t af = pd->af; | ||||
▲ Show 20 Lines • Show All 2,731 Lines • ▼ Show 20 Lines | case AF_INET6: | ||||
dnflow->f_id.dst_ip6 = pd->dst->v6; | dnflow->f_id.dst_ip6 = pd->dst->v6; | ||||
break; | break; | ||||
default: | default: | ||||
panic("Invalid AF"); | panic("Invalid AF"); | ||||
break; | break; | ||||
} | } | ||||
return (true); | return (true); | ||||
} | |||||
int | |||||
pf_test_eth(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, | |||||
struct inpcb *inp) | |||||
{ | |||||
struct pfi_kkif *kif; | |||||
struct mbuf *m = *m0; | |||||
M_ASSERTPKTHDR(m); | |||||
MPASS(ifp->if_vnet == curvnet); | |||||
NET_EPOCH_ASSERT(); | |||||
if (!V_pf_status.running) | |||||
return (PF_PASS); | |||||
kif = (struct pfi_kkif *)ifp->if_pf_kif; | |||||
if (kif == NULL) { | |||||
DPFPRINTF(PF_DEBUG_URGENT, | |||||
("pf_test: kif == NULL, if_xname %s\n", ifp->if_xname)); | |||||
return (PF_DROP); | |||||
} | |||||
if (kif->pfik_flags & PFI_IFLAG_SKIP) | |||||
return (PF_PASS); | |||||
if (m->m_flags & M_SKIP_FIREWALL) | |||||
return (PF_PASS); | |||||
/* Stateless! */ | |||||
return (pf_test_eth_rule(dir, kif, m)); | |||||
} | } | ||||
#ifdef INET | #ifdef INET | ||||
int | int | ||||
pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) | pf_test(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; | ||||
▲ Show 20 Lines • Show All 956 Lines • Show Last 20 Lines |