Deleted Added
full compact
pf.c (284577) pf.c (285940)
1/*-
2 * Copyright (c) 2001 Daniel Hartmeier
3 * Copyright (c) 2002 - 2008 Henning Brauer
4 * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 22 unchanged lines hidden (view full) ---

31 * Effort sponsored in part by the Defense Advanced Research Projects
32 * Agency (DARPA) and Air Force Research Laboratory, Air Force
33 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
34 *
35 * $OpenBSD: pf.c,v 1.634 2009/02/27 12:37:45 henning Exp $
36 */
37
38#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Daniel Hartmeier
3 * Copyright (c) 2002 - 2008 Henning Brauer
4 * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 22 unchanged lines hidden (view full) ---

31 * Effort sponsored in part by the Defense Advanced Research Projects
32 * Agency (DARPA) and Air Force Research Laboratory, Air Force
33 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
34 *
35 * $OpenBSD: pf.c,v 1.634 2009/02/27 12:37:45 henning Exp $
36 */
37
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: stable/10/sys/netpfil/pf/pf.c 284577 2015-06-18 20:59:48Z kp $");
39__FBSDID("$FreeBSD: stable/10/sys/netpfil/pf/pf.c 285940 2015-07-28 09:13:55Z glebius $");
40
41#include "opt_inet.h"
42#include "opt_inet6.h"
43#include "opt_bpf.h"
44#include "opt_pf.h"
45
46#include <sys/param.h>
47#include <sys/bus.h>

--- 602 unchanged lines hidden (view full) ---

650
651 sh = &V_pf_srchash[pf_hashsrc(src, af)];
652 PF_HASHROW_LOCK(sh);
653 LIST_FOREACH(n, &sh->nodes, entry)
654 if (n->rule.ptr == rule && n->af == af &&
655 ((af == AF_INET && n->addr.v4.s_addr == src->v4.s_addr) ||
656 (af == AF_INET6 && bcmp(&n->addr, src, sizeof(*src)) == 0)))
657 break;
40
41#include "opt_inet.h"
42#include "opt_inet6.h"
43#include "opt_bpf.h"
44#include "opt_pf.h"
45
46#include <sys/param.h>
47#include <sys/bus.h>

--- 602 unchanged lines hidden (view full) ---

650
651 sh = &V_pf_srchash[pf_hashsrc(src, af)];
652 PF_HASHROW_LOCK(sh);
653 LIST_FOREACH(n, &sh->nodes, entry)
654 if (n->rule.ptr == rule && n->af == af &&
655 ((af == AF_INET && n->addr.v4.s_addr == src->v4.s_addr) ||
656 (af == AF_INET6 && bcmp(&n->addr, src, sizeof(*src)) == 0)))
657 break;
658 if (n != NULL || returnlocked == 0)
658 if (n != NULL) {
659 n->states++;
659 PF_HASHROW_UNLOCK(sh);
660 PF_HASHROW_UNLOCK(sh);
661 } else if (returnlocked == 0)
662 PF_HASHROW_UNLOCK(sh);
660
661 return (n);
662}
663
664static int
665pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
666 struct pf_addr *src, sa_family_t af)
667{

--- 26 unchanged lines hidden (view full) ---

694 rule->max_src_conn_rate.seconds);
695
696 (*sn)->af = af;
697 (*sn)->rule.ptr = rule;
698 PF_ACPY(&(*sn)->addr, src, af);
699 LIST_INSERT_HEAD(&sh->nodes, *sn, entry);
700 (*sn)->creation = time_uptime;
701 (*sn)->ruletype = rule->action;
663
664 return (n);
665}
666
667static int
668pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
669 struct pf_addr *src, sa_family_t af)
670{

--- 26 unchanged lines hidden (view full) ---

697 rule->max_src_conn_rate.seconds);
698
699 (*sn)->af = af;
700 (*sn)->rule.ptr = rule;
701 PF_ACPY(&(*sn)->addr, src, af);
702 LIST_INSERT_HEAD(&sh->nodes, *sn, entry);
703 (*sn)->creation = time_uptime;
704 (*sn)->ruletype = rule->action;
705 (*sn)->states = 1;
702 if ((*sn)->rule.ptr != NULL)
703 counter_u64_add((*sn)->rule.ptr->src_nodes, 1);
704 PF_HASHROW_UNLOCK(sh);
705 counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_INSERT], 1);
706 } else {
707 if (rule->max_src_states &&
708 (*sn)->states >= rule->max_src_states) {
709 counter_u64_add(V_pf_status.lcounters[LCNT_SRCSTATES],
710 1);
711 return (-1);
712 }
713 }
714 return (0);
715}
716
717void
706 if ((*sn)->rule.ptr != NULL)
707 counter_u64_add((*sn)->rule.ptr->src_nodes, 1);
708 PF_HASHROW_UNLOCK(sh);
709 counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_INSERT], 1);
710 } else {
711 if (rule->max_src_states &&
712 (*sn)->states >= rule->max_src_states) {
713 counter_u64_add(V_pf_status.lcounters[LCNT_SRCSTATES],
714 1);
715 return (-1);
716 }
717 }
718 return (0);
719}
720
721void
718pf_unlink_src_node_locked(struct pf_src_node *src)
722pf_unlink_src_node(struct pf_src_node *src)
719{
723{
720#ifdef INVARIANTS
721 struct pf_srchash *sh;
722
724
723 sh = &V_pf_srchash[pf_hashsrc(&src->addr, src->af)];
724 PF_HASHROW_ASSERT(sh);
725#endif
725 PF_HASHROW_ASSERT(&V_pf_srchash[pf_hashsrc(&src->addr, src->af)]);
726 LIST_REMOVE(src, entry);
727 if (src->rule.ptr)
728 counter_u64_add(src->rule.ptr->src_nodes, -1);
726 LIST_REMOVE(src, entry);
727 if (src->rule.ptr)
728 counter_u64_add(src->rule.ptr->src_nodes, -1);
729 counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS], 1);
730}
731
729}
730
732void
733pf_unlink_src_node(struct pf_src_node *src)
734{
735 struct pf_srchash *sh;
736
737 sh = &V_pf_srchash[pf_hashsrc(&src->addr, src->af)];
738 PF_HASHROW_LOCK(sh);
739 pf_unlink_src_node_locked(src);
740 PF_HASHROW_UNLOCK(sh);
741}
742
743static void
744pf_free_src_node(struct pf_src_node *sn)
745{
746
747 KASSERT(sn->states == 0, ("%s: %p has refs", __func__, sn));
748 uma_zfree(V_pf_sources_z, sn);
749}
750
751u_int
752pf_free_src_nodes(struct pf_src_node_list *head)
753{
754 struct pf_src_node *sn, *tmp;
755 u_int count = 0;
756
757 LIST_FOREACH_SAFE(sn, head, entry, tmp) {
731u_int
732pf_free_src_nodes(struct pf_src_node_list *head)
733{
734 struct pf_src_node *sn, *tmp;
735 u_int count = 0;
736
737 LIST_FOREACH_SAFE(sn, head, entry, tmp) {
758 pf_free_src_node(sn);
738 uma_zfree(V_pf_sources_z, sn);
759 count++;
760 }
761
739 count++;
740 }
741
742 counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS], count);
743
762 return (count);
763}
764
765void
766pf_mtag_initialize()
767{
768
769 pf_mtag_z = uma_zcreate("pf mtags", sizeof(struct m_tag) +

--- 775 unchanged lines hidden (view full) ---

1545 struct pf_src_node *cur, *next;
1546 int i;
1547
1548 LIST_INIT(&freelist);
1549 for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask; i++, sh++) {
1550 PF_HASHROW_LOCK(sh);
1551 LIST_FOREACH_SAFE(cur, &sh->nodes, entry, next)
1552 if (cur->states == 0 && cur->expire <= time_uptime) {
744 return (count);
745}
746
747void
748pf_mtag_initialize()
749{
750
751 pf_mtag_z = uma_zcreate("pf mtags", sizeof(struct m_tag) +

--- 775 unchanged lines hidden (view full) ---

1527 struct pf_src_node *cur, *next;
1528 int i;
1529
1530 LIST_INIT(&freelist);
1531 for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask; i++, sh++) {
1532 PF_HASHROW_LOCK(sh);
1533 LIST_FOREACH_SAFE(cur, &sh->nodes, entry, next)
1534 if (cur->states == 0 && cur->expire <= time_uptime) {
1553 pf_unlink_src_node_locked(cur);
1535 pf_unlink_src_node(cur);
1554 LIST_INSERT_HEAD(&freelist, cur, entry);
1555 } else if (cur->rule.ptr != NULL)
1556 cur->rule.ptr->rule_flag |= PFRULE_REFS;
1557 PF_HASHROW_UNLOCK(sh);
1558 }
1559
1560 pf_free_src_nodes(&freelist);
1561
1562 V_pf_status.src_nodes = uma_zone_get_cur(V_pf_sources_z);
1563}
1564
1565static void
1566pf_src_tree_remove_state(struct pf_state *s)
1567{
1536 LIST_INSERT_HEAD(&freelist, cur, entry);
1537 } else if (cur->rule.ptr != NULL)
1538 cur->rule.ptr->rule_flag |= PFRULE_REFS;
1539 PF_HASHROW_UNLOCK(sh);
1540 }
1541
1542 pf_free_src_nodes(&freelist);
1543
1544 V_pf_status.src_nodes = uma_zone_get_cur(V_pf_sources_z);
1545}
1546
1547static void
1548pf_src_tree_remove_state(struct pf_state *s)
1549{
1568 u_int32_t timeout;
1550 struct pf_src_node *sn;
1551 struct pf_srchash *sh;
1552 uint32_t timeout;
1569
1553
1554 timeout = s->rule.ptr->timeout[PFTM_SRC_NODE] ?
1555 s->rule.ptr->timeout[PFTM_SRC_NODE] :
1556 V_pf_default_rule.timeout[PFTM_SRC_NODE];
1557
1570 if (s->src_node != NULL) {
1558 if (s->src_node != NULL) {
1559 sn = s->src_node;
1560 sh = &V_pf_srchash[pf_hashsrc(&sn->addr, sn->af)];
1561 PF_HASHROW_LOCK(sh);
1571 if (s->src.tcp_est)
1562 if (s->src.tcp_est)
1572 --s->src_node->conn;
1573 if (--s->src_node->states == 0) {
1574 timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
1575 if (!timeout)
1576 timeout =
1577 V_pf_default_rule.timeout[PFTM_SRC_NODE];
1578 s->src_node->expire = time_uptime + timeout;
1579 }
1563 --sn->conn;
1564 if (--sn->states == 0)
1565 sn->expire = time_uptime + timeout;
1566 PF_HASHROW_UNLOCK(sh);
1580 }
1581 if (s->nat_src_node != s->src_node && s->nat_src_node != NULL) {
1567 }
1568 if (s->nat_src_node != s->src_node && s->nat_src_node != NULL) {
1582 if (--s->nat_src_node->states == 0) {
1583 timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
1584 if (!timeout)
1585 timeout =
1586 V_pf_default_rule.timeout[PFTM_SRC_NODE];
1587 s->nat_src_node->expire = time_uptime + timeout;
1588 }
1569 sn = s->nat_src_node;
1570 sh = &V_pf_srchash[pf_hashsrc(&sn->addr, sn->af)];
1571 PF_HASHROW_LOCK(sh);
1572 if (--sn->states == 0)
1573 sn->expire = time_uptime + timeout;
1574 PF_HASHROW_UNLOCK(sh);
1589 }
1590 s->src_node = s->nat_src_node = NULL;
1591}
1592
1593/*
1594 * Unlink and potentilly free a state. Function may be
1595 * called with ID hash row locked, but always returns
1596 * unlocked, since it needs to go through key hash locking.

--- 1969 unchanged lines hidden (view full) ---

3566 goto csfailed;
3567 }
3568 s->rt_kif = r->rpool.cur->kif;
3569 }
3570
3571 s->creation = time_uptime;
3572 s->expire = time_uptime;
3573
1575 }
1576 s->src_node = s->nat_src_node = NULL;
1577}
1578
1579/*
1580 * Unlink and potentilly free a state. Function may be
1581 * called with ID hash row locked, but always returns
1582 * unlocked, since it needs to go through key hash locking.

--- 1969 unchanged lines hidden (view full) ---

3552 goto csfailed;
3553 }
3554 s->rt_kif = r->rpool.cur->kif;
3555 }
3556
3557 s->creation = time_uptime;
3558 s->expire = time_uptime;
3559
3574 if (sn != NULL) {
3560 if (sn != NULL)
3575 s->src_node = sn;
3561 s->src_node = sn;
3576 s->src_node->states++;
3577 }
3578 if (nsn != NULL) {
3579 /* XXX We only modify one side for now. */
3580 PF_ACPY(&nsn->raddr, &nk->addr[1], pd->af);
3581 s->nat_src_node = nsn;
3562 if (nsn != NULL) {
3563 /* XXX We only modify one side for now. */
3564 PF_ACPY(&nsn->raddr, &nk->addr[1], pd->af);
3565 s->nat_src_node = nsn;
3582 s->nat_src_node->states++;
3583 }
3584 if (pd->proto == IPPROTO_TCP) {
3585 if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
3586 off, pd, th, &s->src, &s->dst)) {
3587 REASON_SET(&reason, PFRES_MEMORY);
3588 pf_src_tree_remove_state(s);
3589 STATE_DEC_COUNTERS(s);
3590 uma_zfree(V_pf_state_z, s);

--- 81 unchanged lines hidden (view full) ---

3672 return (PF_PASS);
3673
3674csfailed:
3675 if (sk != NULL)
3676 uma_zfree(V_pf_state_key_z, sk);
3677 if (nk != NULL)
3678 uma_zfree(V_pf_state_key_z, nk);
3679
3566 }
3567 if (pd->proto == IPPROTO_TCP) {
3568 if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
3569 off, pd, th, &s->src, &s->dst)) {
3570 REASON_SET(&reason, PFRES_MEMORY);
3571 pf_src_tree_remove_state(s);
3572 STATE_DEC_COUNTERS(s);
3573 uma_zfree(V_pf_state_z, s);

--- 81 unchanged lines hidden (view full) ---

3655 return (PF_PASS);
3656
3657csfailed:
3658 if (sk != NULL)
3659 uma_zfree(V_pf_state_key_z, sk);
3660 if (nk != NULL)
3661 uma_zfree(V_pf_state_key_z, nk);
3662
3680 if (sn != NULL && sn->states == 0 && sn->expire == 0) {
3681 pf_unlink_src_node(sn);
3682 pf_free_src_node(sn);
3663 if (sn != NULL) {
3664 struct pf_srchash *sh;
3665
3666 sh = &V_pf_srchash[pf_hashsrc(&sn->addr, sn->af)];
3667 PF_HASHROW_LOCK(sh);
3668 if (--sn->states == 0 && sn->expire == 0) {
3669 pf_unlink_src_node(sn);
3670 uma_zfree(V_pf_sources_z, sn);
3671 counter_u64_add(
3672 V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS], 1);
3673 }
3674 PF_HASHROW_UNLOCK(sh);
3683 }
3684
3675 }
3676
3685 if (nsn != sn && nsn != NULL && nsn->states == 0 && nsn->expire == 0) {
3686 pf_unlink_src_node(nsn);
3687 pf_free_src_node(nsn);
3677 if (nsn != sn && nsn != NULL) {
3678 struct pf_srchash *sh;
3679
3680 sh = &V_pf_srchash[pf_hashsrc(&nsn->addr, nsn->af)];
3681 PF_HASHROW_LOCK(sh);
3682 if (--nsn->states == 1 && nsn->expire == 0) {
3683 pf_unlink_src_node(nsn);
3684 uma_zfree(V_pf_sources_z, nsn);
3685 counter_u64_add(
3686 V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS], 1);
3687 }
3688 PF_HASHROW_UNLOCK(sh);
3688 }
3689
3690 return (PF_DROP);
3691}
3692
3693static int
3694pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
3695 struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am,

--- 2757 unchanged lines hidden ---
3689 }
3690
3691 return (PF_DROP);
3692}
3693
3694static int
3695pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
3696 struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am,

--- 2757 unchanged lines hidden ---