summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorCedric Berger <cedric@cvs.openbsd.org>2003-06-08 09:41:09 +0000
committerCedric Berger <cedric@cvs.openbsd.org>2003-06-08 09:41:09 +0000
commit7b563ed48a78c7df6b888d4a74d30fa1a6592c8d (patch)
tree480d3e9d72431a30db8b3c11a6b66d060d7f4b4e /sys/net
parent40a6c2c22cc1a18eeed2736e5a15603640dab733 (diff)
A table in an anchor creates a real anchor: pfctl -sA works.
The following two pfctl functions work with an "-a" option: - pfctl [-a foo[:bar]] -sT - pfctl [-a foo[:bar]] -FT ok dhartmei@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/pf_ioctl.c19
-rw-r--r--sys/net/pf_table.c117
-rw-r--r--sys/net/pfvar.h19
3 files changed, 119 insertions, 36 deletions
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index ab2f76c8601..63bef915ec4 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.67 2003/06/03 12:34:04 henning Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.68 2003/06/08 09:41:08 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -76,10 +76,6 @@ struct pf_pool *pf_get_pool(char *, char *, u_int32_t,
u_int8_t, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
int pf_get_ruleset_number(u_int8_t);
void pf_init_ruleset(struct pf_ruleset *);
-struct pf_anchor *pf_find_anchor(const char *);
-struct pf_ruleset *pf_find_ruleset(char *, char *);
-struct pf_ruleset *pf_find_or_create_ruleset(char *, char *);
-void pf_remove_if_empty_ruleset(struct pf_ruleset *);
void pf_mv_pool(struct pf_palist *, struct pf_palist *);
void pf_empty_pool(struct pf_palist *);
int pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
@@ -354,7 +350,7 @@ pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
struct pf_anchor *anchor;
int i;
- if (ruleset == NULL || ruleset->anchor == NULL)
+ if (ruleset == NULL || ruleset->anchor == NULL || ruleset->tables > 0)
return;
for (i = 0; i < PF_RULESET_MAX; ++i)
if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
@@ -1883,7 +1879,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = ENODEV;
break;
}
- error = pfr_clr_tables(&io->pfrio_ndel, io->pfrio_flags);
+ error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
+ io->pfrio_flags);
break;
}
@@ -1918,8 +1915,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = ENODEV;
break;
}
- error = pfr_get_tables(io->pfrio_buffer, &io->pfrio_size,
- io->pfrio_flags);
+ error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
+ &io->pfrio_size, io->pfrio_flags);
break;
}
@@ -1930,8 +1927,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = ENODEV;
break;
}
- error = pfr_get_tstats(io->pfrio_buffer, &io->pfrio_size,
- io->pfrio_flags);
+ error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
+ &io->pfrio_size, io->pfrio_flags);
break;
}
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
index 150d30342f5..68294aafff5 100644
--- a/sys/net/pf_table.c
+++ b/sys/net/pf_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_table.c,v 1.35 2003/05/24 14:22:03 cedric Exp $ */
+/* $OpenBSD: pf_table.c,v 1.36 2003/06/08 09:41:08 cedric Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -140,7 +140,7 @@ void pfr_setflags_ktable(struct pfr_ktable *, int);
void pfr_clstats_ktables(struct pfr_ktableworkq *, long,
int);
void pfr_clstats_ktable(struct pfr_ktable *, long, int);
-struct pfr_ktable *pfr_create_ktable(struct pfr_table *, long);
+struct pfr_ktable *pfr_create_ktable(struct pfr_table *, long, int);
void pfr_destroy_ktables(struct pfr_ktableworkq *, int);
void pfr_destroy_ktable(struct pfr_ktable *, int);
int pfr_ktable_compare(struct pfr_ktable *,
@@ -148,6 +148,9 @@ int pfr_ktable_compare(struct pfr_ktable *,
struct pfr_ktable *pfr_lookup_table(struct pfr_table *);
void pfr_clean_node_mask(struct pfr_ktable *,
struct pfr_kentryworkq *);
+int pfr_table_count(struct pfr_table *, int);
+int pfr_skip_table(struct pfr_table *,
+ struct pfr_ktable *, int);
RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
@@ -224,7 +227,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (ESRCH);
if (kt->pfrkt_flags & PFR_TFLAG_CONST)
return (EPERM);
- tmpkt = pfr_create_ktable(&pfr_nulltable, 0);
+ tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
if (tmpkt == NULL)
return (ENOMEM);
SLIST_INIT(&workq);
@@ -364,7 +367,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (ESRCH);
if (kt->pfrkt_flags & PFR_TFLAG_CONST)
return (EPERM);
- tmpkt = pfr_create_ktable(&pfr_nulltable, 0);
+ tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
if (tmpkt == NULL)
return (ENOMEM);
pfr_mark_addrs(kt);
@@ -989,15 +992,20 @@ pfr_walktree(struct radix_node *rn, void *arg)
}
int
-pfr_clr_tables(int *ndel, int flags)
+pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
{
struct pfr_ktableworkq workq;
struct pfr_ktable *p;
int s, xdel = 0;
- ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ALLRSETS);
+ if (pfr_table_count(filter, flags) < 0)
+ return (ENOENT);
+
SLIST_INIT(&workq);
RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (pfr_skip_table(filter, p, flags))
+ continue;
if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE))
continue;
p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
@@ -1035,7 +1043,7 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
key.pfrkt_flags |= PFR_TFLAG_ACTIVE;
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p == NULL) {
- p = pfr_create_ktable(&key.pfrkt_t, tzero);
+ p = pfr_create_ktable(&key.pfrkt_t, tzero, 1);
if (p == NULL)
senderr(ENOMEM);
SLIST_FOREACH(q, &addq, pfrkt_workq) {
@@ -1062,7 +1070,7 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
}
}
key.pfrkt_flags = 0;
- r = pfr_create_ktable(&key.pfrkt_t, 0);
+ r = pfr_create_ktable(&key.pfrkt_t, 0, 1);
if (r == NULL)
senderr(ENOMEM);
SLIST_INSERT_HEAD(&addq, r, pfrkt_workq);
@@ -1136,17 +1144,23 @@ _skip:
}
int
-pfr_get_tables(struct pfr_table *tbl, int *size, int flags)
+pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
+ int flags)
{
struct pfr_ktable *p;
- int n = pfr_ktable_cnt;
+ int n;
- ACCEPT_FLAGS(0);
+ ACCEPT_FLAGS(PFR_FLAG_ALLRSETS);
+ n = pfr_table_count(filter, flags);
+ if (n < 0)
+ return (ENOENT);
if (n > *size) {
*size = n;
return (0);
}
RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (pfr_skip_table(filter, p, flags))
+ continue;
if (n-- <= 0)
continue;
if (copyout(&p->pfrkt_t, tbl++, sizeof(*tbl)))
@@ -1161,14 +1175,19 @@ pfr_get_tables(struct pfr_table *tbl, int *size, int flags)
}
int
-pfr_get_tstats(struct pfr_tstats *tbl, int *size, int flags)
+pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
+ int flags)
{
struct pfr_ktable *p;
struct pfr_ktableworkq workq;
- int s, n = pfr_ktable_cnt;
+ int s, n;
long tzero = time.tv_sec;
- ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC|PFR_FLAG_ALLRSETS);
+ /* XXX PFR_FLAG_CLSTATS disabled */
+ n = pfr_table_count(filter, flags);
+ if (n < 0)
+ return (ENOENT);
if (n > *size) {
*size = n;
return (0);
@@ -1177,6 +1196,8 @@ pfr_get_tstats(struct pfr_tstats *tbl, int *size, int flags)
if (flags & PFR_FLAG_ATOMIC)
s = splsoftnet();
RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (pfr_skip_table(filter, p, flags))
+ continue;
if (n-- <= 0)
continue;
if (!(flags & PFR_FLAG_ATOMIC))
@@ -1335,7 +1356,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
SLIST_INIT(&tableq);
kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl);
if (kt == NULL) {
- kt = pfr_create_ktable(tbl, 0);
+ kt = pfr_create_ktable(tbl, 0, 1);
if (kt == NULL)
return (ENOMEM);
SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq);
@@ -1351,7 +1372,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
kt->pfrkt_root = rt;
goto _skip;
}
- rt = pfr_create_ktable(&key.pfrkt_t, 0);
+ rt = pfr_create_ktable(&key.pfrkt_t, 0, 1);
if (rt == NULL) {
pfr_destroy_ktables(&tableq, 0);
return (ENOMEM);
@@ -1361,7 +1382,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
} else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE))
xadd++;
_skip:
- shadow = pfr_create_ktable(tbl, 0);
+ shadow = pfr_create_ktable(tbl, 0, 0);
if (shadow == NULL) {
pfr_destroy_ktables(&tableq, 0);
return (ENOMEM);
@@ -1526,6 +1547,42 @@ pfr_validate_table(struct pfr_table *tbl, int allowedflags)
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);
+ }
+ return (pf_main_ruleset.tables);
+}
+
+int
+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))
+ return (1);
+ return (0);
+}
+
void
pfr_insert_ktables(struct pfr_ktableworkq *workq)
{
@@ -1615,9 +1672,10 @@ pfr_clstats_ktable(struct pfr_ktable *kt, long tzero, int recurse)
}
struct pfr_ktable *
-pfr_create_ktable(struct pfr_table *tbl, long tzero)
+pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
{
struct pfr_ktable *kt;
+ struct pf_ruleset *rs;
kt = pool_get(&pfr_ktable_pl, PR_NOWAIT);
if (kt == NULL)
@@ -1625,6 +1683,19 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero)
bzero(kt, sizeof(*kt));
kt->pfrkt_t = *tbl;
+ if (attachruleset) {
+ rs = pf_find_or_create_ruleset(tbl->pfrt_anchor,
+ tbl->pfrt_ruleset);
+ 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,
offsetof(struct sockaddr_in, sin_addr) * 8) ||
!rn_inithead((void **)&kt->pfrkt_ip6,
@@ -1664,6 +1735,12 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
free((caddr_t)kt->pfrkt_ip6, M_RTABLE);
if (kt->pfrkt_shadow != NULL)
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);
}
@@ -1774,7 +1851,7 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
}
kt = pfr_lookup_table(&tbl);
if (kt == NULL) {
- kt = pfr_create_ktable(&tbl, time.tv_sec);
+ kt = pfr_create_ktable(&tbl, time.tv_sec, 1);
if (kt == NULL)
return (NULL);
if (ac != NULL) {
@@ -1782,7 +1859,7 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
bzero(tbl.pfrt_ruleset, sizeof(tbl.pfrt_ruleset));
rt = pfr_lookup_table(&tbl);
if (rt == NULL) {
- rt = pfr_create_ktable(&tbl, 0);
+ rt = pfr_create_ktable(&tbl, 0, 1);
if (rt == NULL) {
pfr_destroy_ktable(kt, 0);
return (NULL);
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index dcd63338423..839a0fb4fdc 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.153 2003/06/03 12:34:04 henning Exp $ */
+/* $OpenBSD: pfvar.h,v 1.154 2003/06/08 09:41:08 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -494,6 +494,7 @@ struct pf_ruleset {
} active, inactive;
} rules[PF_RULESET_MAX];
struct pf_anchor *anchor;
+ int tables;
};
TAILQ_HEAD(pf_rulesetqueue, pf_ruleset);
@@ -502,6 +503,7 @@ struct pf_anchor {
TAILQ_ENTRY(pf_anchor) entries;
char name[PF_ANCHOR_NAME_SIZE];
struct pf_rulesetqueue rulesets;
+ int tables;
};
TAILQ_HEAD(pf_anchorqueue, pf_anchor);
@@ -591,6 +593,7 @@ struct pfr_ktable {
struct radix_node_head *pfrkt_ip6;
struct pfr_ktable *pfrkt_shadow;
struct pfr_ktable *pfrkt_root;
+ struct pf_ruleset *pfrkt_rs;
int pfrkt_nflags;
};
#define pfrkt_t pfrkt_ts.pfrts_t
@@ -900,7 +903,8 @@ struct pfioc_ruleset {
#define PFR_FLAG_CLSTATS 0x00000008
#define PFR_FLAG_ADDRSTOO 0x00000010
#define PFR_FLAG_REPLACE 0x00000020
-#define PFR_FLAG_ALLMASK 0x0000003F
+#define PFR_FLAG_ALLRSETS 0x00000040
+#define PFR_FLAG_ALLMASK 0x0000007F
struct pfioc_table {
struct pfr_table pfrio_table;
@@ -1030,6 +1034,11 @@ extern int pf_insert_state(struct pf_state *);
extern struct pf_state *pf_find_state(struct pf_state_tree *,
struct pf_tree_node *);
extern struct pf_anchor *pf_find_anchor(const char *);
+extern struct pf_ruleset *pf_find_ruleset(char *, char *);
+extern struct pf_ruleset *pf_find_or_create_ruleset(char *, char *);
+extern void pf_remove_if_empty_ruleset(
+ struct pf_ruleset *);
+
extern struct ifnet *status_ifp;
extern struct pf_rule pf_default_rule;
extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
@@ -1078,11 +1087,11 @@ void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
struct pfr_ktable *
pfr_attach_table(struct pf_ruleset *, char *);
void pfr_detach_table(struct pfr_ktable *);
-int pfr_clr_tables(int *, int);
+int pfr_clr_tables(struct pfr_table *, int *, int);
int pfr_add_tables(struct pfr_table *, int, int *, int);
int pfr_del_tables(struct pfr_table *, int, int *, int);
-int pfr_get_tables(struct pfr_table *, int *, int);
-int pfr_get_tstats(struct pfr_tstats *, int *, int);
+int pfr_get_tables(struct pfr_table *, struct pfr_table *, int *, int);
+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);