diff options
author | Cedric Berger <cedric@cvs.openbsd.org> | 2003-09-26 21:44:10 +0000 |
---|---|---|
committer | Cedric Berger <cedric@cvs.openbsd.org> | 2003-09-26 21:44:10 +0000 |
commit | 21ee0f9ceb87b49a8d22ccccf781aaa0955725ef (patch) | |
tree | 985658c81572fcf0d3626c19a360b7ec20878add /sys | |
parent | 759e80db3df46eb4e1e8d02d28f6df859e880ec9 (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.c | 3 | ||||
-rw-r--r-- | sys/net/pf_ioctl.c | 501 | ||||
-rw-r--r-- | sys/net/pf_table.c | 33 | ||||
-rw-r--r-- | sys/net/pfvar.h | 22 |
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); |