summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorCedric Berger <cedric@cvs.openbsd.org>2003-09-26 21:44:10 +0000
committerCedric Berger <cedric@cvs.openbsd.org>2003-09-26 21:44:10 +0000
commit21ee0f9ceb87b49a8d22ccccf781aaa0955725ef (patch)
tree985658c81572fcf0d3626c19a360b7ec20878add /sys
parent759e80db3df46eb4e1e8d02d28f6df859e880ec9 (diff)
Rearchitecture of the userland/kernel IOCTL interface for transactions.
This brings us close to 100% atomicity for a "pfctl -f pf.conf" command. (some splxxx work remain in the kernel). Basically, improvements are: - Anchors/Rulesets cannot disappear unexpectedly anymore. - No more leftover in the kernel if "pfctl -f" fail. - Commit is now done in a single atomic IOCTL. WARNING: The kernel code is fully backward compatible, but the new pfctl/authpf userland utilities will only run on a new kernel. The following ioctls are deprecated (i.e. will be deleted sooner or later, depending on how many 3rd party utilities use them and how soon they can be upgraded): - DIOCBEGINRULES - DIOCCOMMITRULES - DIOCBEGINALTQS - DIOCCOMMITALTQS - DIOCRINABEGIN - DIOCRINADEFINE They are replaced by the following ioctls (yes, PF(4) will follow) which operate on a vector of rulesets: - DIOCXBEGIN - DIOCXCOMMIT - DIOCXROLLBACK Ok dhartmei@ mcbride@
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pf.c3
-rw-r--r--sys/net/pf_ioctl.c501
-rw-r--r--sys/net/pf_table.c33
-rw-r--r--sys/net/pfvar.h22
4 files changed, 429 insertions, 130 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index bde57816ebb..32ac4dabd1f 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.391 2003/09/26 14:48:19 mcbride Exp $ */
+/* $OpenBSD: pf.c,v 1.392 2003/09/26 21:44:08 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -103,6 +103,7 @@ struct ifnet *status_ifp;
u_int32_t ticket_altqs_active;
u_int32_t ticket_altqs_inactive;
+int altqs_inactive_open;
u_int32_t ticket_pabuf;
struct timeout pf_expire_to; /* expire timeout */
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 0607f96b7e6..09ce5daf881 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.81 2003/08/22 21:50:34 david Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.82 2003/09/26 21:44:08 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -79,6 +79,12 @@ void pf_init_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 *);
+int pf_begin_altq(u_int32_t *);
+int pf_rollback_altq(u_int32_t);
+int pf_commit_altq(u_int32_t);
+int pf_begin_rules(u_int32_t *, int, char *, char *);
+int pf_rollback_rules(u_int32_t, int, char *, char *);
+int pf_commit_rules(u_int32_t, int, char *, char *);
extern struct timeout pf_expire_to;
@@ -353,7 +359,8 @@ pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
return;
for (i = 0; i < PF_RULESET_MAX; ++i)
if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
- !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr))
+ !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
+ ruleset->rules[i].inactive.open)
return;
anchor = ruleset->anchor;
@@ -499,6 +506,187 @@ pf_tag_unref(u_int16_t tag)
}
int
+pf_begin_altq(u_int32_t *ticket)
+{
+ struct pf_altq *altq;
+ int error = 0;
+
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+ if (altq->qname[0] == 0) {
+ /* detach and destroy the discipline */
+ error = altq_remove(altq);
+ }
+ pool_put(&pf_altq_pl, altq);
+ }
+ if (error)
+ return (error);
+ *ticket = ++ticket_altqs_inactive;
+ altqs_inactive_open = 1;
+ return (0);
+}
+
+int
+pf_rollback_altq(u_int32_t ticket)
+{
+ struct pf_altq *altq;
+ int error = 0;
+
+ if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
+ return (0);
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+ if (altq->qname[0] == 0) {
+ /* detach and destroy the discipline */
+ error = altq_remove(altq);
+ }
+ pool_put(&pf_altq_pl, altq);
+ }
+ altqs_inactive_open = 0;
+ return (error);
+}
+
+int
+pf_commit_altq(u_int32_t ticket)
+{
+ struct pf_altqqueue *old_altqs;
+ struct pf_altq *altq;
+ struct pf_anchor *anchor;
+ struct pf_ruleset *ruleset;
+ int s, err, error = 0;
+
+ if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
+ return (EBUSY);
+
+ /* swap altqs, keep the old. */
+ s = splsoftnet();
+ old_altqs = pf_altqs_active;
+ pf_altqs_active = pf_altqs_inactive;
+ pf_altqs_inactive = old_altqs;
+ ticket_altqs_active = ticket_altqs_inactive;
+
+ /* Attach new disciplines */
+ TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+ if (altq->qname[0] == 0) {
+ /* attach the discipline */
+ error = altq_pfattach(altq);
+ if (error) {
+ splx(s);
+ return (error);
+ }
+ }
+ }
+
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+ if (altq->qname[0] == 0) {
+ /* detach and destroy the discipline */
+ err = altq_pfdetach(altq);
+ if (err != 0 && error == 0)
+ error = err;
+ err = altq_remove(altq);
+ if (err != 0 && error == 0)
+ error = err;
+ }
+ pool_put(&pf_altq_pl, altq);
+ }
+ splx(s);
+
+ /* update queue IDs */
+ pf_rule_set_qid(
+ pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
+ TAILQ_FOREACH(anchor, &pf_anchors, entries) {
+ TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) {
+ pf_rule_set_qid(
+ ruleset->rules[PF_RULESET_FILTER].active.ptr
+ );
+ }
+ }
+ altqs_inactive_open = 0;
+ return (error);
+}
+
+int
+pf_begin_rules(u_int32_t *ticket, int rs_num, char *anchor, char *ruleset)
+{
+ struct pf_ruleset *rs;
+ struct pf_rule *rule;
+
+ if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
+ return (EINVAL);
+ rs = pf_find_or_create_ruleset(anchor, ruleset);
+ if (rs == NULL)
+ return (EINVAL);
+ while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL)
+ pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
+ *ticket = ++rs->rules[rs_num].inactive.ticket;
+ rs->rules[rs_num].inactive.open = 1;
+ return (0);
+}
+
+int
+pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
+{
+ struct pf_ruleset *rs;
+ struct pf_rule *rule;
+
+ if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
+ return (EINVAL);
+ rs = pf_find_ruleset(anchor, ruleset);
+ if (rs == NULL || !rs->rules[rs_num].inactive.open ||
+ rs->rules[rs_num].inactive.ticket != ticket)
+ return (0);
+ while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL)
+ pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
+ rs->rules[rs_num].inactive.open = 0;
+ return (0);
+}
+
+int
+pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
+{
+ struct pf_ruleset *rs;
+ struct pf_rule *rule;
+ struct pf_rulequeue *old_rules;
+ int s;
+
+ if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
+ return (EINVAL);
+ rs = pf_find_ruleset(anchor, ruleset);
+ if (rs == NULL || !rs->rules[rs_num].inactive.open ||
+ ticket != rs->rules[rs_num].inactive.ticket)
+ return (EBUSY);
+
+#ifdef ALTQ
+ /* set queue IDs */
+ if (rs_num == PF_RULESET_FILTER)
+ pf_rule_set_qid(rs->rules[rs_num].inactive.ptr);
+#endif
+
+ /* Swap rules, keep the old. */
+ s = splsoftnet();
+ old_rules = rs->rules[rs_num].active.ptr;
+ rs->rules[rs_num].active.ptr =
+ rs->rules[rs_num].inactive.ptr;
+ rs->rules[rs_num].inactive.ptr = old_rules;
+ rs->rules[rs_num].active.ticket =
+ rs->rules[rs_num].inactive.ticket;
+ pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
+
+ /* Purge the old rule list. */
+ while ((rule = TAILQ_FIRST(old_rules)) != NULL)
+ pf_rm_rule(old_rules, rule);
+ rs->rules[rs_num].inactive.open = 0;
+ pf_remove_if_empty_ruleset(rs);
+ pf_update_anchor_rules();
+ splx(s);
+ return (0);
+}
+
+int
pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
{
struct pf_pooladdr *pa = NULL;
@@ -605,24 +793,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCBEGINRULES: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
- struct pf_ruleset *ruleset;
- struct pf_rule *rule;
- int rs_num;
- ruleset = pf_find_or_create_ruleset(pr->anchor, pr->ruleset);
- if (ruleset == NULL) {
- error = EINVAL;
- break;
- }
- rs_num = pf_get_ruleset_number(pr->rule.action);
- if (rs_num >= PF_RULESET_MAX) {
- error = EINVAL;
- break;
- }
- while ((rule =
- TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr)) != NULL)
- pf_rm_rule(ruleset->rules[rs_num].inactive.ptr, rule);
- pr->ticket = ++ruleset->rules[rs_num].inactive.ticket;
+ error = pf_begin_rules(&pr->ticket, pf_get_ruleset_number(
+ pr->rule.action), pr->anchor, pr->ruleset);
break;
}
@@ -741,48 +914,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCCOMMITRULES: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
- struct pf_ruleset *ruleset;
- struct pf_rulequeue *old_rules;
- struct pf_rule *rule;
- int rs_num;
- ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
- if (ruleset == NULL) {
- error = EINVAL;
- break;
- }
- rs_num = pf_get_ruleset_number(pr->rule.action);
- if (rs_num >= PF_RULESET_MAX) {
- error = EINVAL;
- break;
- }
- if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
- error = EBUSY;
- break;
- }
-
-#ifdef ALTQ
- /* set queue IDs */
- if (rs_num == PF_RULESET_FILTER)
- pf_rule_set_qid(ruleset->rules[rs_num].inactive.ptr);
-#endif
-
- /* Swap rules, keep the old. */
- s = splsoftnet();
- old_rules = ruleset->rules[rs_num].active.ptr;
- ruleset->rules[rs_num].active.ptr =
- ruleset->rules[rs_num].inactive.ptr;
- ruleset->rules[rs_num].inactive.ptr = old_rules;
- ruleset->rules[rs_num].active.ticket =
- ruleset->rules[rs_num].inactive.ticket;
- pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
-
- /* Purge the old rule list. */
- while ((rule = TAILQ_FIRST(old_rules)) != NULL)
- pf_rm_rule(old_rules, rule);
- pf_remove_if_empty_ruleset(ruleset);
- pf_update_anchor_rules();
- splx(s);
+ error = pf_commit_rules(pr->ticket, pf_get_ruleset_number(
+ pr->rule.action), pr->anchor, pr->ruleset);
break;
}
@@ -1438,18 +1572,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCBEGINALTQS: {
u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_altq *altq;
- /* Purge the old altq list */
- while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
- TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
- if (altq->qname[0] == 0) {
- /* detach and destroy the discipline */
- error = altq_remove(altq);
- }
- pool_put(&pf_altq_pl, altq);
- }
- *ticket = ++ticket_altqs_inactive;
+ error = pf_begin_altq(ticket);
break;
}
@@ -1494,63 +1618,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
case DIOCCOMMITALTQS: {
- u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_altqqueue *old_altqs;
- struct pf_altq *altq;
- struct pf_anchor *anchor;
- struct pf_ruleset *ruleset;
- int err;
-
- if (*ticket != ticket_altqs_inactive) {
- error = EBUSY;
- break;
- }
-
- /* Swap altqs, keep the old. */
- s = splsoftnet();
- old_altqs = pf_altqs_active;
- pf_altqs_active = pf_altqs_inactive;
- pf_altqs_inactive = old_altqs;
- ticket_altqs_active = ticket_altqs_inactive;
-
- /* Attach new disciplines */
- TAILQ_FOREACH(altq, pf_altqs_active, entries) {
- if (altq->qname[0] == 0) {
- /* attach the discipline */
- error = altq_pfattach(altq);
- if (error) {
- splx(s);
- goto fail;
- }
- }
- }
-
- /* Purge the old altq list */
- while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
- TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
- if (altq->qname[0] == 0) {
- /* detach and destroy the discipline */
- err = altq_pfdetach(altq);
- if (err != 0 && error == 0)
- error = err;
- err = altq_remove(altq);
- if (err != 0 && error == 0)
- error = err;
- }
- pool_put(&pf_altq_pl, altq);
- }
- splx(s);
+ u_int32_t ticket = *(u_int32_t *)addr;
- /* update queue IDs */
- pf_rule_set_qid(
- pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
- TAILQ_FOREACH(anchor, &pf_anchors, entries) {
- TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) {
- pf_rule_set_qid(
- ruleset->rules[PF_RULESET_FILTER].active.ptr
- );
- }
- }
+ error = pf_commit_altq(ticket);
break;
}
@@ -2148,6 +2218,183 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
+ case DIOCXBEGIN: {
+ struct pfioc_trans *io = (struct pfioc_trans *)addr;
+ struct pfioc_trans_e ioe;
+ struct pfr_table table;
+ int i;
+
+ if (io->esize != sizeof(ioe)) {
+ error = ENODEV;
+ goto fail;
+ }
+ for (i = 0; i < io->size; i++) {
+ if (copyin(io->array+i, &ioe, sizeof(ioe))) {
+ error = EFAULT;
+ goto fail;
+ }
+ switch(ioe.rs_num) {
+ case PF_RULESET_ALTQ:
+ if (ioe.anchor[0] || ioe.ruleset[0]) {
+ error = EINVAL;
+ goto fail;
+ }
+ if ((error = pf_begin_altq(&ioe.ticket)))
+ goto fail;
+ break;
+ case PF_RULESET_TABLE:
+ bzero(&table, sizeof(table));
+ strlcpy(table.pfrt_anchor, ioe.anchor,
+ sizeof(table.pfrt_anchor));
+ strlcpy(table.pfrt_ruleset, ioe.ruleset,
+ sizeof(table.pfrt_ruleset));
+ if ((error = pfr_ina_begin(&table,
+ &ioe.ticket, NULL, 0)))
+ goto fail;
+ break;
+ default:
+ if ((error = pf_begin_rules(&ioe.ticket,
+ ioe.rs_num, ioe.anchor, ioe.ruleset)))
+ goto fail;
+ break;
+ }
+ if (copyout(&ioe, io->array+i, sizeof(io->array[i]))) {
+ error = EFAULT;
+ goto fail;
+ }
+ }
+ break;
+ }
+
+ case DIOCXROLLBACK: {
+ struct pfioc_trans *io = (struct pfioc_trans *)addr;
+ struct pfioc_trans_e ioe;
+ struct pfr_table table;
+ int i;
+
+ if (io->esize != sizeof(ioe)) {
+ error = ENODEV;
+ goto fail;
+ }
+ for (i = 0; i < io->size; i++) {
+ if (copyin(io->array+i, &ioe, sizeof(ioe))) {
+ error = EFAULT;
+ goto fail;
+ }
+ switch(ioe.rs_num) {
+ case PF_RULESET_ALTQ:
+ if (ioe.anchor[0] || ioe.ruleset[0]) {
+ error = EINVAL;
+ goto fail;
+ }
+ if ((error = pf_rollback_altq(ioe.ticket)))
+ goto fail; /* really bad */
+ break;
+ case PF_RULESET_TABLE:
+ bzero(&table, sizeof(table));
+ strlcpy(table.pfrt_anchor, ioe.anchor,
+ sizeof(table.pfrt_anchor));
+ strlcpy(table.pfrt_ruleset, ioe.ruleset,
+ sizeof(table.pfrt_ruleset));
+ if ((error = pfr_ina_rollback(&table,
+ ioe.ticket, NULL, 0)))
+ goto fail; /* really bad */
+ break;
+ default:
+ if ((error = pf_rollback_rules(ioe.ticket,
+ ioe.rs_num, ioe.anchor, ioe.ruleset)))
+ goto fail; /* really bad */
+ break;
+ }
+ }
+ break;
+ }
+
+ case DIOCXCOMMIT: {
+ struct pfioc_trans *io = (struct pfioc_trans *)addr;
+ struct pfioc_trans_e ioe;
+ struct pfr_table table;
+ struct pf_ruleset *rs;
+ int i;
+
+ if (io->esize != sizeof(ioe)) {
+ error = ENODEV;
+ goto fail;
+ }
+ /* first makes sure everything will succeed */
+ for (i = 0; i < io->size; i++) {
+ if (copyin(io->array+i, &ioe, sizeof(ioe))) {
+ error = EFAULT;
+ goto fail;
+ }
+ switch (ioe.rs_num) {
+ case PF_RULESET_ALTQ:
+ if (ioe.anchor[0] || ioe.ruleset[0]) {
+ error = EINVAL;
+ goto fail;
+ }
+ if (!altqs_inactive_open || ioe.ticket !=
+ ticket_altqs_inactive) {
+ error = EBUSY;
+ goto fail;
+ }
+ break;
+ case PF_RULESET_TABLE:
+ rs = pf_find_ruleset(ioe.anchor, ioe.ruleset);
+ if (rs == NULL || !rs->topen || ioe.ticket !=
+ rs->tticket) {
+ error = EBUSY;
+ goto fail;
+ }
+ break;
+ default:
+ if (ioe.rs_num < 0 || ioe.rs_num >=
+ PF_RULESET_MAX) {
+ error = EINVAL;
+ goto fail;
+ }
+ rs = pf_find_ruleset(ioe.anchor, ioe.ruleset);
+ if (rs == NULL ||
+ !rs->rules[ioe.rs_num].inactive.open ||
+ rs->rules[ioe.rs_num].inactive.ticket !=
+ ioe.ticket) {
+ error = EBUSY;
+ goto fail;
+ }
+ break;
+ }
+ }
+ /* now do the commit - no errors should happen here */
+ for (i = 0; i < io->size; i++) {
+ if (copyin(io->array+i, &ioe, sizeof(ioe))) {
+ error = EFAULT;
+ goto fail;
+ }
+ switch (ioe.rs_num) {
+ case PF_RULESET_ALTQ:
+ if ((error = pf_commit_altq(ioe.ticket)))
+ goto fail; /* really bad */
+ break;
+ case PF_RULESET_TABLE:
+ bzero(&table, sizeof(table));
+ strlcpy(table.pfrt_anchor, ioe.anchor,
+ sizeof(table.pfrt_anchor));
+ strlcpy(table.pfrt_ruleset, ioe.ruleset,
+ sizeof(table.pfrt_ruleset));
+ if ((error = pfr_ina_commit(&table, ioe.ticket,
+ NULL, NULL, 0)))
+ goto fail; /* really bad */
+ break;
+ default:
+ if ((error = pf_commit_rules(ioe.ticket,
+ ioe.rs_num, ioe.anchor, ioe.ruleset)))
+ goto fail; /* really bad */
+ break;
+ }
+ }
+ break;
+ }
+
default:
error = ENODEV;
break;
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
index e6ce25fa46e..490edb2393c 100644
--- a/sys/net/pf_table.c
+++ b/sys/net/pf_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_table.c,v 1.41 2003/08/22 15:19:23 henning Exp $ */
+/* $OpenBSD: pf_table.c,v 1.42 2003/09/26 21:44:09 cedric Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -1459,6 +1459,37 @@ _bad:
}
int
+pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
+{
+ struct pfr_ktableworkq workq;
+ struct pfr_ktable *p;
+ struct pf_ruleset *rs;
+ int xdel = 0;
+
+ ACCEPT_FLAGS(PFR_FLAG_DUMMY);
+ rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
+ if (rs == NULL || !rs->topen || ticket != rs->tticket)
+ return (0);
+ SLIST_INIT(&workq);
+ RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
+ pfr_skip_table(trs, p, 0))
+ continue;
+ p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ xdel++;
+ }
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ pfr_setflags_ktables(&workq);
+ rs->topen = 0;
+ pf_remove_if_empty_ruleset(rs);
+ }
+ if (ndel != NULL)
+ *ndel = xdel;
+ return (0);
+}
+
+int
pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
int *nchange, int flags)
{
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 058e425c300..37f879cf80b 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.170 2003/08/22 21:50:34 david Exp $ */
+/* $OpenBSD: pfvar.h,v 1.171 2003/09/26 21:44:09 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -598,6 +598,7 @@ struct pf_ruleset {
struct {
struct pf_rulequeue *ptr;
u_int32_t ticket;
+ int open;
} active, inactive;
} rules[PF_RULESET_MAX];
struct pf_anchor *anchor;
@@ -1004,6 +1005,19 @@ struct pfioc_ruleset {
char name[PF_RULESET_NAME_SIZE];
};
+#define PF_RULESET_ALTQ (PF_RULESET_MAX)
+#define PF_RULESET_TABLE (PF_RULESET_MAX+1)
+struct pfioc_trans {
+ int size; /* number of elements */
+ int esize; /* size of each element in bytes */
+ struct pfioc_trans_e {
+ int rs_num;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
+ u_int32_t ticket;
+ } *array;
+};
+
#define PFR_FLAG_ATOMIC 0x00000001
#define PFR_FLAG_DUMMY 0x00000002
#define PFR_FLAG_FEEDBACK 0x00000004
@@ -1101,6 +1115,10 @@ struct pfioc_table {
#define DIOCOSFPFLUSH _IO('D', 78)
#define DIOCOSFPADD _IOWR('D', 79, struct pf_osfp_ioctl)
#define DIOCOSFPGET _IOWR('D', 80, struct pf_osfp_ioctl)
+#define DIOCXBEGIN _IOWR('D', 81, struct pfioc_trans)
+#define DIOCXCOMMIT _IOWR('D', 82, struct pfioc_trans)
+#define DIOCXROLLBACK _IOWR('D', 83, struct pfioc_trans)
+
#ifdef _KERNEL
RB_HEAD(pf_state_tree, pf_tree_node);
@@ -1118,6 +1136,7 @@ extern struct pf_palist pf_pabuf;
extern u_int32_t ticket_altqs_active;
extern u_int32_t ticket_altqs_inactive;
+extern int altqs_inactive_open;
extern u_int32_t ticket_pabuf;
extern struct pf_altqqueue *pf_altqs_active;
extern struct pf_altqqueue *pf_altqs_inactive;
@@ -1224,6 +1243,7 @@ int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *,
int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
int);
int pfr_ina_begin(struct pfr_table *, u_int32_t *, int *, int);
+int pfr_ina_rollback(struct pfr_table *, u_int32_t, int *, int);
int pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int);
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
int *, u_int32_t, int);