aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/pf/net/pf_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/pf/net/pf_table.c')
-rw-r--r--sys/contrib/pf/net/pf_table.c335
1 files changed, 194 insertions, 141 deletions
diff --git a/sys/contrib/pf/net/pf_table.c b/sys/contrib/pf/net/pf_table.c
index e192004ac77a..7e7ee69a47c2 100644
--- a/sys/contrib/pf/net/pf_table.c
+++ b/sys/contrib/pf/net/pf_table.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $OpenBSD: pf_table.c,v 1.47 2004/03/09 21:44:41 mcbride Exp $ */
+/* $OpenBSD: pf_table.c,v 1.62 2004/12/07 18:02:04 mcbride Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -177,9 +177,11 @@ struct pfr_walktree {
#ifdef __FreeBSD__
uma_zone_t pfr_ktable_pl;
uma_zone_t pfr_kentry_pl;
+uma_zone_t pfr_kentry_pl2;
#else
struct pool pfr_ktable_pl;
struct pool pfr_kentry_pl;
+struct pool pfr_kentry_pl2;
#endif
struct sockaddr_in pfr_sin;
struct sockaddr_in6 pfr_sin6;
@@ -194,7 +196,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 *,
@@ -211,6 +213,7 @@ int pfr_unroute_kentry(struct pfr_ktable *,
struct pfr_kentry *);
int pfr_walktree(struct radix_node *, void *);
int pfr_validate_table(struct pfr_table *, int, int);
+int pfr_fix_anchor(char *);
void pfr_commit_ktable(struct pfr_ktable *, long);
void pfr_insert_ktables(struct pfr_ktableworkq *);
void pfr_insert_ktable(struct pfr_ktable *);
@@ -244,9 +247,11 @@ pfr_initialize(void)
{
#ifndef __FreeBSD__
pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0,
- "pfrktable", NULL);
+ "pfrktable", &pool_allocator_oldnointr);
pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0,
- "pfrkentry", NULL);
+ "pfrkentry", &pool_allocator_oldnointr);
+ pool_init(&pfr_kentry_pl2, sizeof(struct pfr_kentry), 0, 0, 0,
+ "pfrkentry2", NULL);
#endif
pfr_sin.sin_len = sizeof(pfr_sin);
@@ -298,15 +303,8 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentryworkq workq;
struct pfr_kentry *p, *q;
struct pfr_addr ad;
- int i, rv, s = 0, xadd = 0;
-#ifdef __FreeBSD__
- /*
- * XXX Is it OK under LP64 environments?
- */
- long tzero = (long)time_second;
-#else
- long tzero = time.tv_sec;
-#endif
+ int i, rv, s, xadd = 0;
+ long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
@@ -338,7 +336,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)) {
@@ -384,7 +382,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentryworkq workq;
struct pfr_kentry *p;
struct pfr_addr ad;
- int i, rv, s = 0, xdel = 0;
+ int i, rv, s, xdel = 0, log = 1;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
@@ -394,7 +392,34 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (ESRCH);
if (kt->pfrkt_flags & PFR_TFLAG_CONST)
return (EPERM);
- pfr_mark_addrs(kt);
+ /*
+ * there are two algorithms to choose from here.
+ * with:
+ * n: number of addresses to delete
+ * N: number of addresses in the table
+ *
+ * one is O(N) and is better for large 'n'
+ * one is O(n*LOG(N)) and is better for small 'n'
+ *
+ * following code try to decide which one is best.
+ */
+ for (i = kt->pfrkt_cnt; i > 0; i >>= 1)
+ log++;
+ if (size > kt->pfrkt_cnt/log) {
+ /* full table scan */
+ pfr_mark_addrs(kt);
+ } else {
+ /* iterate over addresses to delete */
+ for (i = 0; i < size; i++) {
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
+ return (EFAULT);
+ if (pfr_validate_addr(&ad))
+ return (EINVAL);
+ p = pfr_lookup_addr(kt, &ad, 1);
+ if (p != NULL)
+ p->pfrke_mark = 0;
+ }
+ }
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
if (COPYIN(addr+i, &ad, sizeof(ad)))
@@ -446,15 +471,8 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentryworkq addq, delq, changeq;
struct pfr_kentry *p, *q;
struct pfr_addr ad;
- int i, rv, s = 0, xadd = 0, xdel = 0, xchange = 0;
-#ifdef __FreeBSD__
- /*
- * XXX Is it OK under LP64 environments?
- */
- long tzero = (long)time_second;
-#else
- long tzero = time.tv_sec;
-#endif
+ int i, rv, s, xadd = 0, xdel = 0, xchange = 0;
+ long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
@@ -495,7 +513,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)) {
@@ -650,15 +668,8 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
struct pfr_ktable *kt;
struct pfr_walktree w;
struct pfr_kentryworkq workq;
- int rv, s = 0;
-#ifdef __FreeBSD__
- /*
- * XXX Is it OK under LP64 environments?
- */
- long tzero = (long)time_second;
-#else
- long tzero = time.tv_sec;
-#endif
+ int rv, s;
+ long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
if (pfr_validate_table(tbl, 0, 0))
@@ -765,14 +776,18 @@ pfr_validate_addr(struct pfr_addr *ad)
int i;
switch (ad->pfra_af) {
+#ifdef INET
case AF_INET:
if (ad->pfra_net > 32)
return (-1);
break;
+#endif /* INET */
+#ifdef INET6
case AF_INET6:
if (ad->pfra_net > 128)
return (-1);
break;
+#endif /* INET6 */
default:
return (-1);
}
@@ -845,7 +860,7 @@ struct pfr_kentry *
pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
{
union sockaddr_union sa, mask;
- struct radix_node_head *head;
+ struct radix_node_head *head = NULL; /* make the compiler happy */
struct pfr_kentry *ke;
int s;
@@ -853,7 +868,7 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
if (ad->pfra_af == AF_INET) {
FILLIN_SIN(sa.sin, ad->pfra_ip4addr);
head = kt->pfrkt_ip4;
- } else {
+ } else if ( ad->pfra_af == AF_INET6 ) {
FILLIN_SIN6(sa.sin6, ad->pfra_ip6addr);
head = kt->pfrkt_ip6;
}
@@ -881,22 +896,26 @@ 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));
if (ad->pfra_af == AF_INET)
FILLIN_SIN(ke->pfrke_sa.sin, ad->pfra_ip4addr);
- else
+ else if (ad->pfra_af == AF_INET6)
FILLIN_SIN6(ke->pfrke_sa.sin6, ad->pfra_ip6addr);
ke->pfrke_af = ad->pfra_af;
ke->pfrke_net = ad->pfra_net;
ke->pfrke_not = ad->pfra_not;
+ ke->pfrke_intrpool = intr;
return (ke);
}
@@ -914,7 +933,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
@@ -937,6 +959,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)
@@ -1003,14 +1048,14 @@ pfr_prepare_network(union sockaddr_union *sa, int af, int net)
if (af == AF_INET) {
sa->sin.sin_len = sizeof(sa->sin);
sa->sin.sin_family = AF_INET;
- sa->sin.sin_addr.s_addr = htonl(-1 << (32-net));
- } else {
+ sa->sin.sin_addr.s_addr = net ? htonl(-1 << (32-net)) : 0;
+ } else if (af == AF_INET6) {
sa->sin6.sin6_len = sizeof(sa->sin6);
sa->sin6.sin6_family = AF_INET6;
for (i = 0; i < 4; i++) {
if (net <= 32) {
sa->sin6.sin6_addr.s6_addr32[i] =
- htonl(-1 << (32-net));
+ net ? htonl(-1 << (32-net)) : 0;
break;
}
sa->sin6.sin6_addr.s6_addr32[i] = 0xFFFFFFFF;
@@ -1024,13 +1069,13 @@ pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
{
union sockaddr_union mask;
struct radix_node *rn;
- struct radix_node_head *head;
+ struct radix_node_head *head = NULL; /* make the compiler happy */
int s;
bzero(ke->pfrke_node, sizeof(ke->pfrke_node));
if (ke->pfrke_af == AF_INET)
head = kt->pfrkt_ip4;
- else
+ else if (ke->pfrke_af == AF_INET6)
head = kt->pfrkt_ip6;
s = splsoftnet();
@@ -1055,12 +1100,12 @@ pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
{
union sockaddr_union mask;
struct radix_node *rn;
- struct radix_node_head *head;
+ struct radix_node_head *head = NULL; /* make the compiler happy */
int s;
if (ke->pfrke_af == AF_INET)
head = kt->pfrkt_ip4;
- else
+ else if (ke->pfrke_af == AF_INET6)
head = kt->pfrkt_ip6;
s = splsoftnet();
@@ -1069,9 +1114,17 @@ pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
#endif
if (KENTRY_NETWORK(ke)) {
pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
+#ifdef __FreeBSD__
rn = rn_delete(&ke->pfrke_sa, &mask, head);
+#else
+ rn = rn_delete(&ke->pfrke_sa, &mask, head, NULL);
+#endif
} else
+#ifdef __FreeBSD__
rn = rn_delete(&ke->pfrke_sa, NULL, head);
+#else
+ rn = rn_delete(&ke->pfrke_sa, NULL, head, NULL);
+#endif
#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
RADIX_NODE_HEAD_UNLOCK(head);
#endif
@@ -1095,7 +1148,7 @@ pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke)
ad->pfra_not = ke->pfrke_not;
if (ad->pfra_af == AF_INET)
ad->pfra_ip4addr = ke->pfrke_sa.sin.sin_addr;
- else
+ else if (ad->pfra_af == AF_INET6)
ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr;
}
@@ -1164,7 +1217,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
&ke->pfrke_sa, AF_INET);
w->pfrw_dyn->pfid_mask4 = *SUNION2PF(
&pfr_mask, AF_INET);
- } else {
+ } else if (ke->pfrke_af == AF_INET6){
if (w->pfrw_dyn->pfid_acnt6++ > 0)
break;
pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net);
@@ -1186,6 +1239,8 @@ pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
int s = 0, xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ALLRSETS);
+ if (pfr_fix_anchor(filter->pfrt_anchor))
+ return (EINVAL);
if (pfr_table_count(filter, flags) < 0)
return (ENOENT);
@@ -1218,15 +1273,8 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
{
struct pfr_ktableworkq addq, changeq;
struct pfr_ktable *p, *q, *r, key;
- int i, rv, s = 0, xadd = 0;
-#ifdef __FreeBSD__
- /*
- * XXX Is it OK under LP64 environments?
- */
- long tzero = (long)time_second;
-#else
- long tzero = time.tv_sec;
-#endif
+ int i, rv, s, xadd = 0;
+ long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
SLIST_INIT(&addq);
@@ -1254,7 +1302,6 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
/* find or create root table */
bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor));
- bzero(key.pfrkt_ruleset, sizeof(key.pfrkt_ruleset));
r = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (r != NULL) {
p->pfrkt_root = r;
@@ -1349,6 +1396,8 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
int n, nn;
ACCEPT_FLAGS(PFR_FLAG_ALLRSETS);
+ if (pfr_fix_anchor(filter->pfrt_anchor))
+ return (EINVAL);
n = nn = pfr_table_count(filter, flags);
if (n < 0)
return (ENOENT);
@@ -1378,18 +1427,13 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
{
struct pfr_ktable *p;
struct pfr_ktableworkq workq;
- int s = 0, n, nn;
-#ifdef __FreeBSD__
- /*
- * XXX Is it OK under LP64 environments?
- */
- long tzero = (long)time_second;
-#else
- long tzero = time.tv_sec;
-#endif
+ int s, n, nn;
+ long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC|PFR_FLAG_ALLRSETS);
/* XXX PFR_FLAG_CLSTATS disabled */
+ if (pfr_fix_anchor(filter->pfrt_anchor))
+ return (EINVAL);
n = nn = pfr_table_count(filter, flags);
if (n < 0)
return (ENOENT);
@@ -1434,15 +1478,8 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
{
struct pfr_ktableworkq workq;
struct pfr_ktable *p, key;
- int i, s = 0, xzero = 0;
-#ifdef __FreeBSD__
- /*
- * XXX Is it OK under LP64 environments?
- */
- long tzero = (long)time_second;
-#else
- long tzero = time.tv_sec;
-#endif
+ int i, s, xzero = 0;
+ long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO);
SLIST_INIT(&workq);
@@ -1532,7 +1569,7 @@ pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
int xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_DUMMY);
- rs = pf_find_or_create_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
+ rs = pf_find_or_create_ruleset(trs->pfrt_anchor);
if (rs == NULL)
return (ENOMEM);
SLIST_INIT(&workq);
@@ -1574,7 +1611,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
- rs = pf_find_ruleset(tbl->pfrt_anchor, tbl->pfrt_ruleset);
+ rs = pf_find_ruleset(tbl->pfrt_anchor);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (EBUSY);
tbl->pfrt_flags |= PFR_TFLAG_INACTIVE;
@@ -1620,7 +1657,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)) {
@@ -1665,7 +1702,7 @@ pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
int xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_DUMMY);
- rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
+ rs = pf_find_ruleset(trs->pfrt_anchor);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (0);
SLIST_INIT(&workq);
@@ -1691,21 +1728,14 @@ int
pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
int *nchange, int flags)
{
- struct pfr_ktable *p;
+ struct pfr_ktable *p, *q;
struct pfr_ktableworkq workq;
struct pf_ruleset *rs;
- int s = 0, xadd = 0, xchange = 0;
-#ifdef __FreeBSD__
- /*
- * XXX Is it OK under LP64 environments?
- */
- long tzero = (long)time_second;
-#else
- long tzero = time.tv_sec;
-#endif
+ int s, xadd = 0, xchange = 0;
+ long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
- rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
+ rs = pf_find_ruleset(trs->pfrt_anchor);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (EBUSY);
@@ -1724,8 +1754,10 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
if (!(flags & PFR_FLAG_DUMMY)) {
if (flags & PFR_FLAG_ATOMIC)
s = splsoftnet();
- SLIST_FOREACH(p, &workq, pfrkt_workq)
+ for (p = SLIST_FIRST(&workq); p != NULL; p = q) {
+ q = SLIST_NEXT(p, pfrkt_workq);
pfr_commit_ktable(p, tzero);
+ }
if (flags & PFR_FLAG_ATOMIC)
splx(s);
rs->topen = 0;
@@ -1812,27 +1844,52 @@ pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++)
if (tbl->pfrt_name[i])
return (-1);
+ if (pfr_fix_anchor(tbl->pfrt_anchor))
+ return (-1);
if (tbl->pfrt_flags & ~allowedflags)
return (-1);
return (0);
}
+/*
+ * Rewrite anchors referenced by tables to remove slashes
+ * and check for validity.
+ */
+int
+pfr_fix_anchor(char *anchor)
+{
+ size_t siz = MAXPATHLEN;
+ int i;
+
+ if (anchor[0] == '/') {
+ char *path;
+ int off;
+
+ path = anchor;
+ off = 1;
+ while (*++path == '/')
+ off++;
+ bcopy(path, anchor, siz - off);
+ memset(anchor + siz - off, 0, off);
+ }
+ if (anchor[siz - 1])
+ return (-1);
+ for (i = strlen(anchor); i < siz; i++)
+ if (anchor[i])
+ return (-1);
+ return (0);
+}
+
int
pfr_table_count(struct pfr_table *filter, int flags)
{
struct pf_ruleset *rs;
- struct pf_anchor *ac;
if (flags & PFR_FLAG_ALLRSETS)
return (pfr_ktable_cnt);
- if (filter->pfrt_ruleset[0]) {
- rs = pf_find_ruleset(filter->pfrt_anchor,
- filter->pfrt_ruleset);
- return ((rs != NULL) ? rs->tables : -1);
- }
if (filter->pfrt_anchor[0]) {
- ac = pf_find_anchor(filter->pfrt_anchor);
- return ((ac != NULL) ? ac->tables : -1);
+ rs = pf_find_ruleset(filter->pfrt_anchor);
+ return ((rs != NULL) ? rs->tables : -1);
}
return (pf_main_ruleset.tables);
}
@@ -1842,13 +1899,7 @@ pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags)
{
if (flags & PFR_FLAG_ALLRSETS)
return (0);
- if (strncmp(filter->pfrt_anchor, kt->pfrkt_anchor,
- PF_ANCHOR_NAME_SIZE))
- return (1);
- if (!filter->pfrt_ruleset[0])
- return (0);
- if (strncmp(filter->pfrt_ruleset, kt->pfrkt_ruleset,
- PF_RULESET_NAME_SIZE))
+ if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor))
return (1);
return (0);
}
@@ -1876,10 +1927,12 @@ pfr_insert_ktable(struct pfr_ktable *kt)
void
pfr_setflags_ktables(struct pfr_ktableworkq *workq)
{
- struct pfr_ktable *p;
+ struct pfr_ktable *p, *q;
- SLIST_FOREACH(p, workq, pfrkt_workq)
+ for (p = SLIST_FIRST(workq); p; p = q) {
+ q = SLIST_NEXT(p, pfrkt_workq);
pfr_setflags_ktable(p, p->pfrkt_nflags);
+ }
}
void
@@ -1954,16 +2007,13 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
kt->pfrkt_t = *tbl;
if (attachruleset) {
- rs = pf_find_or_create_ruleset(tbl->pfrt_anchor,
- tbl->pfrt_ruleset);
+ rs = pf_find_or_create_ruleset(tbl->pfrt_anchor);
if (!rs) {
pfr_destroy_ktable(kt, 0);
return (NULL);
}
kt->pfrkt_rs = rs;
rs->tables++;
- if (rs->anchor != NULL)
- rs->anchor->tables++;
}
if (!rn_inithead((void **)&kt->pfrkt_ip4,
@@ -2018,8 +2068,6 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
if (kt->pfrkt_rs != NULL) {
kt->pfrkt_rs->tables--;
- if (kt->pfrkt_rs->anchor != NULL)
- kt->pfrkt_rs->anchor->tables--;
pf_remove_if_empty_ruleset(kt->pfrkt_rs);
}
pool_put(&pfr_ktable_pl, kt);
@@ -2032,11 +2080,7 @@ pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE)))
return (d);
- if ((d = strncmp(p->pfrkt_anchor, q->pfrkt_anchor,
- PF_ANCHOR_NAME_SIZE)))
- return (d);
- return (strncmp(p->pfrkt_ruleset, q->pfrkt_ruleset,
- PF_RULESET_NAME_SIZE));
+ return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor));
}
struct pfr_ktable *
@@ -2059,18 +2103,22 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
return (0);
switch (af) {
+#ifdef INET
case AF_INET:
pfr_sin.sin_addr.s_addr = a->addr32[0];
ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
if (ke && KENTRY_RNF_ROOT(ke))
ke = NULL;
break;
+#endif /* INET */
+#ifdef INET6
case AF_INET6:
bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
if (ke && KENTRY_RNF_ROOT(ke))
ke = NULL;
break;
+#endif /* INET6 */
}
match = (ke && !ke->pfrke_not);
if (match)
@@ -2092,18 +2140,24 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
return;
switch (af) {
+#ifdef INET
case AF_INET:
pfr_sin.sin_addr.s_addr = a->addr32[0];
ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
if (ke && KENTRY_RNF_ROOT(ke))
ke = NULL;
break;
+#endif /* INET */
+#ifdef INET6
case AF_INET6:
bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
if (ke && KENTRY_RNF_ROOT(ke))
ke = NULL;
break;
+#endif /* INET6 */
+ default:
+ ;
}
if ((ke == NULL || ke->pfrke_not) != notrule) {
if (op_pass != PFR_OP_PASS)
@@ -2127,25 +2181,15 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
bzero(&tbl, sizeof(tbl));
strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name));
- if (ac != NULL) {
+ if (ac != NULL)
strlcpy(tbl.pfrt_anchor, ac->name, sizeof(tbl.pfrt_anchor));
- strlcpy(tbl.pfrt_ruleset, rs->name, sizeof(tbl.pfrt_ruleset));
- }
kt = pfr_lookup_table(&tbl);
if (kt == NULL) {
-#ifdef __FreeBSD__
- /*
- * XXX Is it OK under LP64 environments?
- */
- kt = pfr_create_ktable(&tbl, (long)time_second, 1);
-#else
- kt = pfr_create_ktable(&tbl, time.tv_sec, 1);
-#endif
+ kt = pfr_create_ktable(&tbl, time_second, 1);
if (kt == NULL)
return (NULL);
if (ac != NULL) {
bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor));
- bzero(tbl.pfrt_ruleset, sizeof(tbl.pfrt_ruleset));
rt = pfr_lookup_table(&tbl);
if (rt == NULL) {
rt = pfr_create_ktable(&tbl, 0, 1);
@@ -2179,13 +2223,15 @@ int
pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
struct pf_addr **raddr, struct pf_addr **rmask, sa_family_t af)
{
- struct pfr_kentry *ke, *ke2;
- struct pf_addr *addr;
+ struct pfr_kentry *ke, *ke2 = NULL;
+ struct pf_addr *addr = NULL;
union sockaddr_union mask;
int idx = -1, use_counter = 0;
- addr = (af == AF_INET) ? (struct pf_addr *)&pfr_sin.sin_addr :
- (struct pf_addr *)&pfr_sin6.sin6_addr;
+ if (af == AF_INET)
+ addr = (struct pf_addr *)&pfr_sin.sin_addr;
+ else if (af == AF_INET6)
+ addr = (struct pf_addr *)&pfr_sin6.sin6_addr;
if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
kt = kt->pfrkt_root;
if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -2228,9 +2274,12 @@ _next_block:
}
for (;;) {
/* we don't want to use a nested block */
- ke2 = (struct pfr_kentry *)(af == AF_INET ?
- rn_match(&pfr_sin, kt->pfrkt_ip4) :
- rn_match(&pfr_sin6, kt->pfrkt_ip6));
+ if (af == AF_INET)
+ ke2 = (struct pfr_kentry *)rn_match(&pfr_sin,
+ kt->pfrkt_ip4);
+ else if (af == AF_INET6)
+ ke2 = (struct pfr_kentry *)rn_match(&pfr_sin6,
+ kt->pfrkt_ip6);
/* no need to check KENTRY_RNF_ROOT() here */
if (ke2 == ke) {
/* lookup return the same block - perfect */
@@ -2263,6 +2312,7 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
w.pfrw_cnt = idx;
switch (af) {
+#ifdef INET
case AF_INET:
#ifdef __FreeBSD__
kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
@@ -2270,6 +2320,8 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
#endif
return (w.pfrw_kentry);
+#endif /* INET */
+#ifdef INET6
case AF_INET6:
#ifdef __FreeBSD__
kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
@@ -2277,6 +2329,7 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
#endif
return (w.pfrw_kentry);
+#endif /* INET6 */
default:
return (NULL);
}