summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorCedric Berger <cedric@cvs.openbsd.org>2003-01-01 13:23:18 +0000
committerCedric Berger <cedric@cvs.openbsd.org>2003-01-01 13:23:18 +0000
commit8a9daf46bb57189a8e0a075f1ac711bbd7563827 (patch)
tree6bd3ab83f36692dc7f2f4a67b7649f287d660acf /sys
parent406701f6d17bf6436d95f20551b81e56a44dee3b (diff)
Behaves properly when someone try to insert/delete the same table name
multiple time in the same ioctl (i.e. pfradix -A/D test test test). This is not a very efficient implementation, and I'll change it if someone really add/delete more than hundred of tables in the same ioctl.
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pf_table.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
index f21f2e53f66..b1d3e30933a 100644
--- a/sys/net/pf_table.c
+++ b/sys/net/pf_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_table.c,v 1.4 2002/12/30 15:39:18 cedric Exp $ */
+/* $OpenBSD: pf_table.c,v 1.5 2003/01/01 13:23:17 cedric Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -903,38 +903,42 @@ int
pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
{
struct pfr_ktableworkq workq;
- struct pfr_ktable *p, key;
- int i, s, xadd = 0;
+ struct pfr_ktable *p, *q, key;
+ int i, rv, s, xadd = 0;
long tzero = time.tv_sec;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
SLIST_INIT(&workq);
for(i = 0; i < size; i++) {
- if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t))) {
- pfr_destroy_ktables(&workq);
- return (EFAULT);
- }
+ if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+ senderr(EFAULT);
if (key.pfrkt_name[PF_TABLE_NAME_SIZE-1])
- return (EINVAL);
+ senderr(EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p == NULL) {
- if (!(flags & PFR_FLAG_DUMMY)) {
- p = pfr_create_ktable(&key.pfrkt_t, tzero);
- if (p == NULL) {
- pfr_destroy_ktables(&workq);
- return (ENOMEM);
- }
- SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
- /* XXX move the following out of the if */
- if (pfr_lookup_hash(&p->pfrkt_hash)) {
- printf(
- "pfr_add_tables: sha collision\n");
- pfr_destroy_ktables(&workq);
- return (EEXIST);
+ p = pfr_create_ktable(&key.pfrkt_t, tzero);
+ if (p == NULL)
+ senderr(ENOMEM);
+ SLIST_FOREACH(q, &workq, pfrkt_workq) {
+ if (!strcmp(p->pfrkt_name, q->pfrkt_name))
+ goto _skip;
+ if (!memcmp(&p->pfrkt_hash, &q->pfrkt_hash,
+ sizeof(p->pfrkt_hash)))
+ {
+ printf("pfr_add_tables: "
+ "sha collision\n");
+ senderr(EEXIST);
}
}
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ if (pfr_lookup_hash(&p->pfrkt_hash)) {
+ printf(
+ "pfr_add_tables: sha collision\n");
+ senderr(EEXIST);
+ }
xadd++;
}
+_skip:
}
if (!(flags & PFR_FLAG_DUMMY)) {
if (flags & PFR_FLAG_ATOMIC)
@@ -942,17 +946,21 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
pfr_insert_ktables(&workq);
if (flags & PFR_FLAG_ATOMIC)
splx(s);
- }
+ } else
+ pfr_destroy_ktables(&workq);
if (nadd != NULL)
*nadd = xadd;
return (0);
+_bad:
+ pfr_destroy_ktables(&workq);
+ return (rv);
}
int
pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
{
struct pfr_ktableworkq workq;
- struct pfr_ktable *p, key;
+ struct pfr_ktable *p, *q, key;
int i, s, xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
@@ -962,9 +970,13 @@ pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
return (EFAULT);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL) {
+ SLIST_FOREACH(q, &workq, pfrkt_workq)
+ if (!strcmp(p->pfrkt_name, q->pfrkt_name))
+ goto _skip;
SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
xdel++;
}
+_skip:
}
if (!(flags & PFR_FLAG_DUMMY)) {