Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf.c
Show First 20 Lines • Show All 243 Lines • ▼ Show 20 Lines | |||||
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 *); | ||||
static int pf_test_rule(struct pf_rule **, struct pf_state **, | static int pf_test_rule(struct pf_rule **, struct pf_state **, | ||||
int, struct pfi_kif *, struct mbuf *, int, | int, struct pfi_kif *, struct mbuf *, int, | ||||
struct pf_pdesc *, struct pf_rule **, | struct pf_pdesc *, struct pf_rule **, | ||||
struct pf_ruleset **, struct inpcb *); | struct pf_ruleset **, struct inpcb *); | ||||
static int pf_create_state(struct pf_rule *, struct pf_rule *, | static int pf_create_state(struct pf_rule *, struct pf_rule *, | ||||
struct pf_rule *, struct pf_pdesc *, | struct pf_rule *, struct pf_pdesc *, | ||||
struct pf_src_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, | ||||
u_int16_t, u_int16_t, int *, struct pfi_kif *, | u_int16_t, u_int16_t, int *, struct pfi_kif *, | ||||
struct pf_state **, int, u_int16_t, u_int16_t, | struct pf_state **, int, u_int16_t, u_int16_t, | ||||
int); | int); | ||||
static int pf_test_fragment(struct pf_rule **, int, | static int pf_test_fragment(struct pf_rule **, int, | ||||
struct pfi_kif *, struct mbuf *, void *, | struct pfi_kif *, struct mbuf *, void *, | ||||
struct pf_pdesc *, struct pf_rule **, | struct pf_pdesc *, struct pf_rule **, | ||||
struct pf_ruleset **); | struct pf_ruleset **); | ||||
Show All 26 Lines | |||||
static void pf_print_state_parts(struct pf_state *, | static void pf_print_state_parts(struct pf_state *, | ||||
struct pf_state_key *, struct pf_state_key *); | struct pf_state_key *, struct pf_state_key *); | ||||
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 struct pf_state *pf_find_state(struct pfi_kif *, | static struct pf_state *pf_find_state(struct pfi_kif *, | ||||
struct pf_state_key_cmp *, u_int); | struct pf_state_key_cmp *, u_int); | ||||
static int pf_src_connlimit(struct pf_state **); | static int pf_src_connlimit(struct pf_state **); | ||||
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_src_node **, | static int pf_insert_src_node(struct pf_ksrc_node **, | ||||
struct pf_rule *, struct pf_addr *, sa_family_t); | struct pf_rule *, 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 *); | ||||
#ifdef INET | #ifdef INET | ||||
static void pf_route(struct mbuf **, struct pf_rule *, int, | static void pf_route(struct mbuf **, struct pf_rule *, int, | ||||
struct ifnet *, struct pf_state *, | struct ifnet *, struct pf_state *, | ||||
▲ Show 20 Lines • Show All 366 Lines • ▼ Show 20 Lines | #endif | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
/* | /* | ||||
* Can return locked on failure, so that we can consistently | * Can return locked on failure, so that we can consistently | ||||
* allocate and insert a new one. | * allocate and insert a new one. | ||||
*/ | */ | ||||
struct pf_src_node * | struct pf_ksrc_node * | ||||
pf_find_src_node(struct pf_addr *src, struct pf_rule *rule, sa_family_t af, | pf_find_src_node(struct pf_addr *src, struct pf_rule *rule, sa_family_t af, | ||||
int returnlocked) | int returnlocked) | ||||
{ | { | ||||
struct pf_srchash *sh; | struct pf_srchash *sh; | ||||
struct pf_src_node *n; | struct pf_ksrc_node *n; | ||||
counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_SEARCH], 1); | counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_SEARCH], 1); | ||||
sh = &V_pf_srchash[pf_hashsrc(src, af)]; | sh = &V_pf_srchash[pf_hashsrc(src, af)]; | ||||
PF_HASHROW_LOCK(sh); | PF_HASHROW_LOCK(sh); | ||||
LIST_FOREACH(n, &sh->nodes, entry) | LIST_FOREACH(n, &sh->nodes, entry) | ||||
if (n->rule.ptr == rule && n->af == af && | if (n->rule.ptr == rule && n->af == af && | ||||
((af == AF_INET && n->addr.v4.s_addr == src->v4.s_addr) || | ((af == AF_INET && n->addr.v4.s_addr == src->v4.s_addr) || | ||||
(af == AF_INET6 && bcmp(&n->addr, src, sizeof(*src)) == 0))) | (af == AF_INET6 && bcmp(&n->addr, src, sizeof(*src)) == 0))) | ||||
break; | break; | ||||
if (n != NULL) { | if (n != NULL) { | ||||
n->states++; | n->states++; | ||||
PF_HASHROW_UNLOCK(sh); | PF_HASHROW_UNLOCK(sh); | ||||
} else if (returnlocked == 0) | } else if (returnlocked == 0) | ||||
PF_HASHROW_UNLOCK(sh); | PF_HASHROW_UNLOCK(sh); | ||||
return (n); | return (n); | ||||
} | } | ||||
static int | static int | ||||
pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule, | pf_insert_src_node(struct pf_ksrc_node **sn, struct pf_rule *rule, | ||||
struct pf_addr *src, sa_family_t af) | struct pf_addr *src, sa_family_t af) | ||||
{ | { | ||||
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) | ||||
Show All 37 Lines | if (rule->max_src_states && | ||||
1); | 1); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
pf_unlink_src_node(struct pf_src_node *src) | pf_unlink_src_node(struct pf_ksrc_node *src) | ||||
{ | { | ||||
PF_HASHROW_ASSERT(&V_pf_srchash[pf_hashsrc(&src->addr, src->af)]); | PF_HASHROW_ASSERT(&V_pf_srchash[pf_hashsrc(&src->addr, src->af)]); | ||||
LIST_REMOVE(src, entry); | LIST_REMOVE(src, entry); | ||||
if (src->rule.ptr) | if (src->rule.ptr) | ||||
counter_u64_add(src->rule.ptr->src_nodes, -1); | counter_u64_add(src->rule.ptr->src_nodes, -1); | ||||
} | } | ||||
u_int | u_int | ||||
pf_free_src_nodes(struct pf_src_node_list *head) | pf_free_src_nodes(struct pf_ksrc_node_list *head) | ||||
{ | { | ||||
struct pf_src_node *sn, *tmp; | struct pf_ksrc_node *sn, *tmp; | ||||
u_int count = 0; | u_int count = 0; | ||||
LIST_FOREACH_SAFE(sn, head, entry, tmp) { | LIST_FOREACH_SAFE(sn, head, entry, tmp) { | ||||
uma_zfree(V_pf_sources_z, sn); | uma_zfree(V_pf_sources_z, sn); | ||||
count++; | count++; | ||||
} | } | ||||
counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS], count); | counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS], count); | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | pf_initialize() | ||||
for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash; i <= pf_hashmask; | for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash; i <= pf_hashmask; | ||||
i++, kh++, ih++) { | i++, kh++, ih++) { | ||||
mtx_init(&kh->lock, "pf_keyhash", NULL, MTX_DEF | MTX_DUPOK); | mtx_init(&kh->lock, "pf_keyhash", NULL, MTX_DEF | MTX_DUPOK); | ||||
mtx_init(&ih->lock, "pf_idhash", NULL, MTX_DEF); | mtx_init(&ih->lock, "pf_idhash", NULL, MTX_DEF); | ||||
} | } | ||||
/* Source nodes. */ | /* Source nodes. */ | ||||
V_pf_sources_z = uma_zcreate("pf source nodes", | V_pf_sources_z = uma_zcreate("pf source nodes", | ||||
sizeof(struct pf_src_node), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, | sizeof(struct pf_ksrc_node), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, | ||||
0); | 0); | ||||
V_pf_limits[PF_LIMIT_SRC_NODES].zone = V_pf_sources_z; | V_pf_limits[PF_LIMIT_SRC_NODES].zone = V_pf_sources_z; | ||||
uma_zone_set_max(V_pf_sources_z, PFSNODE_HIWAT); | uma_zone_set_max(V_pf_sources_z, PFSNODE_HIWAT); | ||||
uma_zone_set_warning(V_pf_sources_z, "PF source nodes limit reached"); | uma_zone_set_warning(V_pf_sources_z, "PF source nodes limit reached"); | ||||
V_pf_srchash = mallocarray(pf_srchashsize, | V_pf_srchash = mallocarray(pf_srchashsize, | ||||
sizeof(struct pf_srchash), M_PFHASH, M_NOWAIT | M_ZERO); | sizeof(struct pf_srchash), M_PFHASH, M_NOWAIT | M_ZERO); | ||||
if (V_pf_srchash == NULL) { | if (V_pf_srchash == NULL) { | ||||
▲ Show 20 Lines • Show All 734 Lines • ▼ Show 20 Lines | else | ||||
return (time_uptime); | return (time_uptime); | ||||
} | } | ||||
return (state->expire + timeout); | return (state->expire + timeout); | ||||
} | } | ||||
void | void | ||||
pf_purge_expired_src_nodes() | pf_purge_expired_src_nodes() | ||||
{ | { | ||||
struct pf_src_node_list freelist; | struct pf_ksrc_node_list freelist; | ||||
struct pf_srchash *sh; | struct pf_srchash *sh; | ||||
struct pf_src_node *cur, *next; | struct pf_ksrc_node *cur, *next; | ||||
int i; | int i; | ||||
LIST_INIT(&freelist); | LIST_INIT(&freelist); | ||||
for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask; i++, sh++) { | for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask; i++, sh++) { | ||||
PF_HASHROW_LOCK(sh); | PF_HASHROW_LOCK(sh); | ||||
LIST_FOREACH_SAFE(cur, &sh->nodes, entry, next) | LIST_FOREACH_SAFE(cur, &sh->nodes, entry, next) | ||||
if (cur->states == 0 && cur->expire <= time_uptime) { | if (cur->states == 0 && cur->expire <= time_uptime) { | ||||
pf_unlink_src_node(cur); | pf_unlink_src_node(cur); | ||||
LIST_INSERT_HEAD(&freelist, cur, entry); | LIST_INSERT_HEAD(&freelist, cur, entry); | ||||
} else if (cur->rule.ptr != NULL) | } else if (cur->rule.ptr != NULL) | ||||
cur->rule.ptr->rule_flag |= PFRULE_REFS; | cur->rule.ptr->rule_flag |= PFRULE_REFS; | ||||
PF_HASHROW_UNLOCK(sh); | PF_HASHROW_UNLOCK(sh); | ||||
} | } | ||||
pf_free_src_nodes(&freelist); | pf_free_src_nodes(&freelist); | ||||
V_pf_status.src_nodes = uma_zone_get_cur(V_pf_sources_z); | V_pf_status.src_nodes = uma_zone_get_cur(V_pf_sources_z); | ||||
} | } | ||||
static void | static void | ||||
pf_src_tree_remove_state(struct pf_state *s) | pf_src_tree_remove_state(struct pf_state *s) | ||||
{ | { | ||||
struct pf_src_node *sn; | struct pf_ksrc_node *sn; | ||||
struct pf_srchash *sh; | struct pf_srchash *sh; | ||||
uint32_t timeout; | uint32_t timeout; | ||||
timeout = s->rule.ptr->timeout[PFTM_SRC_NODE] ? | timeout = s->rule.ptr->timeout[PFTM_SRC_NODE] ? | ||||
s->rule.ptr->timeout[PFTM_SRC_NODE] : | s->rule.ptr->timeout[PFTM_SRC_NODE] : | ||||
V_pf_default_rule.timeout[PFTM_SRC_NODE]; | V_pf_default_rule.timeout[PFTM_SRC_NODE]; | ||||
if (s->src_node != NULL) { | if (s->src_node != NULL) { | ||||
▲ Show 20 Lines • Show All 1,614 Lines • ▼ Show 20 Lines | pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, | ||||
struct pf_rule **am, struct pf_ruleset **rsm, struct inpcb *inp) | struct pf_rule **am, struct pf_ruleset **rsm, struct inpcb *inp) | ||||
{ | { | ||||
struct pf_rule *nr = NULL; | struct pf_rule *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; | ||||
struct pf_rule *r, *a = NULL; | struct pf_rule *r, *a = NULL; | ||||
struct pf_ruleset *ruleset = NULL; | struct pf_ruleset *ruleset = NULL; | ||||
struct pf_src_node *nsn = NULL; | struct pf_ksrc_node *nsn = NULL; | ||||
struct tcphdr *th = pd->hdr.tcp; | struct tcphdr *th = pd->hdr.tcp; | ||||
struct pf_state_key *sk = NULL, *nk = NULL; | struct pf_state_key *sk = NULL, *nk = NULL; | ||||
u_short reason; | u_short reason; | ||||
int rewrite = 0, hdrlen = 0; | int rewrite = 0, hdrlen = 0; | ||||
int tag = -1, rtableid = -1; | int tag = -1, rtableid = -1; | ||||
int asd = 0; | int asd = 0; | ||||
int match = 0; | int match = 0; | ||||
int state_icmp = 0; | int state_icmp = 0; | ||||
▲ Show 20 Lines • Show All 348 Lines • ▼ Show 20 Lines | if (sk != NULL) | ||||
uma_zfree(V_pf_state_key_z, sk); | uma_zfree(V_pf_state_key_z, sk); | ||||
if (nk != NULL) | if (nk != NULL) | ||||
uma_zfree(V_pf_state_key_z, nk); | uma_zfree(V_pf_state_key_z, nk); | ||||
return (PF_DROP); | return (PF_DROP); | ||||
} | } | ||||
static int | static int | ||||
pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a, | pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a, | ||||
struct pf_pdesc *pd, struct pf_src_node *nsn, struct pf_state_key *nk, | struct pf_pdesc *pd, struct pf_ksrc_node *nsn, struct pf_state_key *nk, | ||||
struct pf_state_key *sk, struct mbuf *m, int off, u_int16_t sport, | struct pf_state_key *sk, struct mbuf *m, int off, u_int16_t sport, | ||||
u_int16_t dport, int *rewrite, struct pfi_kif *kif, struct pf_state **sm, | u_int16_t dport, int *rewrite, struct pfi_kif *kif, struct pf_state **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_state *s = NULL; | struct pf_state *s = NULL; | ||||
struct pf_src_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; | ||||
/* 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); | ||||
▲ Show 20 Lines • Show All 1,738 Lines • ▼ Show 20 Lines | |||||
pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, | pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, | ||||
struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp) | struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp) | ||||
{ | { | ||||
struct mbuf *m0, *m1; | struct mbuf *m0, *m1; | ||||
struct sockaddr_in dst; | struct sockaddr_in dst; | ||||
struct ip *ip; | struct ip *ip; | ||||
struct ifnet *ifp = NULL; | struct ifnet *ifp = NULL; | ||||
struct pf_addr naddr; | struct pf_addr naddr; | ||||
struct pf_src_node *sn = NULL; | struct pf_ksrc_node *sn = NULL; | ||||
int error = 0; | int error = 0; | ||||
uint16_t ip_len, ip_off; | uint16_t ip_len, ip_off; | ||||
KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__)); | KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__)); | ||||
KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: invalid direction", | KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: invalid direction", | ||||
__func__)); | __func__)); | ||||
if ((pd->pf_mtag == NULL && | if ((pd->pf_mtag == NULL && | ||||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | |||||
pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, | pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, | ||||
struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp) | struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp) | ||||
{ | { | ||||
struct mbuf *m0; | struct mbuf *m0; | ||||
struct sockaddr_in6 dst; | struct sockaddr_in6 dst; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
struct ifnet *ifp = NULL; | struct ifnet *ifp = NULL; | ||||
struct pf_addr naddr; | struct pf_addr naddr; | ||||
struct pf_src_node *sn = NULL; | struct pf_ksrc_node *sn = NULL; | ||||
KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__)); | KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__)); | ||||
KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: invalid direction", | KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: invalid direction", | ||||
__func__)); | __func__)); | ||||
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)) || | ||||
pd->pf_mtag->routed++ > 3) { | pd->pf_mtag->routed++ > 3) { | ||||
▲ Show 20 Lines • Show All 1,026 Lines • Show Last 20 Lines |