summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Thomas McBride <mcbride@cvs.openbsd.org>2009-03-09 13:53:11 +0000
committerRyan Thomas McBride <mcbride@cvs.openbsd.org>2009-03-09 13:53:11 +0000
commitb0a023a94b1bc66e6a579481c636536f1d5d14d7 (patch)
tree8608b763a542072d4a24af842259dbbaf50c37c7
parent3a6e9748f7da78e44e709f4ae46d09b211deb6b6 (diff)
Make the DIOCSETIFFLAG, DIOCSETLIMIT, and DIOCSETTIMEOUT ioctls
transactional, closing PRs 4941 and 5910. Minor flag day, requires rebuild of userland tools that use struct pfi_kif. ok henning deraadt
-rw-r--r--sys/net/pf.c12
-rw-r--r--sys/net/pf_if.c18
-rw-r--r--sys/net/pf_ioctl.c54
-rw-r--r--sys/net/pfvar.h5
4 files changed, 65 insertions, 24 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 15a629cd147..0ec86a23189 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.636 2009/03/07 01:15:41 mcbride Exp $ */
+/* $OpenBSD: pf.c,v 1.637 2009/03/09 13:53:09 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -230,11 +230,11 @@ extern struct pool pfr_ktable_pl;
extern struct pool pfr_kentry_pl;
struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
- { &pf_state_pl, PFSTATE_HIWAT },
- { &pf_src_tree_pl, PFSNODE_HIWAT },
- { &pf_frent_pl, PFFRAG_FRENT_HIWAT },
- { &pfr_ktable_pl, PFR_KTABLE_HIWAT },
- { &pfr_kentry_pl, PFR_KENTRY_HIWAT }
+ { &pf_state_pl, PFSTATE_HIWAT, PFSTATE_HIWAT },
+ { &pf_src_tree_pl, PFSNODE_HIWAT, PFSNODE_HIWAT },
+ { &pf_frent_pl, PFFRAG_FRENT_HIWAT, PFFRAG_FRENT_HIWAT },
+ { &pfr_ktable_pl, PFR_KTABLE_HIWAT, PFR_KTABLE_HIWAT },
+ { &pfr_kentry_pl, PFR_KENTRY_HIWAT, PFR_KENTRY_HIWAT }
};
enum { PF_ICMP_MULTI_NONE, PF_ICMP_MULTI_SOLICITED, PF_ICMP_MULTI_LINK };
diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c
index ddf5cec4d2f..6a29e361025 100644
--- a/sys/net/pf_if.c
+++ b/sys/net/pf_if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_if.c,v 1.55 2008/11/24 13:22:09 mikeb Exp $ */
+/* $OpenBSD: pf_if.c,v 1.56 2009/03/09 13:53:10 mcbride Exp $ */
/*
* Copyright 2005 Henning Brauer <henning@openbsd.org>
@@ -714,7 +714,7 @@ pfi_set_flags(const char *name, int flags)
RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
if (pfi_skip_if(name, p))
continue;
- p->pfik_flags |= flags;
+ p->pfik_flags_new = p->pfik_flags | flags;
}
splx(s);
return (0);
@@ -730,12 +730,24 @@ pfi_clear_flags(const char *name, int flags)
RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
if (pfi_skip_if(name, p))
continue;
- p->pfik_flags &= ~flags;
+ p->pfik_flags_new = p->pfik_flags & ~flags;
}
splx(s);
return (0);
}
+void
+pfi_xcommit(void)
+{
+ struct pfi_kif *p;
+ int s;
+
+ s = splsoftnet();
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs)
+ p->pfik_flags = p->pfik_flags_new;
+ splx(s);
+}
+
/* from pf_print_state.c */
int
pfi_unmask(void *addr)
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index c2b0f184984..d59cfe307fa 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.214 2009/02/16 00:31:25 dlg Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.215 2009/03/09 13:53:10 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -114,7 +114,7 @@ int pf_addr_setup(struct pf_ruleset *,
struct pf_addr_wrap *, sa_family_t);
void pf_addr_copyout(struct pf_addr_wrap *);
-struct pf_rule pf_default_rule;
+struct pf_rule pf_default_rule, pf_default_rule_new;
struct rwlock pf_consistency_lock = RWLOCK_INITIALIZER("pfcnslk");
#ifdef ALTQ
static int pf_altq_running;
@@ -1712,20 +1712,16 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCSETTIMEOUT: {
struct pfioc_tm *pt = (struct pfioc_tm *)addr;
- int old;
if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
pt->seconds < 0) {
error = EINVAL;
goto fail;
}
- old = pf_default_rule.timeout[pt->timeout];
if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
pt->seconds = 1;
- pf_default_rule.timeout[pt->timeout] = pt->seconds;
- if (pt->timeout == PFTM_INTERVAL && pt->seconds < old)
- wakeup(pf_purge_thread);
- pt->seconds = old;
+ pf_default_rule_new.timeout[pt->timeout] = pt->seconds;
+ pt->seconds = pf_default_rule.timeout[pt->timeout];
break;
}
@@ -1753,21 +1749,19 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCSETLIMIT: {
struct pfioc_limit *pl = (struct pfioc_limit *)addr;
- int old_limit;
if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
pf_pool_limits[pl->index].pp == NULL) {
error = EINVAL;
goto fail;
}
- if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
- pl->limit, NULL, 0) != 0) {
+ if (((struct pool *)pf_pool_limits[pl->index].pp)->pr_nout >
+ pl->limit) {
error = EBUSY;
goto fail;
}
- old_limit = pf_pool_limits[pl->index].limit;
- pf_pool_limits[pl->index].limit = pl->limit;
- pl->limit = old_limit;
+ pf_pool_limits[pl->index].limit_new = pl->limit;
+ pl->limit = pf_pool_limits[pl->index].limit;
break;
}
@@ -2433,6 +2427,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
+ pf_default_rule_new = pf_default_rule;
for (i = 0; i < io->size; i++) {
if (copyin(io->array+i, ioe, sizeof(*ioe))) {
free(table, M_TEMP);
@@ -2619,6 +2614,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
}
+ /*
+ * Checked already in DIOCSETLIMIT, but check again as the
+ * situation might have changed.
+ */
+ for (i = 0; i < PF_LIMIT_MAX; i++) {
+ if (((struct pool *)pf_pool_limits[i].pp)->pr_nout >
+ pf_pool_limits[i].limit_new) {
+ error = EBUSY;
+ goto fail;
+ }
+ }
/* now do the commit - no errors should happen here */
for (i = 0; i < io->size; i++) {
if (copyin(io->array+i, ioe, sizeof(*ioe))) {
@@ -2658,6 +2664,26 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
}
+ for (i = 0; i < PF_LIMIT_MAX; i++) {
+ if (pf_pool_limits[i].limit_new !=
+ pf_pool_limits[i].limit &&
+ pool_sethardlimit(pf_pool_limits[i].pp,
+ pf_pool_limits[i].limit_new, NULL, 0) != 0) {
+ error = EBUSY;
+ goto fail; /* really bad */
+ }
+ pf_pool_limits[i].limit = pf_pool_limits[i].limit_new;
+ }
+ for (i = 0; i < PFTM_MAX; i++) {
+ int old = pf_default_rule.timeout[i];
+
+ pf_default_rule.timeout[i] =
+ pf_default_rule_new.timeout[i];
+ if (pf_default_rule.timeout[i] == PFTM_INTERVAL &&
+ pf_default_rule.timeout[i] < old)
+ wakeup(pf_purge_thread);
+ }
+ pfi_xcommit();
free(table, M_TEMP);
free(ioe, M_TEMP);
break;
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 2de3ff2372b..8dd2f87c0fc 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.283 2009/02/16 00:31:25 dlg Exp $ */
+/* $OpenBSD: pfvar.h,v 1.284 2009/03/09 13:53:10 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -1063,6 +1063,7 @@ struct pfi_kif {
u_int64_t pfik_bytes[2][2][2];
u_int32_t pfik_tzero;
int pfik_flags;
+ int pfik_flags_new;
void *pfik_ah_cookie;
struct ifnet *pfik_ifp;
struct ifg_group *pfik_group;
@@ -1749,6 +1750,7 @@ void pfi_update_status(const char *, struct pf_status *);
int pfi_get_ifaces(const char *, struct pfi_kif *, int *);
int pfi_set_flags(const char *, int);
int pfi_clear_flags(const char *, int);
+void pfi_xcommit(void);
int pf_match_tag(struct mbuf *, struct pf_rule *, int *);
u_int16_t pf_tagname2tag(char *);
@@ -1767,6 +1769,7 @@ extern struct rwlock pf_consistency_lock;
struct pf_pool_limit {
void *pp;
unsigned limit;
+ unsigned limit_new;
};
extern struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];