summaryrefslogtreecommitdiff
path: root/sys
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 /sys
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
Diffstat (limited to 'sys')
-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];