Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf.c
Show First 20 Lines • Show All 188 Lines • ▼ Show 20 Lines | |||||
MTX_SYSINIT(pf_unlnkdrules_mtx, &pf_unlnkdrules_mtx, "pf unlinked rules", | MTX_SYSINIT(pf_unlnkdrules_mtx, &pf_unlnkdrules_mtx, "pf unlinked rules", | ||||
MTX_DEF); | MTX_DEF); | ||||
static VNET_DEFINE(uma_zone_t, pf_sources_z); | static VNET_DEFINE(uma_zone_t, pf_sources_z); | ||||
#define V_pf_sources_z VNET(pf_sources_z) | #define V_pf_sources_z VNET(pf_sources_z) | ||||
uma_zone_t pf_mtag_z; | uma_zone_t pf_mtag_z; | ||||
VNET_DEFINE(uma_zone_t, pf_state_z); | VNET_DEFINE(uma_zone_t, pf_state_z); | ||||
VNET_DEFINE(uma_zone_t, pf_state_key_z); | VNET_DEFINE(uma_zone_t, pf_state_key_z); | ||||
VNET_DEFINE(uma_zone_t, pf_udp_mapping_z); | |||||
VNET_DEFINE(uint64_t, pf_stateid[MAXCPU]); | VNET_DEFINE(uint64_t, pf_stateid[MAXCPU]); | ||||
#define PFID_CPUBITS 8 | #define PFID_CPUBITS 8 | ||||
#define PFID_CPUSHIFT (sizeof(uint64_t) * NBBY - PFID_CPUBITS) | #define PFID_CPUSHIFT (sizeof(uint64_t) * NBBY - PFID_CPUBITS) | ||||
#define PFID_CPUMASK ((uint64_t)((1 << PFID_CPUBITS) - 1) << PFID_CPUSHIFT) | #define PFID_CPUMASK ((uint64_t)((1 << PFID_CPUBITS) - 1) << PFID_CPUSHIFT) | ||||
#define PFID_MAXID (~PFID_CPUMASK) | #define PFID_MAXID (~PFID_CPUMASK) | ||||
CTASSERT((1 << PFID_CPUBITS) >= MAXCPU); | CTASSERT((1 << PFID_CPUBITS) >= MAXCPU); | ||||
Show All 31 Lines | static int pf_test_rule(struct pf_rule **, struct pf_state **, | ||||
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_src_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, struct pf_udp_mapping *); | ||||
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 **); | ||||
static int pf_tcp_track_full(struct pf_state_peer *, | static int pf_tcp_track_full(struct pf_state_peer *, | ||||
struct pf_state_peer *, struct pf_state **, | struct pf_state_peer *, struct pf_state **, | ||||
struct pfi_kif *, struct mbuf *, int, | struct pfi_kif *, struct mbuf *, int, | ||||
struct pf_pdesc *, u_short *, int *); | struct pf_pdesc *, u_short *, int *); | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | if (s->anchor.ptr != NULL) \ | ||||
counter_u64_add(s->anchor.ptr->states_cur, -1); \ | counter_u64_add(s->anchor.ptr->states_cur, -1); \ | ||||
counter_u64_add(s->rule.ptr->states_cur, -1); \ | counter_u64_add(s->rule.ptr->states_cur, -1); \ | ||||
} while (0) | } while (0) | ||||
static MALLOC_DEFINE(M_PFHASH, "pf_hash", "pf(4) hash header structures"); | static MALLOC_DEFINE(M_PFHASH, "pf_hash", "pf(4) hash header structures"); | ||||
VNET_DEFINE(struct pf_keyhash *, pf_keyhash); | VNET_DEFINE(struct pf_keyhash *, pf_keyhash); | ||||
VNET_DEFINE(struct pf_idhash *, pf_idhash); | VNET_DEFINE(struct pf_idhash *, pf_idhash); | ||||
VNET_DEFINE(struct pf_srchash *, pf_srchash); | VNET_DEFINE(struct pf_srchash *, pf_srchash); | ||||
VNET_DEFINE(struct pf_udpendpointhash *, pf_udpendpointhash); | |||||
SYSCTL_NODE(_net, OID_AUTO, pf, CTLFLAG_RW, 0, "pf(4)"); | SYSCTL_NODE(_net, OID_AUTO, pf, CTLFLAG_RW, 0, "pf(4)"); | ||||
u_long pf_hashmask; | u_long pf_hashmask; | ||||
u_long pf_srchashmask; | u_long pf_srchashmask; | ||||
static u_long pf_hashsize; | static u_long pf_hashsize; | ||||
static u_long pf_srchashsize; | static u_long pf_srchashsize; | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | pf_hashkey(struct pf_state_key *sk) | ||||
h = murmur3_32_hash32((uint32_t *)sk, | h = murmur3_32_hash32((uint32_t *)sk, | ||||
sizeof(struct pf_state_key_cmp)/sizeof(uint32_t), | sizeof(struct pf_state_key_cmp)/sizeof(uint32_t), | ||||
V_pf_hashseed); | V_pf_hashseed); | ||||
return (h & pf_hashmask); | return (h & pf_hashmask); | ||||
} | } | ||||
static inline uint32_t | |||||
pf_hashudpendpoint(struct pf_udp_endpoint *endpoint) | |||||
{ | |||||
uint32_t h; | |||||
h = murmur3_32_hash32((uint32_t *)endpoint, | |||||
sizeof(struct pf_udp_endpoint_cmp)/sizeof(uint32_t), | |||||
V_pf_hashseed); | |||||
return (h & pf_hashmask); | |||||
} | |||||
static __inline uint32_t | static __inline uint32_t | ||||
pf_hashsrc(struct pf_addr *addr, sa_family_t af) | pf_hashsrc(struct pf_addr *addr, sa_family_t af) | ||||
{ | { | ||||
uint32_t h; | uint32_t h; | ||||
switch (af) { | switch (af) { | ||||
case AF_INET: | case AF_INET: | ||||
h = murmur3_32_hash32((uint32_t *)&addr->v4, | h = murmur3_32_hash32((uint32_t *)&addr->v4, | ||||
sizeof(addr->v4)/sizeof(uint32_t), V_pf_hashseed); | sizeof(addr->v4)/sizeof(uint32_t), V_pf_hashseed); | ||||
break; | break; | ||||
case AF_INET6: | case AF_INET6: | ||||
h = murmur3_32_hash32((uint32_t *)&addr->v6, | h = murmur3_32_hash32((uint32_t *)&addr->v6, | ||||
sizeof(addr->v6)/sizeof(uint32_t), V_pf_hashseed); | sizeof(addr->v6)/sizeof(uint32_t), V_pf_hashseed); | ||||
glebius: Please use standard C keyword "inline" instead of "__inline" gcc-ism. | |||||
break; | break; | ||||
default: | default: | ||||
panic("%s: unknown address family %u", __func__, af); | panic("%s: unknown address family %u", __func__, af); | ||||
} | } | ||||
return (h & pf_srchashmask); | return (h & pf_srchashmask); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 325 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* Per-vnet data storage structures initialization. */ | /* Per-vnet data storage structures initialization. */ | ||||
void | void | ||||
pf_initialize() | pf_initialize() | ||||
{ | { | ||||
struct pf_keyhash *kh; | struct pf_keyhash *kh; | ||||
struct pf_idhash *ih; | struct pf_idhash *ih; | ||||
struct pf_udpendpointhash *uh; | |||||
struct pf_srchash *sh; | struct pf_srchash *sh; | ||||
u_int i; | u_int i; | ||||
if (pf_hashsize == 0 || !powerof2(pf_hashsize)) | if (pf_hashsize == 0 || !powerof2(pf_hashsize)) | ||||
pf_hashsize = PF_HASHSIZ; | pf_hashsize = PF_HASHSIZ; | ||||
if (pf_srchashsize == 0 || !powerof2(pf_srchashsize)) | if (pf_srchashsize == 0 || !powerof2(pf_srchashsize)) | ||||
pf_srchashsize = PF_HASHSIZ / 4; | pf_srchashsize = PF_HASHSIZ / 4; | ||||
V_pf_hashseed = arc4random(); | V_pf_hashseed = arc4random(); | ||||
/* States and state keys storage. */ | /* States and state keys storage. */ | ||||
V_pf_state_z = uma_zcreate("pf states", sizeof(struct pf_state), | V_pf_state_z = uma_zcreate("pf states", sizeof(struct pf_state), | ||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); | NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); | ||||
V_pf_limits[PF_LIMIT_STATES].zone = V_pf_state_z; | V_pf_limits[PF_LIMIT_STATES].zone = V_pf_state_z; | ||||
uma_zone_set_max(V_pf_state_z, PFSTATE_HIWAT); | uma_zone_set_max(V_pf_state_z, PFSTATE_HIWAT); | ||||
uma_zone_set_warning(V_pf_state_z, "PF states limit reached"); | uma_zone_set_warning(V_pf_state_z, "PF states limit reached"); | ||||
V_pf_state_key_z = uma_zcreate("pf state keys", | V_pf_state_key_z = uma_zcreate("pf state keys", | ||||
sizeof(struct pf_state_key), pf_state_key_ctor, NULL, NULL, NULL, | sizeof(struct pf_state_key), pf_state_key_ctor, NULL, NULL, NULL, | ||||
UMA_ALIGN_PTR, 0); | UMA_ALIGN_PTR, 0); | ||||
V_pf_udp_mapping_z = uma_zcreate("pf UDP mappings", | |||||
sizeof(struct pf_udp_mapping), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); | |||||
V_pf_keyhash = malloc(pf_hashsize * sizeof(struct pf_keyhash), | V_pf_keyhash = malloc(pf_hashsize * sizeof(struct pf_keyhash), | ||||
M_PFHASH, M_WAITOK | M_ZERO); | M_PFHASH, M_WAITOK | M_ZERO); | ||||
V_pf_idhash = malloc(pf_hashsize * sizeof(struct pf_idhash), | V_pf_idhash = malloc(pf_hashsize * sizeof(struct pf_idhash), | ||||
M_PFHASH, M_WAITOK | M_ZERO); | M_PFHASH, M_WAITOK | M_ZERO); | ||||
V_pf_udpendpointhash = malloc(pf_hashsize * sizeof(struct pf_udpendpointhash), | |||||
M_PFHASH, M_WAITOK | M_ZERO); | |||||
pf_hashmask = pf_hashsize - 1; | pf_hashmask = pf_hashsize - 1; | ||||
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, uh=V_pf_udpendpointhash; i <= pf_hashmask; | ||||
i++, kh++, ih++) { | i++, kh++, ih++, uh++) { | ||||
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); | ||||
mtx_init(&uh->lock, "pf_udpendpointhash", NULL, MTX_DEF | MTX_DUPOK); | |||||
} | } | ||||
/* 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_src_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); | ||||
Show All 27 Lines | pf_mtag_cleanup() | ||||
uma_zdestroy(pf_mtag_z); | uma_zdestroy(pf_mtag_z); | ||||
} | } | ||||
void | void | ||||
pf_cleanup() | pf_cleanup() | ||||
{ | { | ||||
struct pf_keyhash *kh; | struct pf_keyhash *kh; | ||||
struct pf_idhash *ih; | struct pf_idhash *ih; | ||||
struct pf_udpendpointhash *uh; | |||||
struct pf_srchash *sh; | struct pf_srchash *sh; | ||||
struct pf_send_entry *pfse, *next; | struct pf_send_entry *pfse, *next; | ||||
u_int i; | u_int i; | ||||
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, uh=V_pf_udpendpointhash; i <= pf_hashmask; | ||||
i++, kh++, ih++) { | i++, kh++, ih++, uh++) { | ||||
KASSERT(LIST_EMPTY(&kh->keys), ("%s: key hash not empty", | KASSERT(LIST_EMPTY(&kh->keys), ("%s: key hash not empty", | ||||
__func__)); | __func__)); | ||||
KASSERT(LIST_EMPTY(&ih->states), ("%s: id hash not empty", | KASSERT(LIST_EMPTY(&ih->states), ("%s: id hash not empty", | ||||
__func__)); | __func__)); | ||||
KASSERT(LIST_EMPTY(&uh->endpoints), ("%s: udpendpoint hash not empty", | |||||
__func__)); | |||||
mtx_destroy(&kh->lock); | mtx_destroy(&kh->lock); | ||||
mtx_destroy(&ih->lock); | mtx_destroy(&ih->lock); | ||||
mtx_destroy(&uh->lock); | |||||
} | } | ||||
free(V_pf_keyhash, M_PFHASH); | free(V_pf_keyhash, M_PFHASH); | ||||
free(V_pf_idhash, M_PFHASH); | free(V_pf_idhash, M_PFHASH); | ||||
free(V_pf_udpendpointhash, M_PFHASH); | |||||
for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask; i++, sh++) { | for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask; i++, sh++) { | ||||
KASSERT(LIST_EMPTY(&sh->nodes), | KASSERT(LIST_EMPTY(&sh->nodes), | ||||
("%s: source node hash not empty", __func__)); | ("%s: source node hash not empty", __func__)); | ||||
mtx_destroy(&sh->lock); | mtx_destroy(&sh->lock); | ||||
} | } | ||||
free(V_pf_srchash, M_PFHASH); | free(V_pf_srchash, M_PFHASH); | ||||
STAILQ_FOREACH_SAFE(pfse, &V_pf_sendqueue, pfse_next, next) { | STAILQ_FOREACH_SAFE(pfse, &V_pf_sendqueue, pfse_next, next) { | ||||
m_freem(pfse->pfse_m); | m_freem(pfse->pfse_m); | ||||
free(pfse, M_PFTEMP); | free(pfse, M_PFTEMP); | ||||
} | } | ||||
uma_zdestroy(V_pf_sources_z); | uma_zdestroy(V_pf_sources_z); | ||||
uma_zdestroy(V_pf_state_z); | uma_zdestroy(V_pf_state_z); | ||||
uma_zdestroy(V_pf_state_key_z); | uma_zdestroy(V_pf_state_key_z); | ||||
uma_zdestroy(V_pf_udp_mapping_z); | |||||
} | } | ||||
static int | static int | ||||
pf_mtag_uminit(void *mem, int size, int how) | pf_mtag_uminit(void *mem, int size, int how) | ||||
{ | { | ||||
struct m_tag *t; | struct m_tag *t; | ||||
t = (struct m_tag *)mem; | t = (struct m_tag *)mem; | ||||
▲ Show 20 Lines • Show All 471 Lines • ▼ Show 20 Lines | if (inout == 1) { | ||||
idx = PF_SK_STACK; | idx = PF_SK_STACK; | ||||
goto second_run; | goto second_run; | ||||
} | } | ||||
PF_HASHROW_UNLOCK(kh); | PF_HASHROW_UNLOCK(kh); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
struct pf_udp_mapping* | |||||
pf_udp_mapping_create(sa_family_t af, struct pf_addr *src_addr, uint16_t src_port, | |||||
struct pf_addr *nat_addr, uint16_t nat_port) | |||||
{ | |||||
struct pf_udp_mapping *mapping; | |||||
Not Done Inline ActionsPlease follow style(9), do not initialize variables in declaration. They rule may be violated sometimes, but calling function in initializer is too much! glebius: Please follow style(9), do not initialize variables in declaration. They rule may be violated… | |||||
mapping = uma_zalloc(V_pf_udp_mapping_z, M_NOWAIT | M_ZERO); | |||||
if (mapping == NULL) | |||||
return NULL; | |||||
PF_ACPY(&mapping->endpoints[0].addr, src_addr, af); | |||||
mapping->endpoints[0].port = src_port; | |||||
mapping->endpoints[0].af = af; | |||||
mapping->endpoints[0].mapping = mapping; | |||||
PF_ACPY(&mapping->endpoints[1].addr, nat_addr, af); | |||||
mapping->endpoints[1].port = nat_port; | |||||
mapping->endpoints[1].af = af; | |||||
mapping->endpoints[1].mapping = mapping; | |||||
Not Done Inline ActionsPlease put return values into braces, to follow style(9). This refers to all new returns in this patch. glebius: Please put return values into braces, to follow style(9). This refers to all new returns in… | |||||
refcount_init(&mapping->refs, 1); | |||||
return (mapping); | |||||
} | |||||
int | |||||
pf_udp_mapping_insert(struct pf_udp_mapping *mapping) | |||||
{ | |||||
struct pf_udpendpointhash *h0, *h1; | |||||
struct pf_udp_endpoint *endpoint; | |||||
int ret = 1; | |||||
h0 = &V_pf_udpendpointhash[pf_hashudpendpoint(&mapping->endpoints[0])]; | |||||
h1 = &V_pf_udpendpointhash[pf_hashudpendpoint(&mapping->endpoints[1])]; | |||||
if (h0 == h1) { | |||||
PF_HASHROW_LOCK(h0); | |||||
} else if (h0 < h1) { | |||||
PF_HASHROW_LOCK(h0); | |||||
PF_HASHROW_LOCK(h1); | |||||
} else { | |||||
PF_HASHROW_LOCK(h1); | |||||
PF_HASHROW_LOCK(h0); | |||||
} | |||||
LIST_FOREACH(endpoint, &h0->endpoints, entry) | |||||
if (bcmp(endpoint, &mapping->endpoints[0], sizeof(struct pf_udp_endpoint_cmp)) == 0) | |||||
break; | |||||
if (endpoint != NULL) | |||||
goto cleanup; | |||||
LIST_FOREACH(endpoint, &h1->endpoints, entry) | |||||
if (bcmp(endpoint, &mapping->endpoints[1], sizeof(struct pf_udp_endpoint_cmp)) == 0) | |||||
break; | |||||
if (endpoint != NULL) | |||||
goto cleanup; | |||||
LIST_INSERT_HEAD(&h0->endpoints, &mapping->endpoints[0], entry); | |||||
LIST_INSERT_HEAD(&h1->endpoints, &mapping->endpoints[1], entry); | |||||
ret = 0; | |||||
cleanup: | |||||
if (h0 != h1) { | |||||
PF_HASHROW_UNLOCK(h0); | |||||
PF_HASHROW_UNLOCK(h1); | |||||
} else { | |||||
PF_HASHROW_UNLOCK(h0); | |||||
} | |||||
return (ret); | |||||
} | |||||
void | |||||
pf_udp_mapping_release(struct pf_udp_mapping *mapping) | |||||
{ | |||||
/* refcount is synchronized on the source endpoint's row lock */ | |||||
Not Done Inline ActionsPlease put empty line after declarations. glebius: Please put empty line after declarations. | |||||
struct pf_udpendpointhash *h0, *h1; | |||||
h0 = &V_pf_udpendpointhash[pf_hashudpendpoint(&mapping->endpoints[0])]; | |||||
PF_HASHROW_LOCK(h0); | |||||
if (refcount_release(&mapping->refs)) { | |||||
LIST_REMOVE(&mapping->endpoints[0], entry); | |||||
PF_HASHROW_UNLOCK(h0); | |||||
h1 = &V_pf_udpendpointhash[pf_hashudpendpoint(&mapping->endpoints[1])]; | |||||
PF_HASHROW_LOCK(h1); | |||||
LIST_REMOVE(&mapping->endpoints[1], entry); | |||||
PF_HASHROW_UNLOCK(h1); | |||||
uma_zfree(V_pf_udp_mapping_z, mapping); | |||||
} else { | |||||
PF_HASHROW_UNLOCK(h0); | |||||
} | |||||
} | |||||
struct pf_udp_mapping * | |||||
pf_udp_mapping_find(struct pf_udp_endpoint_cmp *key) | |||||
{ | |||||
struct pf_udpendpointhash *uh; | |||||
struct pf_udp_endpoint *endpoint; | |||||
uh = &V_pf_udpendpointhash[pf_hashudpendpoint((struct pf_udp_endpoint*)key)]; | |||||
PF_HASHROW_LOCK(uh); | |||||
LIST_FOREACH(endpoint, &uh->endpoints, entry) | |||||
if (bcmp(endpoint, key, sizeof(struct pf_udp_endpoint_cmp)) == 0 && | |||||
bcmp(endpoint, &endpoint->mapping->endpoints[0], sizeof(struct pf_udp_endpoint_cmp)) == 0) | |||||
break; | |||||
if (endpoint == NULL) { | |||||
PF_HASHROW_UNLOCK(uh); | |||||
return NULL; | |||||
} | |||||
refcount_acquire(&endpoint->mapping->refs); | |||||
PF_HASHROW_UNLOCK(uh); | |||||
return (endpoint->mapping); | |||||
} | |||||
/* END state table stuff */ | /* END state table stuff */ | ||||
static void | static void | ||||
pf_send(struct pf_send_entry *pfse) | pf_send(struct pf_send_entry *pfse) | ||||
{ | { | ||||
PF_SENDQ_LOCK(); | PF_SENDQ_LOCK(); | ||||
STAILQ_INSERT_TAIL(&V_pf_sendqueue, pfse, pfse_next); | STAILQ_INSERT_TAIL(&V_pf_sendqueue, pfse, pfse_next); | ||||
▲ Show 20 Lines • Show All 265 Lines • ▼ Show 20 Lines | pf_unlink_state(struct pf_state *s, u_int flags) | ||||
s->timeout = PFTM_UNLINKED; | s->timeout = PFTM_UNLINKED; | ||||
PF_HASHROW_UNLOCK(ih); | PF_HASHROW_UNLOCK(ih); | ||||
pf_detach_state(s); | pf_detach_state(s); | ||||
refcount_release(&s->refs); | refcount_release(&s->refs); | ||||
if (s->udp_mapping) | |||||
pf_udp_mapping_release(s->udp_mapping); | |||||
return (pf_release_state(s)); | return (pf_release_state(s)); | ||||
} | } | ||||
void | void | ||||
pf_free_state(struct pf_state *cur) | pf_free_state(struct pf_state *cur) | ||||
{ | { | ||||
KASSERT(cur->refs == 0, ("%s: %p has refs", __func__, cur)); | KASSERT(cur->refs == 0, ("%s: %p has refs", __func__, cur)); | ||||
▲ Show 20 Lines • Show All 1,470 Lines • ▼ Show 20 Lines | pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, | ||||
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; | ||||
u_int16_t sport = 0, dport = 0; | u_int16_t sport = 0, dport = 0; | ||||
u_int16_t bproto_sum = 0, bip_sum = 0; | u_int16_t bproto_sum = 0, bip_sum = 0; | ||||
u_int8_t icmptype = 0, icmpcode = 0; | u_int8_t icmptype = 0, icmpcode = 0; | ||||
struct pf_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE]; | struct pf_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE]; | ||||
struct pf_udp_mapping *udp_mapping = NULL; | |||||
PF_RULES_RASSERT(); | PF_RULES_RASSERT(); | ||||
if (inp != NULL) { | if (inp != NULL) { | ||||
INP_LOCK_ASSERT(inp); | INP_LOCK_ASSERT(inp); | ||||
pd->lookup.uid = inp->inp_cred->cr_uid; | pd->lookup.uid = inp->inp_cred->cr_uid; | ||||
pd->lookup.gid = inp->inp_cred->cr_groups[0]; | pd->lookup.gid = inp->inp_cred->cr_groups[0]; | ||||
pd->lookup.done = 1; | pd->lookup.done = 1; | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | default: | ||||
sport = dport = hdrlen = 0; | sport = dport = hdrlen = 0; | ||||
break; | break; | ||||
} | } | ||||
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); | r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); | ||||
/* check packet for BINAT/NAT/RDR */ | /* check packet for BINAT/NAT/RDR */ | ||||
if ((nr = pf_get_translation(pd, m, off, direction, kif, &nsn, &sk, | if ((nr = pf_get_translation(pd, m, off, direction, kif, &nsn, &sk, | ||||
&nk, saddr, daddr, sport, dport, anchor_stack)) != NULL) { | &nk, saddr, daddr, sport, dport, anchor_stack, &udp_mapping)) != NULL) { | ||||
KASSERT(sk != NULL, ("%s: null sk", __func__)); | KASSERT(sk != NULL, ("%s: null sk", __func__)); | ||||
KASSERT(nk != NULL, ("%s: null nk", __func__)); | KASSERT(nk != NULL, ("%s: null nk", __func__)); | ||||
if (pd->ip_sum) | if (pd->ip_sum) | ||||
bip_sum = *pd->ip_sum; | bip_sum = *pd->ip_sum; | ||||
switch (pd->proto) { | switch (pd->proto) { | ||||
case IPPROTO_TCP: | case IPPROTO_TCP: | ||||
▲ Show 20 Lines • Show All 290 Lines • ▼ Show 20 Lines | #endif | ||||
if (rtableid >= 0) | if (rtableid >= 0) | ||||
M_SETFIB(m, rtableid); | M_SETFIB(m, rtableid); | ||||
if (!state_icmp && (r->keep_state || nr != NULL || | if (!state_icmp && (r->keep_state || nr != NULL || | ||||
(pd->flags & PFDESC_TCP_NORM))) { | (pd->flags & PFDESC_TCP_NORM))) { | ||||
int action; | int action; | ||||
action = pf_create_state(r, nr, a, pd, nsn, nk, sk, m, off, | action = pf_create_state(r, nr, a, pd, nsn, nk, sk, m, off, | ||||
sport, dport, &rewrite, kif, sm, tag, bproto_sum, bip_sum, | sport, dport, &rewrite, kif, sm, tag, bproto_sum, bip_sum, | ||||
hdrlen); | hdrlen, udp_mapping); | ||||
if (action != PF_PASS) | if (action != PF_PASS) { | ||||
if (udp_mapping != NULL) | |||||
pf_udp_mapping_release(udp_mapping); | |||||
return (action); | return (action); | ||||
} | |||||
} else { | } else { | ||||
if (sk != NULL) | 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); | ||||
if (udp_mapping != NULL) | |||||
pf_udp_mapping_release(udp_mapping); | |||||
} | } | ||||
/* copy back packet headers if we performed NAT operations */ | /* copy back packet headers if we performed NAT operations */ | ||||
if (rewrite) | if (rewrite) | ||||
m_copyback(m, off, hdrlen, pd->hdr.any); | m_copyback(m, off, hdrlen, pd->hdr.any); | ||||
if (*sm != NULL && !((*sm)->state_flags & PFSTATE_NOSYNC) && | if (*sm != NULL && !((*sm)->state_flags & PFSTATE_NOSYNC) && | ||||
direction == PF_OUT && | direction == PF_OUT && | ||||
pfsync_defer_ptr != NULL && pfsync_defer_ptr(*sm, m)) | pfsync_defer_ptr != NULL && pfsync_defer_ptr(*sm, m)) | ||||
/* | /* | ||||
* We want the state created, but we dont | * We want the state created, but we dont | ||||
* want to send this in case a partner | * want to send this in case a partner | ||||
* firewall has to know about it to allow | * firewall has to know about it to allow | ||||
* replies through it. | * replies through it. | ||||
*/ | */ | ||||
return (PF_DEFER); | return (PF_DEFER); | ||||
return (PF_PASS); | return (PF_PASS); | ||||
cleanup: | cleanup: | ||||
if (sk != NULL) | 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); | ||||
if (udp_mapping != NULL) | |||||
pf_udp_mapping_release(udp_mapping); | |||||
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_src_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_udp_mapping *udp_mapping) | |||||
{ | { | ||||
struct pf_state *s = NULL; | struct pf_state *s = NULL; | ||||
struct pf_src_node *sn = NULL; | struct pf_src_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 */ | ||||
▲ Show 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | if (pd->proto == IPPROTO_TCP && (th->th_flags & (TH_SYN|TH_ACK)) == | ||||
mss = pf_calc_mss(pd->dst, pd->af, rtid, mss); | mss = pf_calc_mss(pd->dst, pd->af, rtid, mss); | ||||
s->src.mss = mss; | s->src.mss = mss; | ||||
pf_send_tcp(NULL, r, pd->af, pd->dst, pd->src, th->th_dport, | pf_send_tcp(NULL, r, pd->af, pd->dst, pd->src, th->th_dport, | ||||
th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1, | th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1, | ||||
TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL); | TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL); | ||||
REASON_SET(&reason, PFRES_SYNPROXY); | REASON_SET(&reason, PFRES_SYNPROXY); | ||||
return (PF_SYNPROXY_DROP); | return (PF_SYNPROXY_DROP); | ||||
} | } | ||||
s->udp_mapping = udp_mapping; | |||||
return (PF_PASS); | return (PF_PASS); | ||||
csfailed: | csfailed: | ||||
if (sk != NULL) | 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); | ||||
▲ Show 20 Lines • Show All 2,871 Lines • Show Last 20 Lines |
Please use standard C keyword "inline" instead of "__inline" gcc-ism.