FreeBSD Bugzilla – Attachment 183243 Details for
Bug 219803
[patch] PF: implement RFC 4787 REQ 1 and 3 (full cone NAT)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
pf RFC 4787 req 1 and 3 implementation
pf-rfc4787.patch (text/plain), 18.40 KB, created by
Damjan Jovanovic
on 2017-06-05 17:48:30 UTC
(
hide
)
Description:
pf RFC 4787 req 1 and 3 implementation
Filename:
MIME Type:
Creator:
Damjan Jovanovic
Created:
2017-06-05 17:48:30 UTC
Size:
18.40 KB
patch
obsolete
>diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h >index c5e8567..5b6664b 100644 >--- a/sys/net/pfvar.h >+++ b/sys/net/pfvar.h >@@ -683,6 +683,29 @@ struct pf_state_peer { > u_int8_t pad[1]; > }; > >+/* Keep synced with struct pf_udp_endpoint. */ >+struct pf_udp_endpoint_cmp { >+ struct pf_addr addr; >+ u_int16_t port; >+ sa_family_t af; >+ u_int8_t pad[1]; >+}; >+ >+struct pf_udp_endpoint { >+ struct pf_addr addr; >+ u_int16_t port; >+ sa_family_t af; >+ u_int8_t pad[1]; >+ >+ struct pf_udp_mapping *mapping; >+ LIST_ENTRY(pf_udp_endpoint) entry; >+}; >+ >+struct pf_udp_mapping { >+ struct pf_udp_endpoint endpoints[2]; >+ u_int refs; >+}; >+ > /* Keep synced with struct pf_state_key. */ > struct pf_state_key_cmp { > struct pf_addr addr[2]; >@@ -728,6 +751,7 @@ struct pf_state { > union pf_rule_ptr nat_rule; > struct pf_addr rt_addr; > struct pf_state_key *key[2]; /* addresses stack and wire */ >+ struct pf_udp_mapping *udp_mapping; > struct pfi_kif *kif; > struct pfi_kif *rt_kif; > struct pf_src_node *src_node; >@@ -1452,6 +1476,11 @@ struct pf_srchash { > struct mtx lock; > }; > >+struct pf_udpendpointhash { >+ LIST_HEAD(, pf_udp_endpoint) endpoints; >+ struct mtx lock; >+}; >+ > struct pf_keyhash { > LIST_HEAD(, pf_state_key) keys; > struct mtx lock; >@@ -1465,8 +1494,10 @@ struct pf_idhash { > extern u_long pf_hashmask; > extern u_long pf_srchashmask; > #define PF_HASHSIZ (32768) >+VNET_DECLARE(struct pf_udpendpointhash *, pf_udpendpointhash); > VNET_DECLARE(struct pf_keyhash *, pf_keyhash); > VNET_DECLARE(struct pf_idhash *, pf_idhash); >+#define V_pf_udpendpointhash VNET(pf_udpendpointhash) > #define V_pf_keyhash VNET(pf_keyhash) > #define V_pf_idhash VNET(pf_idhash) > VNET_DECLARE(struct pf_srchash *, pf_srchash); >@@ -1517,6 +1548,8 @@ VNET_DECLARE(uma_zone_t, pf_state_z); > #define V_pf_state_z VNET(pf_state_z) > VNET_DECLARE(uma_zone_t, pf_state_key_z); > #define V_pf_state_key_z VNET(pf_state_key_z) >+VNET_DECLARE(uma_zone_t, pf_udp_mapping_z); >+#define V_pf_udp_mapping_z VNET(pf_udp_mapping_z) > VNET_DECLARE(uma_zone_t, pf_state_scrub_z); > #define V_pf_state_scrub_z VNET(pf_state_scrub_z) > >@@ -1555,6 +1588,14 @@ pf_release_state(struct pf_state *s) > extern struct pf_state *pf_find_state_byid(uint64_t, uint32_t); > extern struct pf_state *pf_find_state_all(struct pf_state_key_cmp *, > u_int, int *); >+extern struct pf_udp_mapping *pf_udp_mapping_find(struct pf_udp_endpoint_cmp *endpoint); >+extern struct pf_udp_mapping *pf_udp_mapping_create(sa_family_t af, >+ struct pf_addr *src_addr, u_int16_t src_port, >+ struct pf_addr *nat_addr, u_int16_t nat_port); >+extern int pf_udp_mapping_insert(struct pf_udp_mapping *mapping); >+extern void pf_udp_mapping_release(struct pf_udp_mapping *mapping); >+ >+ > extern struct pf_src_node *pf_find_src_node(struct pf_addr *, > struct pf_rule *, sa_family_t, int); > extern void pf_unlink_src_node(struct pf_src_node *); >@@ -1749,7 +1790,8 @@ struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *, > int, int, struct pfi_kif *, struct pf_src_node **, > struct pf_state_key **, struct pf_state_key **, > struct pf_addr *, struct pf_addr *, >- uint16_t, uint16_t, struct pf_anchor_stackframe *); >+ uint16_t, uint16_t, struct pf_anchor_stackframe *, >+ struct pf_udp_mapping **udp_mapping); > > struct pf_state_key *pf_state_key_setup(struct pf_pdesc *, struct pf_addr *, > struct pf_addr *, u_int16_t, u_int16_t); >diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c >index 7d6c53d..9bd9b11 100644 >--- a/sys/netpfil/pf/pf.c >+++ b/sys/netpfil/pf/pf.c >@@ -194,6 +194,7 @@ static VNET_DEFINE(uma_zone_t, pf_sources_z); > uma_zone_t pf_mtag_z; > VNET_DEFINE(uma_zone_t, pf_state_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]); > #define PFID_CPUBITS 8 >@@ -241,7 +242,7 @@ static int pf_create_state(struct pf_rule *, struct pf_rule *, > struct pf_state_key *, struct mbuf *, int, > u_int16_t, u_int16_t, int *, struct pfi_kif *, > 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, > struct pfi_kif *, struct mbuf *, void *, > struct pf_pdesc *, struct pf_rule **, >@@ -356,6 +357,7 @@ static MALLOC_DEFINE(M_PFHASH, "pf_hash", "pf(4) hash header structures"); > VNET_DEFINE(struct pf_keyhash *, pf_keyhash); > VNET_DEFINE(struct pf_idhash *, pf_idhash); > 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)"); > >@@ -426,6 +428,18 @@ pf_hashkey(struct pf_state_key *sk) > } > > 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 > pf_hashsrc(struct pf_addr *addr, sa_family_t af) > { > uint32_t h; >@@ -779,6 +793,7 @@ pf_initialize() > { > struct pf_keyhash *kh; > struct pf_idhash *ih; >+ struct pf_udpendpointhash *uh; > struct pf_srchash *sh; > u_int i; > >@@ -799,15 +814,20 @@ pf_initialize() > V_pf_state_key_z = uma_zcreate("pf state keys", > sizeof(struct pf_state_key), pf_state_key_ctor, NULL, NULL, NULL, > 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), > M_PFHASH, M_WAITOK | M_ZERO); > V_pf_idhash = malloc(pf_hashsize * sizeof(struct pf_idhash), > 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; >- for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash; i <= pf_hashmask; >- i++, kh++, ih++) { >+ for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash, uh=V_pf_udpendpointhash; i <= pf_hashmask; >+ i++, kh++, ih++, uh++) { > mtx_init(&kh->lock, "pf_keyhash", NULL, MTX_DEF | MTX_DUPOK); > mtx_init(&ih->lock, "pf_idhash", NULL, MTX_DEF); >+ mtx_init(&uh->lock, "pf_udpendpointhash", NULL, MTX_DEF | MTX_DUPOK); > } > > /* Source nodes. */ >@@ -851,21 +871,26 @@ pf_cleanup() > { > struct pf_keyhash *kh; > struct pf_idhash *ih; >+ struct pf_udpendpointhash *uh; > struct pf_srchash *sh; > struct pf_send_entry *pfse, *next; > u_int i; > >- for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash; i <= pf_hashmask; >- i++, kh++, ih++) { >+ for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash, uh=V_pf_udpendpointhash; i <= pf_hashmask; >+ i++, kh++, ih++, uh++) { > KASSERT(LIST_EMPTY(&kh->keys), ("%s: key hash not empty", > __func__)); > KASSERT(LIST_EMPTY(&ih->states), ("%s: id hash not empty", > __func__)); >+ KASSERT(LIST_EMPTY(&uh->endpoints), ("%s: udpendpoint hash not empty", >+ __func__)); > mtx_destroy(&kh->lock); > mtx_destroy(&ih->lock); >+ mtx_destroy(&uh->lock); > } > free(V_pf_keyhash, 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++) { > KASSERT(LIST_EMPTY(&sh->nodes), >@@ -882,6 +907,7 @@ pf_cleanup() > uma_zdestroy(V_pf_sources_z); > uma_zdestroy(V_pf_state_z); > uma_zdestroy(V_pf_state_key_z); >+ uma_zdestroy(V_pf_udp_mapping_z); > } > > static int >@@ -1369,6 +1395,111 @@ second_run: > return (ret); > } > >+struct pf_udp_mapping* >+pf_udp_mapping_create(sa_family_t af, struct pf_addr *src_addr, u_int16_t src_port, >+ struct pf_addr *nat_addr, u_int16_t nat_port) >+{ >+ struct pf_udp_mapping *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; >+ 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 */ >+ 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 */ > > static void >@@ -1650,6 +1781,9 @@ pf_unlink_state(struct pf_state *s, u_int flags) > pf_detach_state(s); > refcount_release(&s->refs); > >+ if (s->udp_mapping) >+ pf_udp_mapping_release(s->udp_mapping); >+ > return (pf_release_state(s)); > } > >@@ -3136,6 +3270,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, > u_int16_t bproto_sum = 0, bip_sum = 0; > u_int8_t icmptype = 0, icmpcode = 0; > struct pf_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE]; >+ struct pf_udp_mapping *udp_mapping = NULL; > > PF_RULES_RASSERT(); > >@@ -3199,7 +3334,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, > > /* check packet for BINAT/NAT/RDR */ > 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(nk != NULL, ("%s: null nk", __func__)); > >@@ -3506,14 +3641,19 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, > int action; > action = pf_create_state(r, nr, a, pd, nsn, nk, sk, m, off, > sport, dport, &rewrite, kif, sm, tag, bproto_sum, bip_sum, >- hdrlen); >- if (action != PF_PASS) >+ hdrlen, udp_mapping); >+ if (action != PF_PASS) { >+ if (udp_mapping != NULL) >+ pf_udp_mapping_release(udp_mapping); > return (action); >+ } > } else { > if (sk != NULL) > uma_zfree(V_pf_state_key_z, sk); > if (nk != NULL) > 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 */ >@@ -3538,6 +3678,8 @@ cleanup: > uma_zfree(V_pf_state_key_z, sk); > if (nk != NULL) > uma_zfree(V_pf_state_key_z, nk); >+ if (udp_mapping != NULL) >+ pf_udp_mapping_release(udp_mapping); > return (PF_DROP); > } > >@@ -3546,7 +3688,8 @@ 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_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, >- 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_src_node *sn = NULL; >@@ -3752,6 +3895,7 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a, > REASON_SET(&reason, PFRES_SYNPROXY); > return (PF_SYNPROXY_DROP); > } >+ s->udp_mapping = udp_mapping; > > return (PF_PASS); > >diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c >index eac5317..aae40ab 100644 >--- a/sys/netpfil/pf/pf_lb.c >+++ b/sys/netpfil/pf/pf_lb.c >@@ -63,7 +63,8 @@ static struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *, > uint16_t, int, struct pf_anchor_stackframe *); > static int pf_get_sport(sa_family_t, uint8_t, struct pf_rule *, > struct pf_addr *, uint16_t, struct pf_addr *, uint16_t, struct pf_addr *, >- uint16_t *, uint16_t, uint16_t, struct pf_src_node **); >+ uint16_t *, uint16_t, uint16_t, struct pf_src_node **, >+ struct pf_udp_mapping**); > > #define mix(a,b,c) \ > do { \ >@@ -214,14 +215,36 @@ static int > pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, > struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr, > uint16_t dport, struct pf_addr *naddr, uint16_t *nport, uint16_t low, >- uint16_t high, struct pf_src_node **sn) >+ uint16_t high, struct pf_src_node **sn, struct pf_udp_mapping **udp_mapping) > { > struct pf_state_key_cmp key; > struct pf_addr init_addr; > >+ if (proto == IPPROTO_UDP) { >+ struct pf_udp_endpoint_cmp udp_source; >+ bzero(&udp_source, sizeof(udp_source)); >+ udp_source.af = af; >+ PF_ACPY(&udp_source.addr, saddr, af); >+ udp_source.port = sport; >+ *udp_mapping = pf_udp_mapping_find(&udp_source); >+ if (*udp_mapping) { >+ PF_ACPY(naddr, &(*udp_mapping)->endpoints[1].addr, af); >+ *nport = (*udp_mapping)->endpoints[1].port; >+ /* as per pf_map_addr(): */ >+ if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR && >+ (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) >+ *sn = pf_find_src_node(saddr, r, af, 0); >+ return (0); >+ } else { >+ *udp_mapping = pf_udp_mapping_create(af, saddr, sport, &init_addr, 0); >+ if (*udp_mapping == NULL) >+ return (1); >+ } >+ } >+ > bzero(&init_addr, sizeof(init_addr)); > if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) >- return (1); >+ goto failed; > > if (proto == IPPROTO_ICMP) { > low = 1; >@@ -236,6 +259,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, > > do { > PF_ACPY(&key.addr[1], naddr, key.af); >+ PF_ACPY(&(*udp_mapping)->endpoints[1].addr, naddr, af); > > /* > * port search; start random, step; >@@ -255,8 +279,16 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, > } else if (low == high) { > key.port[1] = htons(low); > if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { >- *nport = htons(low); >- return (0); >+ if (proto == IPPROTO_UDP) { >+ (*udp_mapping)->endpoints[1].port = htons(low); >+ if (pf_udp_mapping_insert(*udp_mapping) == 0) { >+ *nport = htons(low); >+ return (0); >+ } >+ } else { >+ *nport = htons(low); >+ return (0); >+ } > } > } else { > uint16_t tmp, cut; >@@ -270,19 +302,35 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, > cut = arc4random() % (1 + high - low) + low; > /* low <= cut <= high */ > for (tmp = cut; tmp <= high; ++(tmp)) { >- key.port[1] = htons(tmp); >- if (pf_find_state_all(&key, PF_IN, NULL) == >- NULL) { >- *nport = htons(tmp); >- return (0); >+ if (proto == IPPROTO_UDP) { >+ (*udp_mapping)->endpoints[1].port = htons(tmp); >+ if (pf_udp_mapping_insert(*udp_mapping) == 0) { >+ *nport = htons(tmp); >+ return (0); >+ } >+ } else { >+ key.port[1] = htons(tmp); >+ if (pf_find_state_all(&key, PF_IN, NULL) == >+ NULL) { >+ *nport = htons(tmp); >+ return (0); >+ } > } > } > for (tmp = cut - 1; tmp >= low; --(tmp)) { >- key.port[1] = htons(tmp); >- if (pf_find_state_all(&key, PF_IN, NULL) == >- NULL) { >- *nport = htons(tmp); >- return (0); >+ if (proto == IPPROTO_UDP) { >+ (*udp_mapping)->endpoints[1].port = htons(tmp); >+ if (pf_udp_mapping_insert(*udp_mapping) == 0) { >+ *nport = htons(tmp); >+ return (0); >+ } >+ } else { >+ key.port[1] = htons(tmp); >+ if (pf_find_state_all(&key, PF_IN, NULL) == >+ NULL) { >+ *nport = htons(tmp); >+ return (0); >+ } > } > } > } >@@ -300,7 +348,13 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, > return (1); > } > } while (! PF_AEQ(&init_addr, naddr, af) ); >- return (1); /* none available */ >+ /* none available */ >+failed: >+ if (*udp_mapping) { >+ uma_zfree(V_pf_udp_mapping_z, *udp_mapping); >+ *udp_mapping = NULL; >+ } >+ return (1); > } > > int >@@ -512,7 +566,8 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, > struct pfi_kif *kif, struct pf_src_node **sn, > struct pf_state_key **skp, struct pf_state_key **nkp, > struct pf_addr *saddr, struct pf_addr *daddr, >- uint16_t sport, uint16_t dport, struct pf_anchor_stackframe *anchor_stack) >+ uint16_t sport, uint16_t dport, struct pf_anchor_stackframe *anchor_stack, >+ struct pf_udp_mapping **udp_mapping) > { > struct pf_rule *r = NULL; > struct pf_addr *naddr; >@@ -566,7 +621,7 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, > case PF_NAT: > if (pf_get_sport(pd->af, pd->proto, r, saddr, sport, daddr, > dport, naddr, nport, r->rpool.proxy_port[0], >- r->rpool.proxy_port[1], sn)) { >+ r->rpool.proxy_port[1], sn, udp_mapping)) { > DPFPRINTF(PF_DEBUG_MISC, > ("pf: NAT proxy port allocation (%u-%u) failed\n", > r->rpool.proxy_port[0], r->rpool.proxy_port[1]));
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 219803
:
183243
|
183512
|
183534