Deleted Added
full compact
pf.c (285830) pf.c (286014)
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: releng/10.2/sys/netpfil/pf/pf.c 284577 2015-06-18 20:59:48Z kp $");
39__FBSDID("$FreeBSD: releng/10.2/sys/netpfil/pf/pf.c 286014 2015-07-29 14:16:25Z 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 == 0 && 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,

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

5906 M_SETFIB(m, r->rtableid);
5907
5908#ifdef ALTQ
5909 if (action == PF_PASS && r->qid) {
5910 if (pd.pf_mtag == NULL &&
5911 ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
5912 action = PF_DROP;
5913 REASON_SET(&reason, PFRES_MEMORY);
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,

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

5907 M_SETFIB(m, r->rtableid);
5908
5909#ifdef ALTQ
5910 if (action == PF_PASS && r->qid) {
5911 if (pd.pf_mtag == NULL &&
5912 ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
5913 action = PF_DROP;
5914 REASON_SET(&reason, PFRES_MEMORY);
5915 } else {
5916 if (pqid || (pd.tos & IPTOS_LOWDELAY))
5917 pd.pf_mtag->qid = r->pqid;
5918 else
5919 pd.pf_mtag->qid = r->qid;
5920 /* Add hints for ecn. */
5921 pd.pf_mtag->hdr = h;
5914 }
5922 }
5915 if (pqid || (pd.tos & IPTOS_LOWDELAY))
5916 pd.pf_mtag->qid = r->pqid;
5917 else
5918 pd.pf_mtag->qid = r->qid;
5919 /* add hints for ecn */
5920 pd.pf_mtag->hdr = h;
5921
5922 }
5923#endif /* ALTQ */
5924
5925 /*
5926 * connections redirected to loopback should not match sockets
5927 * bound specifically to loopback due to security implications,
5928 * see tcp_input() and in_pcblookup_listen().

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

5951 if (m->m_flags & M_FASTFWD_OURS) {
5952 if (pd.pf_mtag == NULL &&
5953 ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
5954 action = PF_DROP;
5955 REASON_SET(&reason, PFRES_MEMORY);
5956 log = 1;
5957 DPFPRINTF(PF_DEBUG_MISC,
5958 ("pf: failed to allocate tag\n"));
5923
5924 }
5925#endif /* ALTQ */
5926
5927 /*
5928 * connections redirected to loopback should not match sockets
5929 * bound specifically to loopback due to security implications,
5930 * see tcp_input() and in_pcblookup_listen().

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

5953 if (m->m_flags & M_FASTFWD_OURS) {
5954 if (pd.pf_mtag == NULL &&
5955 ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
5956 action = PF_DROP;
5957 REASON_SET(&reason, PFRES_MEMORY);
5958 log = 1;
5959 DPFPRINTF(PF_DEBUG_MISC,
5960 ("pf: failed to allocate tag\n"));
5961 } else {
5962 pd.pf_mtag->flags |=
5963 PF_FASTFWD_OURS_PRESENT;
5964 m->m_flags &= ~M_FASTFWD_OURS;
5959 }
5965 }
5960 pd.pf_mtag->flags |= PF_FASTFWD_OURS_PRESENT;
5961 m->m_flags &= ~M_FASTFWD_OURS;
5962 }
5963 ip_divert_ptr(*m0, dir == PF_IN ? DIR_IN : DIR_OUT);
5964 *m0 = NULL;
5965
5966 return (action);
5967 } else {
5968 /* XXX: ipfw has the same behaviour! */
5969 action = PF_DROP;

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

6335 M_SETFIB(m, r->rtableid);
6336
6337#ifdef ALTQ
6338 if (action == PF_PASS && r->qid) {
6339 if (pd.pf_mtag == NULL &&
6340 ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
6341 action = PF_DROP;
6342 REASON_SET(&reason, PFRES_MEMORY);
5966 }
5967 ip_divert_ptr(*m0, dir == PF_IN ? DIR_IN : DIR_OUT);
5968 *m0 = NULL;
5969
5970 return (action);
5971 } else {
5972 /* XXX: ipfw has the same behaviour! */
5973 action = PF_DROP;

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

6339 M_SETFIB(m, r->rtableid);
6340
6341#ifdef ALTQ
6342 if (action == PF_PASS && r->qid) {
6343 if (pd.pf_mtag == NULL &&
6344 ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
6345 action = PF_DROP;
6346 REASON_SET(&reason, PFRES_MEMORY);
6347 } else {
6348 if (pd.tos & IPTOS_LOWDELAY)
6349 pd.pf_mtag->qid = r->pqid;
6350 else
6351 pd.pf_mtag->qid = r->qid;
6352 /* Add hints for ecn. */
6353 pd.pf_mtag->hdr = h;
6343 }
6354 }
6344 if (pd.tos & IPTOS_LOWDELAY)
6345 pd.pf_mtag->qid = r->pqid;
6346 else
6347 pd.pf_mtag->qid = r->qid;
6348 /* add hints for ecn */
6349 pd.pf_mtag->hdr = h;
6350 }
6351#endif /* ALTQ */
6352
6353 if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
6354 pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
6355 (s->nat_rule.ptr->action == PF_RDR ||
6356 s->nat_rule.ptr->action == PF_BINAT) &&
6357 IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))

--- 95 unchanged lines hidden ---
6355 }
6356#endif /* ALTQ */
6357
6358 if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
6359 pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
6360 (s->nat_rule.ptr->action == PF_RDR ||
6361 s->nat_rule.ptr->action == PF_BINAT) &&
6362 IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))

--- 95 unchanged lines hidden ---