summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorRyan Thomas McBride <mcbride@cvs.openbsd.org>2004-12-04 07:49:49 +0000
committerRyan Thomas McBride <mcbride@cvs.openbsd.org>2004-12-04 07:49:49 +0000
commit9c0396be58b3f3da3d725d94639fa5c35aa98e44 (patch)
treef61ebc498ca863892b283c81a1d1a9d9833700b1 /sys/net
parent3c9e74736abb202307165383fd4e3cb926fd82f9 (diff)
Add kernel code to keep track of tcp connections which have completed
the 3-way handshake. Allow limits on both total connections and connection rate, put offenders in a table which can be used in the ruleset, and optionally kill existing states. Rate tracking code from dhartmei@. Adds a second pool for table entries using the default allocator, which allows entries to be added at splsoftnet(). ok deraadt@ dhartmei@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/pf.c175
-rw-r--r--sys/net/pf_ioctl.c28
-rw-r--r--sys/net/pf_table.c49
-rw-r--r--sys/net/pfvar.h47
4 files changed, 277 insertions, 22 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index df003382168..4f69b9afdb9 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.464 2004/11/24 00:36:10 dhartmei Exp $ */
+/* $OpenBSD: pf.c,v 1.465 2004/12/04 07:49:48 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -119,6 +119,11 @@ struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
+void pf_init_threshold(struct pf_threshold *, u_int32_t,
+ u_int32_t);
+void pf_add_threshold(struct pf_threshold *);
+int pf_check_threshold(struct pf_threshold *);
+
void pf_change_ap(struct pf_addr *, u_int16_t *,
u_int16_t *, u_int16_t *, struct pf_addr *,
u_int16_t, u_int8_t, sa_family_t);
@@ -210,6 +215,7 @@ int pf_addr_wrap_neq(struct pf_addr_wrap *,
static int pf_add_mbuf_tag(struct mbuf *, u_int);
struct pf_state *pf_find_state_recurse(struct pfi_kif *,
struct pf_state *, u_int8_t);
+int pf_src_connlimit(struct pf_state **);
int pf_check_congestion(struct ifqueue *);
struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
@@ -221,12 +227,12 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
#define STATE_LOOKUP() \
do { \
if (direction == PF_IN) \
- *state = pf_find_state_recurse( \
+ *state = pf_find_state_recurse( \
kif, &key, PF_EXT_GWY); \
else \
- *state = pf_find_state_recurse( \
+ *state = pf_find_state_recurse( \
kif, &key, PF_LAN_EXT); \
- if (*state == NULL) \
+ if (*state == NULL || (*state)->timeout == PFTM_PURGE) \
return (PF_DROP); \
if (direction == PF_OUT && \
(((*state)->rule.ptr->rt == PF_ROUTETO && \
@@ -589,6 +595,128 @@ pf_find_state_all(struct pf_state *key, u_int8_t tree, int *more)
}
}
+void
+pf_init_threshold(struct pf_threshold *threshold,
+ u_int32_t limit, u_int32_t seconds)
+{
+ threshold->limit = limit * PF_THRESHOLD_MULT;
+ threshold->seconds = seconds;
+ threshold->count = 0;
+ threshold->last = time_second;
+}
+
+void
+pf_add_threshold(struct pf_threshold *threshold)
+{
+ u_int32_t t = time_second, diff = t - threshold->last;
+
+ if (diff >= threshold->seconds)
+ threshold->count = 0;
+ else
+ threshold->count -= threshold->count * diff /
+ threshold->seconds;
+ threshold->count += PF_THRESHOLD_MULT;
+ threshold->last = t;
+}
+
+int
+pf_check_threshold(struct pf_threshold *threshold)
+{
+ return (threshold->count > threshold->limit);
+}
+
+int
+pf_src_connlimit(struct pf_state **state)
+{
+ struct pf_state *s;
+ int bad = 0;
+
+ (*state)->src_node->conn++;
+ pf_add_threshold(&(*state)->src_node->conn_rate);
+
+ if ((*state)->rule.ptr->max_src_conn &&
+ (*state)->rule.ptr->max_src_conn <
+ (*state)->src_node->conn) {
+ pf_status.lcounters[LCNT_SRCCONN]++;
+ bad++;
+ }
+
+ if ((*state)->rule.ptr->max_src_conn_rate.limit &&
+ pf_check_threshold(&(*state)->src_node->conn_rate)) {
+ pf_status.lcounters[LCNT_SRCCONNRATE]++;
+ bad++;
+ }
+
+ if (!bad)
+ return (0);
+
+ if ((*state)->rule.ptr->overload_tbl) {
+ struct pfr_addr p;
+ u_int32_t killed = 0;
+
+ pf_status.lcounters[LCNT_OVERLOAD_TABLE]++;
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf_src_connlimit: blocking address ");
+ pf_print_host(&(*state)->src_node->addr, 0,
+ (*state)->af);
+ }
+
+ bzero(&p, sizeof(p));
+ p.pfra_af = (*state)->af;
+ switch ((*state)->af) {
+#ifdef INET
+ case AF_INET:
+ p.pfra_net = 32;
+ p.pfra_ip4addr = (*state)->src_node->addr.v4;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ p.pfra_net = 128;
+ p.pfra_ip6addr = (*state)->src_node->addr.v6;
+ break;
+#endif /* INET6 */
+ }
+
+ pfr_insert_kentry((*state)->rule.ptr->overload_tbl,
+ &p, time_second);
+
+ /* kill existing states if that's required. */
+ if ((*state)->rule.ptr->rule_flag & PFRULE_SRCTRACK_FLUSH) {
+ pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
+
+ RB_FOREACH(s, pf_state_tree_id, &tree_id) {
+ /*
+ * Kill all states from this source.
+ *
+ * XXX Kill states _to_ the source?
+ */
+ if (s->af == (*state)->af &&
+ (((*state)->direction == PF_OUT &&
+ PF_AEQ(&(*state)->src_node->addr,
+ &s->lan.addr, s->af)) ||
+ ((*state)->direction == PF_IN &&
+ PF_AEQ(&(*state)->src_node->addr,
+ &s->ext.addr, s->af)))) {
+ s->timeout = PFTM_PURGE;
+ s->src.state = s->dst.state =
+ TCPS_CLOSED;
+ killed++;
+ }
+ }
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf(", %u states killed", killed);
+ }
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("\n");
+ }
+
+ /* kill this state */
+ (*state)->timeout = PFTM_PURGE;
+ (*state)->src.state = (*state)->dst.state = TCPS_CLOSED;
+ return (1);
+}
+
int
pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
struct pf_addr *src, sa_family_t af)
@@ -610,9 +738,16 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
if (!rule->max_src_nodes ||
rule->src_nodes < rule->max_src_nodes)
(*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT);
+ else
+ pf_status.lcounters[LCNT_SRCNODES]++;
if ((*sn) == NULL)
return (-1);
bzero(*sn, sizeof(struct pf_src_node));
+
+ pf_init_threshold(&(*sn)->conn_rate,
+ rule->max_src_conn_rate.limit,
+ rule->max_src_conn_rate.seconds);
+
(*sn)->af = af;
if (rule->rule_flag & PFRULE_RULESRCTRACK ||
rule->rpool.opts & PF_POOL_STICKYADDR)
@@ -638,8 +773,10 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
pf_status.src_nodes++;
} else {
if (rule->max_src_states &&
- (*sn)->states >= rule->max_src_states)
+ (*sn)->states >= rule->max_src_states) {
+ pf_status.lcounters[LCNT_SRCSTATES]++;
return (-1);
+ }
}
return (0);
}
@@ -796,6 +933,10 @@ pf_src_tree_remove_state(struct pf_state *s)
u_int32_t timeout;
if (s->src_node != NULL) {
+ if (s->proto == IPPROTO_TCP) {
+ if (s->timeout >= PFTM_TCP_ESTABLISHED )
+ --s->src_node->conn;
+ }
if (--s->src_node->states <= 0) {
timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
if (!timeout)
@@ -2700,8 +2841,10 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
len = pd->tot_len - off - (th->th_off << 2);
/* check maximums */
- if (r->max_states && (r->states >= r->max_states))
+ if (r->max_states && (r->states >= r->max_states)) {
+ pf_status.lcounters[LCNT_STATES]++;
goto cleanup;
+ }
/* src node for flter rule */
if ((r->rule_flag & PFRULE_SRCTRACK ||
r->rpool.opts & PF_POOL_STICKYADDR) &&
@@ -3040,8 +3183,10 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pf_src_node *sn = NULL;
/* check maximums */
- if (r->max_states && (r->states >= r->max_states))
+ if (r->max_states && (r->states >= r->max_states)) {
+ pf_status.lcounters[LCNT_STATES]++;
goto cleanup;
+ }
/* src node for flter rule */
if ((r->rule_flag & PFRULE_SRCTRACK ||
r->rpool.opts & PF_POOL_STICKYADDR) &&
@@ -3323,8 +3468,10 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pf_src_node *sn = NULL;
/* check maximums */
- if (r->max_states && (r->states >= r->max_states))
+ if (r->max_states && (r->states >= r->max_states)) {
+ pf_status.lcounters[LCNT_STATES]++;
goto cleanup;
+ }
/* src node for flter rule */
if ((r->rule_flag & PFRULE_SRCTRACK ||
r->rpool.opts & PF_POOL_STICKYADDR) &&
@@ -3586,8 +3733,10 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pf_src_node *sn = NULL;
/* check maximums */
- if (r->max_states && (r->states >= r->max_states))
+ if (r->max_states && (r->states >= r->max_states)) {
+ pf_status.lcounters[LCNT_STATES]++;
goto cleanup;
+ }
/* src node for flter rule */
if ((r->rule_flag & PFRULE_SRCTRACK ||
r->rpool.opts & PF_POOL_STICKYADDR) &&
@@ -4033,8 +4182,13 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
else if (src->state >= TCPS_CLOSING ||
dst->state >= TCPS_CLOSING)
(*state)->timeout = PFTM_TCP_CLOSING;
- else
+ else {
+ if ((*state)->timeout != PFTM_TCP_ESTABLISHED &&
+ (*state)->src_node != NULL &&
+ pf_src_connlimit(state))
+ return (PF_DROP);
(*state)->timeout = PFTM_TCP_ESTABLISHED;
+ }
/* Fall through to PASS packet */
@@ -4140,7 +4294,6 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
return (PF_DROP);
}
-
/* Any packets which have gotten here are to be passed */
/* translate source/destination address, if necessary */
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 6ee6fc5973a..2058cf21494 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.132 2004/12/01 23:22:43 dhartmei Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.133 2004/12/04 07:49:48 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -575,6 +575,8 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
*/
pf_tbladdr_remove(&rule->src.addr);
pf_tbladdr_remove(&rule->dst.addr);
+ if (rule->overload_tbl)
+ pfr_detach_table(rule->overload_tbl);
}
TAILQ_REMOVE(rulequeue, rule, entries);
rule->entries.tqe_prev = NULL;
@@ -596,6 +598,8 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
if (rulequeue == NULL) {
pf_tbladdr_remove(&rule->src.addr);
pf_tbladdr_remove(&rule->dst.addr);
+ if (rule->overload_tbl)
+ pfr_detach_table(rule->overload_tbl);
}
pfi_detach_rule(rule->kif);
pf_anchor_remove(rule);
@@ -1178,6 +1182,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (pf_tbladdr_setup(ruleset, &pa->addr))
error = EINVAL;
+ if (rule->overload_tblname[0] &&
+ (rule->overload_tbl = pfr_attach_table(ruleset,
+ rule->overload_tblname)) == NULL)
+ error = EINVAL;
+
pf_mv_pool(&pf_pabuf, &rule->rpool.list);
if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
(rule->action == PF_BINAT)) && rule->anchor == NULL) ||
@@ -1385,6 +1394,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
error = EINVAL;
+ if (newrule->overload_tblname[0] &&
+ (newrule->overload_tbl = pfr_attach_table(ruleset,
+ newrule->overload_tblname)) == NULL)
+ error = EINVAL;
+
pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
if (((((newrule->action == PF_NAT) ||
(newrule->action == PF_RDR) ||
@@ -2615,7 +2629,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
p = psn->psn_src_nodes;
RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
- int secs = time_second;
+ int secs = time_second, diff;
if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
break;
@@ -2628,6 +2642,16 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pstore.expire -= secs;
else
pstore.expire = 0;
+
+ /* adjust the connection rate estimate */
+ diff = secs - n->conn_rate.last;
+ if (diff >= n->conn_rate.seconds)
+ pstore.conn_rate.count = 0;
+ else
+ pstore.conn_rate.count -=
+ n->conn_rate.count * diff /
+ n->conn_rate.seconds;
+
error = copyout(&pstore, p, sizeof(*p));
if (error)
goto fail;
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
index 6bc025b3c2f..e01ad9fdb7d 100644
--- a/sys/net/pf_table.c
+++ b/sys/net/pf_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_table.c,v 1.60 2004/10/15 00:15:06 jaredy Exp $ */
+/* $OpenBSD: pf_table.c,v 1.61 2004/12/04 07:49:48 mcbride Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -125,6 +125,7 @@ struct pfr_walktree {
struct pool pfr_ktable_pl;
struct pool pfr_kentry_pl;
+struct pool pfr_kentry_pl2;
struct sockaddr_in pfr_sin;
struct sockaddr_in6 pfr_sin6;
union sockaddr_union pfr_mask;
@@ -138,7 +139,7 @@ void pfr_enqueue_addrs(struct pfr_ktable *,
void pfr_mark_addrs(struct pfr_ktable *);
struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *,
struct pfr_addr *, int);
-struct pfr_kentry *pfr_create_kentry(struct pfr_addr *);
+struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, int);
void pfr_destroy_kentries(struct pfr_kentryworkq *);
void pfr_destroy_kentry(struct pfr_kentry *);
void pfr_insert_kentries(struct pfr_ktable *,
@@ -191,6 +192,8 @@ pfr_initialize(void)
"pfrktable", &pool_allocator_oldnointr);
pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0,
"pfrkentry", &pool_allocator_oldnointr);
+ pool_init(&pfr_kentry_pl2, sizeof(struct pfr_kentry), 0, 0, 0,
+ "pfrkentry2", NULL);
pfr_sin.sin_len = sizeof(pfr_sin);
pfr_sin.sin_family = AF_INET;
@@ -273,7 +276,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
ad.pfra_fback = PFR_FB_NONE;
}
if (p == NULL && q == NULL) {
- p = pfr_create_kentry(&ad);
+ p = pfr_create_kentry(&ad, 0);
if (p == NULL)
senderr(ENOMEM);
if (pfr_route_kentry(tmpkt, p)) {
@@ -449,7 +452,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
ad.pfra_fback = PFR_FB_DUPLICATE;
goto _skip;
}
- p = pfr_create_kentry(&ad);
+ p = pfr_create_kentry(&ad, 0);
if (p == NULL)
senderr(ENOMEM);
if (pfr_route_kentry(tmpkt, p)) {
@@ -790,11 +793,14 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
}
struct pfr_kentry *
-pfr_create_kentry(struct pfr_addr *ad)
+pfr_create_kentry(struct pfr_addr *ad, int intr)
{
struct pfr_kentry *ke;
- ke = pool_get(&pfr_kentry_pl, PR_NOWAIT);
+ if (intr)
+ ke = pool_get(&pfr_kentry_pl2, PR_NOWAIT);
+ else
+ ke = pool_get(&pfr_kentry_pl, PR_NOWAIT);
if (ke == NULL)
return (NULL);
bzero(ke, sizeof(*ke));
@@ -806,6 +812,7 @@ pfr_create_kentry(struct pfr_addr *ad)
ke->pfrke_af = ad->pfra_af;
ke->pfrke_net = ad->pfra_net;
ke->pfrke_not = ad->pfra_not;
+ ke->pfrke_intrpool = intr;
return (ke);
}
@@ -823,7 +830,10 @@ pfr_destroy_kentries(struct pfr_kentryworkq *workq)
void
pfr_destroy_kentry(struct pfr_kentry *ke)
{
- pool_put(&pfr_kentry_pl, ke);
+ if (ke->pfrke_intrpool)
+ pool_put(&pfr_kentry_pl2, ke);
+ else
+ pool_put(&pfr_kentry_pl, ke);
}
void
@@ -846,6 +856,29 @@ pfr_insert_kentries(struct pfr_ktable *kt,
kt->pfrkt_cnt += n;
}
+int
+pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, long tzero)
+{
+ struct pfr_kentry *p;
+ int rv;
+
+ p = pfr_lookup_addr(kt, ad, 1);
+ if (p != NULL)
+ return (0);
+ p = pfr_create_kentry(ad, 1);
+ if (p == NULL)
+ return (EINVAL);
+
+ rv = pfr_route_kentry(kt, p);
+ if (rv)
+ return (rv);
+
+ p->pfrke_tzero = tzero;
+ kt->pfrkt_cnt++;
+
+ return (0);
+}
+
void
pfr_remove_kentries(struct pfr_ktable *kt,
struct pfr_kentryworkq *workq)
@@ -1500,7 +1533,7 @@ _skip:
senderr(EINVAL);
if (pfr_lookup_addr(shadow, &ad, 1) != NULL)
continue;
- p = pfr_create_kentry(&ad);
+ p = pfr_create_kentry(&ad, 0);
if (p == NULL)
senderr(ENOMEM);
if (pfr_route_kentry(shadow, p)) {
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 208e6ac0af5..3c385a966c3 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.204 2004/11/16 20:07:57 mcbride Exp $ */
+/* $OpenBSD: pfvar.h,v 1.205 2004/12/04 07:49:48 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -470,6 +470,8 @@ struct pf_rule {
char tagname[PF_TAG_NAME_SIZE];
char match_tagname[PF_TAG_NAME_SIZE];
+ char overload_tblname[PF_TABLE_NAME_SIZE];
+
TAILQ_ENTRY(pf_rule) entries;
struct pf_pool rpool;
@@ -479,6 +481,7 @@ struct pf_rule {
struct pfi_kif *kif;
struct pf_anchor *anchor;
+ struct pfr_ktable *overload_tbl;
pf_osfp_t os_fingerprint;
@@ -488,6 +491,11 @@ struct pf_rule {
u_int32_t src_nodes;
u_int32_t max_src_nodes;
u_int32_t max_src_states;
+ u_int32_t max_src_conn;
+ struct {
+ u_int32_t limit;
+ u_int32_t seconds;
+ } max_src_conn_rate;
u_int32_t qid;
u_int32_t pqid;
u_int32_t rt_listid;
@@ -540,6 +548,7 @@ struct pf_rule {
#define PFRULE_NOSYNC 0x0010
#define PFRULE_SRCTRACK 0x0020 /* track source states */
#define PFRULE_RULESRCTRACK 0x0040 /* per rule */
+#define PFRULE_SRCTRACK_FLUSH 0x0080 /* flush for src_node->open_states */
/* scrub flags */
#define PFRULE_NODF 0x0100
@@ -554,6 +563,16 @@ struct pf_rule {
#define PFSTATE_HIWAT 10000 /* default state table size */
+
+struct pf_threshold {
+ u_int32_t limit;
+#define PF_THRESHOLD_MULT 1000
+#define PF_THRESHOLD_MAX 0xffffffff / PF_THRESHOLD_MULT
+ u_int32_t seconds;
+ u_int32_t count;
+ u_int32_t last;
+};
+
struct pf_src_node {
RB_ENTRY(pf_src_node) entry;
struct pf_addr addr;
@@ -563,6 +582,8 @@ struct pf_src_node {
u_int32_t bytes;
u_int32_t packets;
u_int32_t states;
+ u_int32_t conn;
+ struct pf_threshold conn_rate;
u_int32_t creation;
u_int32_t expire;
sa_family_t af;
@@ -757,6 +778,7 @@ struct pfr_kentry {
u_int8_t pfrke_net;
u_int8_t pfrke_not;
u_int8_t pfrke_mark;
+ u_int8_t pfrke_intrpool;
};
SLIST_HEAD(pfr_ktableworkq, pfr_ktable);
@@ -894,6 +916,27 @@ struct pf_pdesc {
NULL \
}
+/* Counters for other things we want to keep track of */
+#define LCNT_STATES 0 /* states */
+#define LCNT_SRCSTATES 1 /* max-src-states */
+#define LCNT_SRCNODES 2 /* max-src-nodes */
+#define LCNT_SRCCONN 3 /* max-src-conn */
+#define LCNT_SRCCONNRATE 4 /* max-src-conn-rate */
+#define LCNT_OVERLOAD_TABLE 5 /* entry added to overload table */
+#define LCNT_OVERLOAD_FLUSH 6 /* state entries flushed */
+#define LCNT_MAX 7 /* total+1 */
+
+#define LCNT_NAMES { \
+ "max states per rule", \
+ "max-src-states", \
+ "max-src-nodes", \
+ "max-src-conn", \
+ "max-src-conn-rate", \
+ "overload table insertion", \
+ "overload flush states", \
+ NULL \
+}
+
/* UDP state enumeration */
#define PFUDPS_NO_TRAFFIC 0
#define PFUDPS_SINGLE 1
@@ -948,6 +991,7 @@ struct pf_pdesc {
struct pf_status {
u_int64_t counters[PFRES_MAX];
+ u_int64_t lcounters[LCNT_MAX]; /* limit counters */
u_int64_t fcounters[FCNT_MAX];
u_int64_t scounters[SCNT_MAX];
u_int64_t pcounters[2][2][3];
@@ -1399,6 +1443,7 @@ int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, int *, int);
int pfr_clr_tstats(struct pfr_table *, int, int *, int);
int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
int pfr_clr_addrs(struct pfr_table *, int *, int);
+int pfr_insert_kentry(struct pfr_ktable *, struct pfr_addr *, long);
int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
int);
int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *,