Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf.c
Show First 20 Lines • Show All 323 Lines • ▼ Show 20 Lines | |||||
static int pf_addr_wrap_neq(struct pf_addr_wrap *, | static int pf_addr_wrap_neq(struct pf_addr_wrap *, | ||||
struct pf_addr_wrap *); | struct pf_addr_wrap *); | ||||
static void pf_patch_8(struct mbuf *, u_int16_t *, u_int8_t *, u_int8_t, | static void pf_patch_8(struct mbuf *, u_int16_t *, u_int8_t *, u_int8_t, | ||||
bool, u_int8_t); | bool, u_int8_t); | ||||
static struct pf_kstate *pf_find_state(struct pfi_kkif *, | static struct pf_kstate *pf_find_state(struct pfi_kkif *, | ||||
struct pf_state_key_cmp *, u_int); | struct pf_state_key_cmp *, u_int); | ||||
static int pf_src_connlimit(struct pf_kstate **); | static int pf_src_connlimit(struct pf_kstate **); | ||||
static void pf_overload_task(void *v, int pending); | static void pf_overload_task(void *v, int pending); | ||||
static int pf_insert_src_node(struct pf_ksrc_node **, | static u_short pf_insert_src_node(struct pf_ksrc_node **, | ||||
struct pf_krule *, struct pf_addr *, sa_family_t); | struct pf_krule *, struct pf_addr *, sa_family_t); | ||||
static u_int pf_purge_expired_states(u_int, int); | static u_int pf_purge_expired_states(u_int, int); | ||||
static void pf_purge_unlinked_rules(void); | static void pf_purge_unlinked_rules(void); | ||||
static int pf_mtag_uminit(void *, int, int); | static int pf_mtag_uminit(void *, int, int); | ||||
static void pf_mtag_free(struct m_tag *); | static void pf_mtag_free(struct m_tag *); | ||||
static void pf_packet_rework_nat(struct mbuf *, struct pf_pdesc *, | static void pf_packet_rework_nat(struct mbuf *, struct pf_pdesc *, | ||||
int, struct pf_state_key *); | int, struct pf_state_key *); | ||||
#ifdef INET | #ifdef INET | ||||
▲ Show 20 Lines • Show All 519 Lines • ▼ Show 20 Lines | pf_free_src_node(struct pf_ksrc_node *sn) | ||||
for (int i = 0; i < 2; i++) { | for (int i = 0; i < 2; i++) { | ||||
counter_u64_free(sn->bytes[i]); | counter_u64_free(sn->bytes[i]); | ||||
counter_u64_free(sn->packets[i]); | counter_u64_free(sn->packets[i]); | ||||
} | } | ||||
uma_zfree(V_pf_sources_z, sn); | uma_zfree(V_pf_sources_z, sn); | ||||
} | } | ||||
static int | static u_short | ||||
pf_insert_src_node(struct pf_ksrc_node **sn, struct pf_krule *rule, | pf_insert_src_node(struct pf_ksrc_node **sn, struct pf_krule *rule, | ||||
struct pf_addr *src, sa_family_t af) | struct pf_addr *src, sa_family_t af) | ||||
{ | { | ||||
u_short reason = 0; | |||||
struct pf_srchash *sh = NULL; | struct pf_srchash *sh = NULL; | ||||
KASSERT((rule->rule_flag & PFRULE_SRCTRACK || | KASSERT((rule->rule_flag & PFRULE_SRCTRACK || | ||||
rule->rpool.opts & PF_POOL_STICKYADDR), | rule->rpool.opts & PF_POOL_STICKYADDR), | ||||
("%s for non-tracking rule %p", __func__, rule)); | ("%s for non-tracking rule %p", __func__, rule)); | ||||
if (*sn == NULL) | if (*sn == NULL) | ||||
*sn = pf_find_src_node(src, rule, af, &sh, true); | *sn = pf_find_src_node(src, rule, af, &sh, true); | ||||
if (*sn == NULL) { | if (*sn == NULL) { | ||||
PF_HASHROW_ASSERT(sh); | PF_HASHROW_ASSERT(sh); | ||||
if (!rule->max_src_nodes || | if (rule->max_src_nodes && | ||||
counter_u64_fetch(rule->src_nodes) < rule->max_src_nodes) | counter_u64_fetch(rule->src_nodes) >= rule->max_src_nodes) { | ||||
counter_u64_add(V_pf_status.lcounters[LCNT_SRCNODES], 1); | |||||
PF_HASHROW_UNLOCK(sh); | |||||
reason = PFRES_SRCLIMIT; | |||||
goto done; | |||||
} | |||||
(*sn) = uma_zalloc(V_pf_sources_z, M_NOWAIT | M_ZERO); | (*sn) = uma_zalloc(V_pf_sources_z, M_NOWAIT | M_ZERO); | ||||
else | |||||
counter_u64_add(V_pf_status.lcounters[LCNT_SRCNODES], | |||||
1); | |||||
if ((*sn) == NULL) { | if ((*sn) == NULL) { | ||||
PF_HASHROW_UNLOCK(sh); | PF_HASHROW_UNLOCK(sh); | ||||
return (-1); | reason = PFRES_MEMORY; | ||||
goto done; | |||||
} | } | ||||
for (int i = 0; i < 2; i++) { | for (int i = 0; i < 2; i++) { | ||||
(*sn)->bytes[i] = counter_u64_alloc(M_NOWAIT); | (*sn)->bytes[i] = counter_u64_alloc(M_NOWAIT); | ||||
(*sn)->packets[i] = counter_u64_alloc(M_NOWAIT); | (*sn)->packets[i] = counter_u64_alloc(M_NOWAIT); | ||||
if ((*sn)->bytes[i] == NULL || (*sn)->packets[i] == NULL) { | if ((*sn)->bytes[i] == NULL || (*sn)->packets[i] == NULL) { | ||||
pf_free_src_node(*sn); | pf_free_src_node(*sn); | ||||
PF_HASHROW_UNLOCK(sh); | PF_HASHROW_UNLOCK(sh); | ||||
return (-1); | reason = PFRES_MEMORY; | ||||
goto done; | |||||
} | } | ||||
} | } | ||||
pf_init_threshold(&(*sn)->conn_rate, | pf_init_threshold(&(*sn)->conn_rate, | ||||
rule->max_src_conn_rate.limit, | rule->max_src_conn_rate.limit, | ||||
rule->max_src_conn_rate.seconds); | rule->max_src_conn_rate.seconds); | ||||
MPASS((*sn)->lock == NULL); | MPASS((*sn)->lock == NULL); | ||||
Show All 10 Lines | if ((*sn)->rule.ptr != NULL) | ||||
counter_u64_add((*sn)->rule.ptr->src_nodes, 1); | counter_u64_add((*sn)->rule.ptr->src_nodes, 1); | ||||
PF_HASHROW_UNLOCK(sh); | PF_HASHROW_UNLOCK(sh); | ||||
counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_INSERT], 1); | counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_INSERT], 1); | ||||
} else { | } else { | ||||
if (rule->max_src_states && | if (rule->max_src_states && | ||||
(*sn)->states >= rule->max_src_states) { | (*sn)->states >= rule->max_src_states) { | ||||
counter_u64_add(V_pf_status.lcounters[LCNT_SRCSTATES], | counter_u64_add(V_pf_status.lcounters[LCNT_SRCSTATES], | ||||
1); | 1); | ||||
return (-1); | reason = PFRES_SRCLIMIT; | ||||
goto done; | |||||
} | } | ||||
} | } | ||||
return (0); | done: | ||||
return (reason); | |||||
} | } | ||||
void | void | ||||
pf_unlink_src_node(struct pf_ksrc_node *src) | pf_unlink_src_node(struct pf_ksrc_node *src) | ||||
{ | { | ||||
PF_SRC_NODE_LOCK_ASSERT(src); | PF_SRC_NODE_LOCK_ASSERT(src); | ||||
LIST_REMOVE(src, entry); | LIST_REMOVE(src, entry); | ||||
▲ Show 20 Lines • Show All 3,635 Lines • ▼ Show 20 Lines | pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a, | ||||
u_int16_t dport, int *rewrite, struct pfi_kkif *kif, struct pf_kstate **sm, | u_int16_t dport, int *rewrite, struct pfi_kkif *kif, struct pf_kstate **sm, | ||||
int tag, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen, | int tag, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen, | ||||
struct pf_krule_slist *match_rules) | struct pf_krule_slist *match_rules) | ||||
{ | { | ||||
struct pf_kstate *s = NULL; | struct pf_kstate *s = NULL; | ||||
struct pf_ksrc_node *sn = NULL; | struct pf_ksrc_node *sn = NULL; | ||||
struct tcphdr *th = &pd->hdr.tcp; | struct tcphdr *th = &pd->hdr.tcp; | ||||
u_int16_t mss = V_tcp_mssdflt; | u_int16_t mss = V_tcp_mssdflt; | ||||
u_short reason; | u_short reason, sn_reason; | ||||
/* check maximums */ | /* check maximums */ | ||||
if (r->max_states && | if (r->max_states && | ||||
(counter_u64_fetch(r->states_cur) >= r->max_states)) { | (counter_u64_fetch(r->states_cur) >= r->max_states)) { | ||||
counter_u64_add(V_pf_status.lcounters[LCNT_STATES], 1); | counter_u64_add(V_pf_status.lcounters[LCNT_STATES], 1); | ||||
REASON_SET(&reason, PFRES_MAXSTATES); | REASON_SET(&reason, PFRES_MAXSTATES); | ||||
goto csfailed; | goto csfailed; | ||||
} | } | ||||
/* src node for filter rule */ | /* src node for filter rule */ | ||||
if ((r->rule_flag & PFRULE_SRCTRACK || | if ((r->rule_flag & PFRULE_SRCTRACK || | ||||
r->rpool.opts & PF_POOL_STICKYADDR) && | r->rpool.opts & PF_POOL_STICKYADDR) && | ||||
pf_insert_src_node(&sn, r, pd->src, pd->af) != 0) { | (sn_reason = pf_insert_src_node(&sn, r, pd->src, pd->af)) != 0) { | ||||
REASON_SET(&reason, PFRES_SRCLIMIT); | REASON_SET(&reason, sn_reason); | ||||
goto csfailed; | goto csfailed; | ||||
} | } | ||||
/* src node for translation rule */ | /* src node for translation rule */ | ||||
if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) && | if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) && | ||||
pf_insert_src_node(&nsn, nr, &sk->addr[pd->sidx], pd->af)) { | (sn_reason = pf_insert_src_node(&nsn, nr, &sk->addr[pd->sidx], | ||||
REASON_SET(&reason, PFRES_SRCLIMIT); | pd->af)) != 0 ) { | ||||
REASON_SET(&reason, sn_reason); | |||||
goto csfailed; | goto csfailed; | ||||
} | } | ||||
s = pf_alloc_state(M_NOWAIT); | s = pf_alloc_state(M_NOWAIT); | ||||
if (s == NULL) { | if (s == NULL) { | ||||
REASON_SET(&reason, PFRES_MEMORY); | REASON_SET(&reason, PFRES_MEMORY); | ||||
goto csfailed; | goto csfailed; | ||||
} | } | ||||
s->rule.ptr = r; | s->rule.ptr = r; | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | #endif | ||||
break; | break; | ||||
default: | default: | ||||
pf_set_protostate(s, PF_PEER_SRC, PFOTHERS_SINGLE); | pf_set_protostate(s, PF_PEER_SRC, PFOTHERS_SINGLE); | ||||
pf_set_protostate(s, PF_PEER_DST, PFOTHERS_NO_TRAFFIC); | pf_set_protostate(s, PF_PEER_DST, PFOTHERS_NO_TRAFFIC); | ||||
s->timeout = PFTM_OTHER_FIRST_PACKET; | s->timeout = PFTM_OTHER_FIRST_PACKET; | ||||
} | } | ||||
if (r->rt) { | if (r->rt) { | ||||
if (pf_map_addr(pd->af, r, pd->src, &s->rt_addr, NULL, &sn)) { | /* pf_map_addr increases the reason counters */ | ||||
REASON_SET(&reason, PFRES_MAPFAILED); | if ((reason = pf_map_addr(pd->af, r, pd->src, &s->rt_addr, NULL, | ||||
&sn)) != 0) { | |||||
pf_src_tree_remove_state(s); | pf_src_tree_remove_state(s); | ||||
s->timeout = PFTM_UNLINKED; | s->timeout = PFTM_UNLINKED; | ||||
STATE_DEC_COUNTERS(s); | STATE_DEC_COUNTERS(s); | ||||
pf_free_state(s); | pf_free_state(s); | ||||
goto csfailed; | goto csfailed; | ||||
} | } | ||||
s->rt_kif = r->rpool.cur->kif; | s->rt_kif = r->rpool.cur->kif; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 3,403 Lines • Show Last 20 Lines |