Lines 194-199
static VNET_DEFINE(uma_zone_t, pf_sources_z);
Link Here
|
194 |
uma_zone_t pf_mtag_z; |
194 |
uma_zone_t pf_mtag_z; |
195 |
VNET_DEFINE(uma_zone_t, pf_state_z); |
195 |
VNET_DEFINE(uma_zone_t, pf_state_z); |
196 |
VNET_DEFINE(uma_zone_t, pf_state_key_z); |
196 |
VNET_DEFINE(uma_zone_t, pf_state_key_z); |
|
|
197 |
VNET_DEFINE(uma_zone_t, pf_udp_mapping_z); |
197 |
|
198 |
|
198 |
VNET_DEFINE(uint64_t, pf_stateid[MAXCPU]); |
199 |
VNET_DEFINE(uint64_t, pf_stateid[MAXCPU]); |
199 |
#define PFID_CPUBITS 8 |
200 |
#define PFID_CPUBITS 8 |
Lines 241-247
static int pf_create_state(struct pf_rule *, struct pf_rule *,
Link Here
|
241 |
struct pf_state_key *, struct mbuf *, int, |
242 |
struct pf_state_key *, struct mbuf *, int, |
242 |
u_int16_t, u_int16_t, int *, struct pfi_kif *, |
243 |
u_int16_t, u_int16_t, int *, struct pfi_kif *, |
243 |
struct pf_state **, int, u_int16_t, u_int16_t, |
244 |
struct pf_state **, int, u_int16_t, u_int16_t, |
244 |
int); |
245 |
int, struct pf_udp_mapping *); |
245 |
static int pf_test_fragment(struct pf_rule **, int, |
246 |
static int pf_test_fragment(struct pf_rule **, int, |
246 |
struct pfi_kif *, struct mbuf *, void *, |
247 |
struct pfi_kif *, struct mbuf *, void *, |
247 |
struct pf_pdesc *, struct pf_rule **, |
248 |
struct pf_pdesc *, struct pf_rule **, |
Lines 356-361
static MALLOC_DEFINE(M_PFHASH, "pf_hash", "pf(4) hash header structures");
Link Here
|
356 |
VNET_DEFINE(struct pf_keyhash *, pf_keyhash); |
357 |
VNET_DEFINE(struct pf_keyhash *, pf_keyhash); |
357 |
VNET_DEFINE(struct pf_idhash *, pf_idhash); |
358 |
VNET_DEFINE(struct pf_idhash *, pf_idhash); |
358 |
VNET_DEFINE(struct pf_srchash *, pf_srchash); |
359 |
VNET_DEFINE(struct pf_srchash *, pf_srchash); |
|
|
360 |
VNET_DEFINE(struct pf_udpendpointhash *, pf_udpendpointhash); |
359 |
|
361 |
|
360 |
SYSCTL_NODE(_net, OID_AUTO, pf, CTLFLAG_RW, 0, "pf(4)"); |
362 |
SYSCTL_NODE(_net, OID_AUTO, pf, CTLFLAG_RW, 0, "pf(4)"); |
361 |
|
363 |
|
Lines 426-431
pf_hashkey(struct pf_state_key *sk)
Link Here
|
426 |
} |
428 |
} |
427 |
|
429 |
|
428 |
static __inline uint32_t |
430 |
static __inline uint32_t |
|
|
431 |
pf_hashudpendpoint(struct pf_udp_endpoint *endpoint) |
432 |
{ |
433 |
uint32_t h; |
434 |
|
435 |
h = murmur3_32_hash32((uint32_t *)endpoint, |
436 |
sizeof(struct pf_udp_endpoint_cmp)/sizeof(uint32_t), |
437 |
V_pf_hashseed); |
438 |
|
439 |
return (h & pf_hashmask); |
440 |
} |
441 |
|
442 |
static __inline uint32_t |
429 |
pf_hashsrc(struct pf_addr *addr, sa_family_t af) |
443 |
pf_hashsrc(struct pf_addr *addr, sa_family_t af) |
430 |
{ |
444 |
{ |
431 |
uint32_t h; |
445 |
uint32_t h; |
Lines 779-784
pf_initialize()
Link Here
|
779 |
{ |
793 |
{ |
780 |
struct pf_keyhash *kh; |
794 |
struct pf_keyhash *kh; |
781 |
struct pf_idhash *ih; |
795 |
struct pf_idhash *ih; |
|
|
796 |
struct pf_udpendpointhash *uh; |
782 |
struct pf_srchash *sh; |
797 |
struct pf_srchash *sh; |
783 |
u_int i; |
798 |
u_int i; |
784 |
|
799 |
|
Lines 799-813
pf_initialize()
Link Here
|
799 |
V_pf_state_key_z = uma_zcreate("pf state keys", |
814 |
V_pf_state_key_z = uma_zcreate("pf state keys", |
800 |
sizeof(struct pf_state_key), pf_state_key_ctor, NULL, NULL, NULL, |
815 |
sizeof(struct pf_state_key), pf_state_key_ctor, NULL, NULL, NULL, |
801 |
UMA_ALIGN_PTR, 0); |
816 |
UMA_ALIGN_PTR, 0); |
|
|
817 |
V_pf_udp_mapping_z = uma_zcreate("pf UDP mappings", |
818 |
sizeof(struct pf_udp_mapping), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); |
802 |
V_pf_keyhash = malloc(pf_hashsize * sizeof(struct pf_keyhash), |
819 |
V_pf_keyhash = malloc(pf_hashsize * sizeof(struct pf_keyhash), |
803 |
M_PFHASH, M_WAITOK | M_ZERO); |
820 |
M_PFHASH, M_WAITOK | M_ZERO); |
804 |
V_pf_idhash = malloc(pf_hashsize * sizeof(struct pf_idhash), |
821 |
V_pf_idhash = malloc(pf_hashsize * sizeof(struct pf_idhash), |
805 |
M_PFHASH, M_WAITOK | M_ZERO); |
822 |
M_PFHASH, M_WAITOK | M_ZERO); |
|
|
823 |
V_pf_udpendpointhash = malloc(pf_hashsize * sizeof(struct pf_udpendpointhash), |
824 |
M_PFHASH, M_WAITOK | M_ZERO); |
806 |
pf_hashmask = pf_hashsize - 1; |
825 |
pf_hashmask = pf_hashsize - 1; |
807 |
for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash; i <= pf_hashmask; |
826 |
for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash, uh=V_pf_udpendpointhash; i <= pf_hashmask; |
808 |
i++, kh++, ih++) { |
827 |
i++, kh++, ih++, uh++) { |
809 |
mtx_init(&kh->lock, "pf_keyhash", NULL, MTX_DEF | MTX_DUPOK); |
828 |
mtx_init(&kh->lock, "pf_keyhash", NULL, MTX_DEF | MTX_DUPOK); |
810 |
mtx_init(&ih->lock, "pf_idhash", NULL, MTX_DEF); |
829 |
mtx_init(&ih->lock, "pf_idhash", NULL, MTX_DEF); |
|
|
830 |
mtx_init(&uh->lock, "pf_udpendpointhash", NULL, MTX_DEF | MTX_DUPOK); |
811 |
} |
831 |
} |
812 |
|
832 |
|
813 |
/* Source nodes. */ |
833 |
/* Source nodes. */ |
Lines 851-871
pf_cleanup()
Link Here
|
851 |
{ |
871 |
{ |
852 |
struct pf_keyhash *kh; |
872 |
struct pf_keyhash *kh; |
853 |
struct pf_idhash *ih; |
873 |
struct pf_idhash *ih; |
|
|
874 |
struct pf_udpendpointhash *uh; |
854 |
struct pf_srchash *sh; |
875 |
struct pf_srchash *sh; |
855 |
struct pf_send_entry *pfse, *next; |
876 |
struct pf_send_entry *pfse, *next; |
856 |
u_int i; |
877 |
u_int i; |
857 |
|
878 |
|
858 |
for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash; i <= pf_hashmask; |
879 |
for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash, uh=V_pf_udpendpointhash; i <= pf_hashmask; |
859 |
i++, kh++, ih++) { |
880 |
i++, kh++, ih++, uh++) { |
860 |
KASSERT(LIST_EMPTY(&kh->keys), ("%s: key hash not empty", |
881 |
KASSERT(LIST_EMPTY(&kh->keys), ("%s: key hash not empty", |
861 |
__func__)); |
882 |
__func__)); |
862 |
KASSERT(LIST_EMPTY(&ih->states), ("%s: id hash not empty", |
883 |
KASSERT(LIST_EMPTY(&ih->states), ("%s: id hash not empty", |
863 |
__func__)); |
884 |
__func__)); |
|
|
885 |
KASSERT(LIST_EMPTY(&uh->endpoints), ("%s: udpendpoint hash not empty", |
886 |
__func__)); |
864 |
mtx_destroy(&kh->lock); |
887 |
mtx_destroy(&kh->lock); |
865 |
mtx_destroy(&ih->lock); |
888 |
mtx_destroy(&ih->lock); |
|
|
889 |
mtx_destroy(&uh->lock); |
866 |
} |
890 |
} |
867 |
free(V_pf_keyhash, M_PFHASH); |
891 |
free(V_pf_keyhash, M_PFHASH); |
868 |
free(V_pf_idhash, M_PFHASH); |
892 |
free(V_pf_idhash, M_PFHASH); |
|
|
893 |
free(V_pf_udpendpointhash, M_PFHASH); |
869 |
|
894 |
|
870 |
for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask; i++, sh++) { |
895 |
for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask; i++, sh++) { |
871 |
KASSERT(LIST_EMPTY(&sh->nodes), |
896 |
KASSERT(LIST_EMPTY(&sh->nodes), |
Lines 882-887
pf_cleanup()
Link Here
|
882 |
uma_zdestroy(V_pf_sources_z); |
907 |
uma_zdestroy(V_pf_sources_z); |
883 |
uma_zdestroy(V_pf_state_z); |
908 |
uma_zdestroy(V_pf_state_z); |
884 |
uma_zdestroy(V_pf_state_key_z); |
909 |
uma_zdestroy(V_pf_state_key_z); |
|
|
910 |
uma_zdestroy(V_pf_udp_mapping_z); |
885 |
} |
911 |
} |
886 |
|
912 |
|
887 |
static int |
913 |
static int |
Lines 1369-1374
second_run:
Link Here
|
1369 |
return (ret); |
1395 |
return (ret); |
1370 |
} |
1396 |
} |
1371 |
|
1397 |
|
|
|
1398 |
struct pf_udp_mapping* |
1399 |
pf_udp_mapping_create(sa_family_t af, struct pf_addr *src_addr, u_int16_t src_port, |
1400 |
struct pf_addr *nat_addr, u_int16_t nat_port) |
1401 |
{ |
1402 |
struct pf_udp_mapping *mapping = uma_zalloc(V_pf_udp_mapping_z, M_NOWAIT | M_ZERO); |
1403 |
if (mapping == NULL) |
1404 |
return NULL; |
1405 |
PF_ACPY(&mapping->endpoints[0].addr, src_addr, af); |
1406 |
mapping->endpoints[0].port = src_port; |
1407 |
mapping->endpoints[0].af = af; |
1408 |
mapping->endpoints[0].mapping = mapping; |
1409 |
PF_ACPY(&mapping->endpoints[1].addr, nat_addr, af); |
1410 |
mapping->endpoints[1].port = nat_port; |
1411 |
mapping->endpoints[1].af = af; |
1412 |
mapping->endpoints[1].mapping = mapping; |
1413 |
refcount_init(&mapping->refs, 1); |
1414 |
return mapping; |
1415 |
} |
1416 |
|
1417 |
int |
1418 |
pf_udp_mapping_insert(struct pf_udp_mapping *mapping) |
1419 |
{ |
1420 |
struct pf_udpendpointhash *h0, *h1; |
1421 |
struct pf_udp_endpoint *endpoint; |
1422 |
int ret = 1; |
1423 |
|
1424 |
h0 = &V_pf_udpendpointhash[pf_hashudpendpoint(&mapping->endpoints[0])]; |
1425 |
h1 = &V_pf_udpendpointhash[pf_hashudpendpoint(&mapping->endpoints[1])]; |
1426 |
if (h0 == h1) { |
1427 |
PF_HASHROW_LOCK(h0); |
1428 |
} else if (h0 < h1) { |
1429 |
PF_HASHROW_LOCK(h0); |
1430 |
PF_HASHROW_LOCK(h1); |
1431 |
} else { |
1432 |
PF_HASHROW_LOCK(h1); |
1433 |
PF_HASHROW_LOCK(h0); |
1434 |
} |
1435 |
|
1436 |
LIST_FOREACH(endpoint, &h0->endpoints, entry) |
1437 |
if (bcmp(endpoint, &mapping->endpoints[0], sizeof(struct pf_udp_endpoint_cmp)) == 0) |
1438 |
break; |
1439 |
if (endpoint != NULL) |
1440 |
goto cleanup; |
1441 |
LIST_FOREACH(endpoint, &h1->endpoints, entry) |
1442 |
if (bcmp(endpoint, &mapping->endpoints[1], sizeof(struct pf_udp_endpoint_cmp)) == 0) |
1443 |
break; |
1444 |
if (endpoint != NULL) |
1445 |
goto cleanup; |
1446 |
LIST_INSERT_HEAD(&h0->endpoints, &mapping->endpoints[0], entry); |
1447 |
LIST_INSERT_HEAD(&h1->endpoints, &mapping->endpoints[1], entry); |
1448 |
ret = 0; |
1449 |
|
1450 |
cleanup: |
1451 |
if (h0 != h1) { |
1452 |
PF_HASHROW_UNLOCK(h0); |
1453 |
PF_HASHROW_UNLOCK(h1); |
1454 |
} else { |
1455 |
PF_HASHROW_UNLOCK(h0); |
1456 |
} |
1457 |
return ret; |
1458 |
} |
1459 |
|
1460 |
void |
1461 |
pf_udp_mapping_release(struct pf_udp_mapping *mapping) |
1462 |
{ |
1463 |
/* refcount is synchronized on the source endpoint's row lock */ |
1464 |
struct pf_udpendpointhash *h0, *h1; |
1465 |
h0 = &V_pf_udpendpointhash[pf_hashudpendpoint(&mapping->endpoints[0])]; |
1466 |
PF_HASHROW_LOCK(h0); |
1467 |
if (refcount_release(&mapping->refs)) { |
1468 |
LIST_REMOVE(&mapping->endpoints[0], entry); |
1469 |
PF_HASHROW_UNLOCK(h0); |
1470 |
h1 = &V_pf_udpendpointhash[pf_hashudpendpoint(&mapping->endpoints[1])]; |
1471 |
PF_HASHROW_LOCK(h1); |
1472 |
LIST_REMOVE(&mapping->endpoints[1], entry); |
1473 |
PF_HASHROW_UNLOCK(h1); |
1474 |
|
1475 |
uma_zfree(V_pf_udp_mapping_z, mapping); |
1476 |
} else { |
1477 |
PF_HASHROW_UNLOCK(h0); |
1478 |
} |
1479 |
} |
1480 |
|
1481 |
struct pf_udp_mapping * |
1482 |
pf_udp_mapping_find(struct pf_udp_endpoint_cmp *key) |
1483 |
{ |
1484 |
struct pf_udpendpointhash *uh; |
1485 |
struct pf_udp_endpoint *endpoint; |
1486 |
|
1487 |
uh = &V_pf_udpendpointhash[pf_hashudpendpoint((struct pf_udp_endpoint*)key)]; |
1488 |
|
1489 |
PF_HASHROW_LOCK(uh); |
1490 |
LIST_FOREACH(endpoint, &uh->endpoints, entry) |
1491 |
if (bcmp(endpoint, key, sizeof(struct pf_udp_endpoint_cmp)) == 0 && |
1492 |
bcmp(endpoint, &endpoint->mapping->endpoints[0], sizeof(struct pf_udp_endpoint_cmp)) == 0) |
1493 |
break; |
1494 |
if (endpoint == NULL) { |
1495 |
PF_HASHROW_UNLOCK(uh); |
1496 |
return NULL; |
1497 |
} |
1498 |
refcount_acquire(&endpoint->mapping->refs); |
1499 |
PF_HASHROW_UNLOCK(uh); |
1500 |
return endpoint->mapping; |
1501 |
} |
1502 |
|
1372 |
/* END state table stuff */ |
1503 |
/* END state table stuff */ |
1373 |
|
1504 |
|
1374 |
static void |
1505 |
static void |
Lines 1650-1655
pf_unlink_state(struct pf_state *s, u_int flags)
Link Here
|
1650 |
pf_detach_state(s); |
1781 |
pf_detach_state(s); |
1651 |
refcount_release(&s->refs); |
1782 |
refcount_release(&s->refs); |
1652 |
|
1783 |
|
|
|
1784 |
if (s->udp_mapping) |
1785 |
pf_udp_mapping_release(s->udp_mapping); |
1786 |
|
1653 |
return (pf_release_state(s)); |
1787 |
return (pf_release_state(s)); |
1654 |
} |
1788 |
} |
1655 |
|
1789 |
|
Lines 3136-3141
pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
Link Here
|
3136 |
u_int16_t bproto_sum = 0, bip_sum = 0; |
3270 |
u_int16_t bproto_sum = 0, bip_sum = 0; |
3137 |
u_int8_t icmptype = 0, icmpcode = 0; |
3271 |
u_int8_t icmptype = 0, icmpcode = 0; |
3138 |
struct pf_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE]; |
3272 |
struct pf_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE]; |
|
|
3273 |
struct pf_udp_mapping *udp_mapping = NULL; |
3139 |
|
3274 |
|
3140 |
PF_RULES_RASSERT(); |
3275 |
PF_RULES_RASSERT(); |
3141 |
|
3276 |
|
Lines 3199-3205
pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
Link Here
|
3199 |
|
3334 |
|
3200 |
/* check packet for BINAT/NAT/RDR */ |
3335 |
/* check packet for BINAT/NAT/RDR */ |
3201 |
if ((nr = pf_get_translation(pd, m, off, direction, kif, &nsn, &sk, |
3336 |
if ((nr = pf_get_translation(pd, m, off, direction, kif, &nsn, &sk, |
3202 |
&nk, saddr, daddr, sport, dport, anchor_stack)) != NULL) { |
3337 |
&nk, saddr, daddr, sport, dport, anchor_stack, &udp_mapping)) != NULL) { |
3203 |
KASSERT(sk != NULL, ("%s: null sk", __func__)); |
3338 |
KASSERT(sk != NULL, ("%s: null sk", __func__)); |
3204 |
KASSERT(nk != NULL, ("%s: null nk", __func__)); |
3339 |
KASSERT(nk != NULL, ("%s: null nk", __func__)); |
3205 |
|
3340 |
|
Lines 3506-3519
pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
Link Here
|
3506 |
int action; |
3641 |
int action; |
3507 |
action = pf_create_state(r, nr, a, pd, nsn, nk, sk, m, off, |
3642 |
action = pf_create_state(r, nr, a, pd, nsn, nk, sk, m, off, |
3508 |
sport, dport, &rewrite, kif, sm, tag, bproto_sum, bip_sum, |
3643 |
sport, dport, &rewrite, kif, sm, tag, bproto_sum, bip_sum, |
3509 |
hdrlen); |
3644 |
hdrlen, udp_mapping); |
3510 |
if (action != PF_PASS) |
3645 |
if (action != PF_PASS) { |
|
|
3646 |
if (udp_mapping != NULL) |
3647 |
pf_udp_mapping_release(udp_mapping); |
3511 |
return (action); |
3648 |
return (action); |
|
|
3649 |
} |
3512 |
} else { |
3650 |
} else { |
3513 |
if (sk != NULL) |
3651 |
if (sk != NULL) |
3514 |
uma_zfree(V_pf_state_key_z, sk); |
3652 |
uma_zfree(V_pf_state_key_z, sk); |
3515 |
if (nk != NULL) |
3653 |
if (nk != NULL) |
3516 |
uma_zfree(V_pf_state_key_z, nk); |
3654 |
uma_zfree(V_pf_state_key_z, nk); |
|
|
3655 |
if (udp_mapping != NULL) |
3656 |
pf_udp_mapping_release(udp_mapping); |
3517 |
} |
3657 |
} |
3518 |
|
3658 |
|
3519 |
/* copy back packet headers if we performed NAT operations */ |
3659 |
/* copy back packet headers if we performed NAT operations */ |
Lines 3538-3543
cleanup:
Link Here
|
3538 |
uma_zfree(V_pf_state_key_z, sk); |
3678 |
uma_zfree(V_pf_state_key_z, sk); |
3539 |
if (nk != NULL) |
3679 |
if (nk != NULL) |
3540 |
uma_zfree(V_pf_state_key_z, nk); |
3680 |
uma_zfree(V_pf_state_key_z, nk); |
|
|
3681 |
if (udp_mapping != NULL) |
3682 |
pf_udp_mapping_release(udp_mapping); |
3541 |
return (PF_DROP); |
3683 |
return (PF_DROP); |
3542 |
} |
3684 |
} |
3543 |
|
3685 |
|
Lines 3546-3552
pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
Link Here
|
3546 |
struct pf_pdesc *pd, struct pf_src_node *nsn, struct pf_state_key *nk, |
3688 |
struct pf_pdesc *pd, struct pf_src_node *nsn, struct pf_state_key *nk, |
3547 |
struct pf_state_key *sk, struct mbuf *m, int off, u_int16_t sport, |
3689 |
struct pf_state_key *sk, struct mbuf *m, int off, u_int16_t sport, |
3548 |
u_int16_t dport, int *rewrite, struct pfi_kif *kif, struct pf_state **sm, |
3690 |
u_int16_t dport, int *rewrite, struct pfi_kif *kif, struct pf_state **sm, |
3549 |
int tag, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen) |
3691 |
int tag, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen, |
|
|
3692 |
struct pf_udp_mapping *udp_mapping) |
3550 |
{ |
3693 |
{ |
3551 |
struct pf_state *s = NULL; |
3694 |
struct pf_state *s = NULL; |
3552 |
struct pf_src_node *sn = NULL; |
3695 |
struct pf_src_node *sn = NULL; |
Lines 3752-3757
pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
Link Here
|
3752 |
REASON_SET(&reason, PFRES_SYNPROXY); |
3895 |
REASON_SET(&reason, PFRES_SYNPROXY); |
3753 |
return (PF_SYNPROXY_DROP); |
3896 |
return (PF_SYNPROXY_DROP); |
3754 |
} |
3897 |
} |
|
|
3898 |
s->udp_mapping = udp_mapping; |
3755 |
|
3899 |
|
3756 |
return (PF_PASS); |
3900 |
return (PF_PASS); |
3757 |
|
3901 |
|