diff options
author | Cedric Berger <cedric@cvs.openbsd.org> | 2003-01-01 13:23:18 +0000 |
---|---|---|
committer | Cedric Berger <cedric@cvs.openbsd.org> | 2003-01-01 13:23:18 +0000 |
commit | 8a9daf46bb57189a8e0a075f1ac711bbd7563827 (patch) | |
tree | 6bd3ab83f36692dc7f2f4a67b7649f287d660acf /sys | |
parent | 406701f6d17bf6436d95f20551b81e56a44dee3b (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.c | 58 |
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)) { |