summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/pf_ioctl.c272
1 files changed, 147 insertions, 125 deletions
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 018b7ad0438..1ccc46a027a 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.235 2010/06/30 18:10:55 henning Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.236 2010/12/15 14:22:25 claudio Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -111,6 +111,9 @@ int pf_addr_setup(struct pf_ruleset *,
int pf_kif_setup(char *, struct pfi_kif **);
void pf_addr_copyout(struct pf_addr_wrap *);
void pf_trans_set_commit(void);
+void pf_pool_copyin(struct pf_pool *, struct pf_pool *);
+int pf_rule_copyin(struct pf_rule *, struct pf_rule *,
+ struct pf_ruleset *);
struct pf_rule pf_default_rule, pf_default_rule_new;
struct rwlock pf_consistency_lock = RWLOCK_INITIALIZER("pfcnslk");
@@ -1011,21 +1014,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EBUSY;
break;
}
- rule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL);
+ rule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL|PR_ZERO);
if (rule == NULL) {
error = ENOMEM;
break;
}
- bcopy(&pr->rule, rule, sizeof(struct pf_rule));
+ if ((error = pf_rule_copyin(&pr->rule, rule, ruleset))) {
+ pool_put(&pf_rule_pl, rule);
+ break;
+ }
rule->cuid = p->p_cred->p_ruid;
rule->cpid = p->p_pid;
- rule->anchor = NULL;
- rule->kif = NULL;
- rule->rcv_kif = NULL;
- /* initialize refcounting */
- rule->states_cur = 0;
- rule->src_nodes = 0;
- rule->entries.tqe_prev = NULL;
switch (rule->af) {
case 0:
@@ -1054,48 +1053,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
rule->dst.addr.type == PF_ADDR_NONE)
error = EINVAL;
- if (pf_kif_setup(rule->ifname, &rule->kif))
- error = EINVAL;
- if (pf_kif_setup(rule->rcv_ifname, &rule->rcv_kif))
- error = EINVAL;
- if (pf_kif_setup(rule->rdr.ifname, &rule->rdr.kif))
- error = EINVAL;
- if (pf_kif_setup(rule->nat.ifname, &rule->nat.kif))
- error = EINVAL;
- if (pf_kif_setup(rule->route.ifname, &rule->route.kif))
- error = EINVAL;
-
- if (rule->rtableid > 0 && !rtable_exists(rule->rtableid))
- error = EBUSY;
-
-#ifdef ALTQ
- /* set queue IDs */
- if (rule->qname[0] != 0) {
- if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
- error = EBUSY;
- else if (rule->pqname[0] != 0) {
- if ((rule->pqid =
- pf_qname2qid(rule->pqname)) == 0)
- error = EBUSY;
- } else
- rule->pqid = rule->qid;
- }
-#endif
- if (rule->tagname[0])
- if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
- error = EBUSY;
- if (rule->match_tagname[0])
- if ((rule->match_tag =
- pf_tagname2tag(rule->match_tagname)) == 0)
- error = EBUSY;
- if (rule->rt && !rule->direction)
- error = EINVAL;
-#if NPFLOG > 0
- if (!rule->log)
- rule->logif = 0;
- if (rule->logif >= PFLOGIFS_MAX)
- error = EINVAL;
-#endif
if (pf_addr_setup(ruleset, &rule->src.addr, rule->af))
error = EINVAL;
if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af))
@@ -1108,22 +1065,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
error = EINVAL;
-
- if (rule->overload_tblname[0]) {
- if ((rule->overload_tbl = pfr_attach_table(ruleset,
- rule->overload_tblname, 0)) == NULL)
- error = EINVAL;
- else
- rule->overload_tbl->pfrkt_flags |=
- PFR_TFLAG_ACTIVE;
- }
+ if (rule->rt && !rule->direction)
+ error = EINVAL;
if (error) {
pf_rm_rule(NULL, rule);
break;
}
- rule->evaluations = rule->packets[0] = rule->packets[1] =
- rule->bytes[0] = rule->bytes[1] = 0;
TAILQ_INSERT_TAIL(ruleset->rules.inactive.ptr,
rule, entries);
ruleset->rules.inactive.rcount++;
@@ -1232,17 +1180,15 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
if (pcr->action != PF_CHANGE_REMOVE) {
- newrule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL);
+ newrule = pool_get(&pf_rule_pl,
+ PR_WAITOK|PR_LIMITFAIL|PR_ZERO);
if (newrule == NULL) {
error = ENOMEM;
break;
}
- bcopy(&pcr->rule, newrule, sizeof(struct pf_rule));
+ pf_rule_copyin(&pcr->rule, newrule, ruleset);
newrule->cuid = p->p_cred->p_ruid;
newrule->cpid = p->p_pid;
- /* initialize refcounting */
- newrule->states_cur = 0;
- newrule->entries.tqe_prev = NULL;
switch (newrule->af) {
case 0:
@@ -1261,51 +1207,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
goto fail;
}
- if (pf_kif_setup(newrule->ifname, &newrule->kif))
- error = EINVAL;
- if (pf_kif_setup(newrule->rcv_ifname, &newrule->rcv_kif))
- error = EINVAL;
- if (pf_kif_setup(newrule->rdr.ifname, &newrule->rdr.kif))
- error = EINVAL;
- if (pf_kif_setup(newrule->nat.ifname, &newrule->nat.kif))
- error = EINVAL;
- if (pf_kif_setup(newrule->route.ifname, &newrule->route.kif))
- error = EINVAL;
-
- if (newrule->rtableid > 0 &&
- !rtable_exists(newrule->rtableid))
- error = EBUSY;
-
-#ifdef ALTQ
- /* set queue IDs */
- if (newrule->qname[0] != 0) {
- if ((newrule->qid =
- pf_qname2qid(newrule->qname)) == 0)
- error = EBUSY;
- else if (newrule->pqname[0] != 0) {
- if ((newrule->pqid =
- pf_qname2qid(newrule->pqname)) == 0)
- error = EBUSY;
- } else
- newrule->pqid = newrule->qid;
- }
-#endif /* ALTQ */
- if (newrule->tagname[0])
- if ((newrule->tag =
- pf_tagname2tag(newrule->tagname)) == 0)
- error = EBUSY;
- if (newrule->match_tagname[0])
- if ((newrule->match_tag = pf_tagname2tag(
- newrule->match_tagname)) == 0)
- error = EBUSY;
if (newrule->rt && !newrule->direction)
error = EINVAL;
-#if NPFLOG > 0
- if (!newrule->log)
- newrule->logif = 0;
- if (newrule->logif >= PFLOGIFS_MAX)
- error = EINVAL;
-#endif
if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af))
error = EINVAL;
if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af))
@@ -1319,23 +1222,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
error = EINVAL;
- if (newrule->overload_tblname[0]) {
- if ((newrule->overload_tbl = pfr_attach_table(
- ruleset, newrule->overload_tblname, 0)) ==
- NULL)
- error = EINVAL;
- else
- newrule->overload_tbl->pfrkt_flags |=
- PFR_TFLAG_ACTIVE;
- }
-
if (error) {
pf_rm_rule(NULL, newrule);
break;
}
- newrule->evaluations = 0;
- newrule->packets[0] = newrule->packets[1] = 0;
- newrule->bytes[0] = newrule->bytes[1] = 0;
}
if (pcr->action == PF_CHANGE_ADD_HEAD)
@@ -1753,6 +1643,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(&pa->altq, altq, sizeof(struct pf_altq));
+ altq->altq_disc = NULL;
/*
* if this is for a queue, find the discipline and
@@ -1764,7 +1655,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pool_put(&pf_altq_pl, altq);
break;
}
- altq->altq_disc = NULL;
TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
if (strncmp(a->ifname, altq->ifname,
IFNAMSIZ) == 0 && a->qname[0] == 0) {
@@ -2570,3 +2460,135 @@ pf_trans_set_commit(void)
if (pf_trans_set.mask & PF_TSET_REASS)
pf_status.reass = pf_trans_set.reass;
}
+
+void
+pf_pool_copyin(struct pf_pool *from, struct pf_pool *to)
+{
+ bcopy(from, to, sizeof(*to));
+ to->kif = NULL;
+}
+
+int
+pf_rule_copyin(struct pf_rule *from, struct pf_rule *to,
+ struct pf_ruleset *ruleset)
+{
+ int i;
+
+ to->src = from->src;
+ to->dst = from->dst;
+
+ /* XXX union skip[] */
+
+ strlcpy(to->label, from->label, sizeof(to->label));
+ strlcpy(to->ifname, from->ifname, sizeof(to->ifname));
+ strlcpy(to->rcv_ifname, from->rcv_ifname, sizeof(to->rcv_ifname));
+ strlcpy(to->qname, from->qname, sizeof(to->qname));
+ strlcpy(to->pqname, from->pqname, sizeof(to->pqname));
+ strlcpy(to->tagname, from->tagname, sizeof(to->tagname));
+ strlcpy(to->match_tagname, from->match_tagname,
+ sizeof(to->match_tagname));
+ strlcpy(to->overload_tblname, from->overload_tblname,
+ sizeof(to->overload_tblname));
+
+ pf_pool_copyin(&from->nat, &to->nat);
+ pf_pool_copyin(&from->rdr, &to->rdr);
+ pf_pool_copyin(&from->route, &to->route);
+
+ if (pf_kif_setup(to->ifname, &to->kif))
+ return (EINVAL);
+ if (pf_kif_setup(to->rcv_ifname, &to->rcv_kif))
+ return (EINVAL);
+ if (to->overload_tblname[0]) {
+ if ((to->overload_tbl = pfr_attach_table(ruleset,
+ to->overload_tblname, 0)) == NULL)
+ return (EINVAL);
+ else
+ to->overload_tbl->pfrkt_flags |= PFR_TFLAG_ACTIVE;
+ }
+
+ if (pf_kif_setup(to->rdr.ifname, &to->rdr.kif))
+ return (EINVAL);
+ if (pf_kif_setup(to->nat.ifname, &to->nat.kif))
+ return (EINVAL);
+ if (pf_kif_setup(to->route.ifname, &to->route.kif))
+ return (EINVAL);
+
+ to->os_fingerprint = from->os_fingerprint;
+
+ to->rtableid = from->rtableid;
+ if (to->rtableid > 0 && !rtable_exists(to->rtableid))
+ return (EBUSY);
+
+ for (i = 0; i < PFTM_MAX; i++)
+ to->timeout[i] = from->timeout[i];
+ to->states_tot = from->states_tot;
+ to->max_states = from->max_states;
+ to->max_src_nodes = from->max_src_nodes;
+ to->max_src_states = from->max_src_states;
+ to->max_src_conn = from->max_src_conn;
+ to->max_src_conn_rate.limit = from->max_src_conn_rate.limit;
+ to->max_src_conn_rate.seconds = from->max_src_conn_rate.seconds;
+
+#ifdef ALTQ
+ /* set queue IDs */
+ if (to->qname[0] != 0) {
+ if ((to->qid = pf_qname2qid(to->qname)) == 0)
+ return (EBUSY);
+ else if (to->pqname[0] != 0) {
+ if ((to->pqid = pf_qname2qid(to->pqname)) == 0)
+ return (EBUSY);
+ } else
+ to->pqid = to->qid;
+ }
+#endif
+ to->rt_listid = from->rt_listid;
+ to->prob = from->prob;
+ to->return_icmp = from->return_icmp;
+ to->return_icmp6 = from->return_icmp6;
+ to->max_mss = from->max_mss;
+ if (to->tagname[0])
+ if ((to->tag = pf_tagname2tag(to->tagname)) == 0)
+ return (EBUSY);
+ if (to->match_tagname[0])
+ if ((to->match_tag = pf_tagname2tag(to->match_tagname)) == 0)
+ return (EBUSY);
+ to->scrub_flags = from->scrub_flags;
+ to->uid = from->uid;
+ to->gid = from->gid;
+ to->rule_flag = from->rule_flag;
+ to->action = from->action;
+ to->direction = from->direction;
+ to->log = from->log;
+ to->logif = from->logif;
+#if NPFLOG > 0
+ if (!to->log)
+ to->logif = 0;
+ if (to->logif >= PFLOGIFS_MAX)
+ return (EINVAL);
+#endif
+ to->quick = from->quick;
+ to->ifnot = from->ifnot;
+ to->match_tag_not = from->match_tag_not;
+ to->keep_state = from->keep_state;
+ to->af = from->af;
+ to->proto = from->proto;
+ to->type = from->type;
+ to->code = from->code;
+ to->flags = from->flags;
+ to->flagset = from->flagset;
+ to->min_ttl = from->min_ttl;
+ to->allow_opts = from->allow_opts;
+ to->rt = from->rt;
+ to->return_ttl = from->return_ttl;
+ to->tos = from->tos;
+ to->set_tos = from->set_tos;
+ to->anchor_relative = from->anchor_relative; /* XXX */
+ to->anchor_wildcard = from->anchor_wildcard; /* XXX */
+ to->flush = from->flush;
+ to->divert.addr = from->divert.addr;
+ to->divert.port = from->divert.port;
+ to->divert_packet.addr = from->divert_packet.addr;
+ to->divert_packet.port = from->divert_packet.port;
+
+ return (0);
+}