diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2001-08-19 20:25:23 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2001-08-19 20:25:23 +0000 |
commit | 15d5ebc2f96992deedc9d65931a8b6f2c6d08c1e (patch) | |
tree | 8259df3efdbaa309a333764c78945df0c3beee1d /sys/net | |
parent | e116eae02a3afd7e92c9d2cb89287f3ed0a40a74 (diff) |
Add new ioctls for adding/removing RDR and NAT rules to/from the active
rule sets.
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/pf.c | 192 | ||||
-rw-r--r-- | sys/net/pfvar.h | 23 |
2 files changed, 201 insertions, 14 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c index 6f52aa4127d..1f46ade3c78 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.132 2001/08/19 20:00:39 frantzen Exp $ */ +/* $OpenBSD: pf.c,v 1.133 2001/08/19 20:25:22 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -120,6 +120,8 @@ int pf_tree_key_compare(struct pf_tree_key *, struct pf_tree_key *); int pf_compare_rules(struct pf_rule *, struct pf_rule *); +int pf_compare_nats(struct pf_nat *, struct pf_nat *); +int pf_compare_rdrs(struct pf_rdr *, struct pf_rdr *); void pf_tree_rotate_left(struct pf_tree_node **); void pf_tree_rotate_right(struct pf_tree_node **); struct pf_tree_node *pf_tree_first(struct pf_tree_node *); @@ -246,6 +248,46 @@ pf_compare_rules(struct pf_rule *a, struct pf_rule *b) return (0); } +int +pf_compare_nats(struct pf_nat *a, struct pf_nat *b) +{ + if (a->saddr != b->saddr || + a->smask != b->smask || + a->daddr != b->daddr || + a->dmask != b->dmask || + a->raddr != b->raddr || + a->proto != b->proto || + a->snot != b->snot || + a->dnot != b->dnot || + a->ifnot != b->ifnot) + return (1); + if (strcmp(a->ifname, b->ifname)) + return (1); + return (0); +} + +int +pf_compare_rdrs(struct pf_rdr *a, struct pf_rdr *b) +{ + if (a->saddr != b->saddr || + a->smask != b->smask || + a->daddr != b->daddr || + a->dmask != b->dmask || + a->raddr != b->raddr || + a->dport != b->dport || + a->dport2 != b->dport2 || + a->rport != b->rport || + a->proto != b->proto || + a->snot != b->snot || + a->dnot != b->dnot || + a->ifnot != b->ifnot || + a->opts != b->opts) + return (1); + if (strcmp(a->ifname, b->ifname)) + return (1); + return (0); +} + void pf_tree_rotate_left(struct pf_tree_node **n) { @@ -897,13 +939,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_rule *oldrule = NULL, *newrule = NULL; u_int32_t nr = 0; - if (pcr->action < PF_CHANGERULE_ADD_HEAD || - pcr->action > PF_CHANGERULE_REMOVE) { + if (pcr->action < PF_CHANGE_ADD_HEAD || + pcr->action > PF_CHANGE_REMOVE) { error = EINVAL; break; } - if (pcr->action != PF_CHANGERULE_REMOVE) { + if (pcr->action != PF_CHANGE_REMOVE) { newrule = pool_get(&pf_rule_pl, PR_NOWAIT); if (newrule == NULL) { error = ENOMEM; @@ -925,9 +967,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) s = splsoftnet(); - if (pcr->action == PF_CHANGERULE_ADD_HEAD) + if (pcr->action == PF_CHANGE_ADD_HEAD) oldrule = TAILQ_FIRST(pf_rules_active); - else if (pcr->action == PF_CHANGERULE_ADD_TAIL) + else if (pcr->action == PF_CHANGE_ADD_TAIL) oldrule = TAILQ_LAST(pf_rules_active, pf_rulequeue); else { oldrule = TAILQ_FIRST(pf_rules_active); @@ -941,7 +983,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } } - if (pcr->action == PF_CHANGERULE_REMOVE) { + if (pcr->action == PF_CHANGE_REMOVE) { struct pf_tree_node *n; for (n = pf_tree_first(tree_ext_gwy); n != NULL; @@ -954,8 +996,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) if (oldrule == NULL) TAILQ_INSERT_TAIL(pf_rules_active, newrule, entries); - else if (pcr->action == PF_CHANGERULE_ADD_HEAD || - pcr->action == PF_CHANGERULE_ADD_BEFORE) + else if (pcr->action == PF_CHANGE_ADD_HEAD || + pcr->action == PF_CHANGE_ADD_BEFORE) TAILQ_INSERT_BEFORE(oldrule, newrule, entries); else TAILQ_INSERT_AFTER(pf_rules_active, oldrule, @@ -1076,6 +1118,72 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } + case DIOCCHANGENAT: { + struct pfioc_changenat *pcn = (struct pfioc_changenat *)addr; + struct pf_nat *oldnat = NULL, *newnat = NULL; + + if (pcn->action < PF_CHANGE_ADD_HEAD || + pcn->action > PF_CHANGE_REMOVE) { + error = EINVAL; + break; + } + + if (pcn->action != PF_CHANGE_REMOVE) { + newnat = pool_get(&pf_nat_pl, PR_NOWAIT); + if (newnat == NULL) { + error = ENOMEM; + break; + } + bcopy(&pcn->newnat, newnat, sizeof(struct pf_nat)); + newnat->ifp = NULL; + if (newnat->ifname[0]) { + newnat->ifp = ifunit(newnat->ifname); + if (newnat->ifp == NULL) { + pool_put(&pf_nat_pl, newnat); + error = EINVAL; + break; + } + } + } + + s = splsoftnet(); + + if (pcn->action == PF_CHANGE_ADD_HEAD) + oldnat = TAILQ_FIRST(pf_nats_active); + else if (pcn->action == PF_CHANGE_ADD_TAIL) + oldnat = TAILQ_LAST(pf_nats_active, pf_natqueue); + else { + oldnat = TAILQ_FIRST(pf_nats_active); + while ((oldnat != NULL) && pf_compare_nats(oldnat, + &pcn->oldnat)) + oldnat = TAILQ_NEXT(oldnat, entries); + if (oldnat == NULL) { + error = EINVAL; + splx(s); + break; + } + } + + if (pcn->action == PF_CHANGE_REMOVE) { + TAILQ_REMOVE(pf_nats_active, oldnat, entries); + pool_put(&pf_nat_pl, oldnat); + } else { + if (oldnat == NULL) + TAILQ_INSERT_TAIL(pf_nats_active, newnat, + entries); + else if (pcn->action == PF_CHANGE_ADD_HEAD || + pcn->action == PF_CHANGE_ADD_BEFORE) + TAILQ_INSERT_BEFORE(oldnat, newnat, entries); + else + TAILQ_INSERT_AFTER(pf_nats_active, oldnat, + newnat, entries); + } + + ticket_nats_active++; + splx(s); + break; + } + case DIOCBEGINRDRS: { u_int32_t *ticket = (u_int32_t *)addr; struct pf_rdr *rdr; @@ -1180,6 +1288,72 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } + case DIOCCHANGERDR: { + struct pfioc_changerdr *pcn = (struct pfioc_changerdr *)addr; + struct pf_rdr *oldrdr = NULL, *newrdr = NULL; + + if (pcn->action < PF_CHANGE_ADD_HEAD || + pcn->action > PF_CHANGE_REMOVE) { + error = EINVAL; + break; + } + + if (pcn->action != PF_CHANGE_REMOVE) { + newrdr = pool_get(&pf_rdr_pl, PR_NOWAIT); + if (newrdr == NULL) { + error = ENOMEM; + break; + } + bcopy(&pcn->newrdr, newrdr, sizeof(struct pf_rdr)); + newrdr->ifp = NULL; + if (newrdr->ifname[0]) { + newrdr->ifp = ifunit(newrdr->ifname); + if (newrdr->ifp == NULL) { + pool_put(&pf_rdr_pl, newrdr); + error = EINVAL; + break; + } + } + } + + s = splsoftnet(); + + if (pcn->action == PF_CHANGE_ADD_HEAD) + oldrdr = TAILQ_FIRST(pf_rdrs_active); + else if (pcn->action == PF_CHANGE_ADD_TAIL) + oldrdr = TAILQ_LAST(pf_rdrs_active, pf_rdrqueue); + else { + oldrdr = TAILQ_FIRST(pf_rdrs_active); + while ((oldrdr != NULL) && pf_compare_rdrs(oldrdr, + &pcn->oldrdr)) + oldrdr = TAILQ_NEXT(oldrdr, entries); + if (oldrdr == NULL) { + error = EINVAL; + splx(s); + break; + } + } + + if (pcn->action == PF_CHANGE_REMOVE) { + TAILQ_REMOVE(pf_rdrs_active, oldrdr, entries); + pool_put(&pf_rdr_pl, oldrdr); + } else { + if (oldrdr == NULL) + TAILQ_INSERT_TAIL(pf_rdrs_active, newrdr, + entries); + else if (pcn->action == PF_CHANGE_ADD_HEAD || + pcn->action == PF_CHANGE_ADD_BEFORE) + TAILQ_INSERT_BEFORE(oldrdr, newrdr, entries); + else + TAILQ_INSERT_AFTER(pf_rdrs_active, oldrdr, + newrdr, entries); + } + + ticket_rdrs_active++; + splx(s); + break; + } + case DIOCCLRSTATES: { struct pf_tree_node *n; diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 02eea7db9b4..931c75847d7 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.43 2001/08/19 19:03:58 dhartmei Exp $ */ +/* $OpenBSD: pfvar.h,v 1.44 2001/08/19 20:25:22 dhartmei Exp $ */ /* * Copyright (c) 2001, Daniel Hartmeier @@ -41,9 +41,9 @@ enum { PF_PASS=0, PF_DROP=1, PF_SCRUB=2 }; enum { PF_OP_IRG=1, PF_OP_EQ=2, PF_OP_NE=3, PF_OP_LT=4, PF_OP_LE=5, PF_OP_GT=6, PF_OP_GE=7, PF_OP_XRG=8 }; enum { PF_DEBUG_NONE=0, PF_DEBUG_URGENT=1, PF_DEBUG_MISC=2 }; -enum { PF_CHANGERULE_ADD_HEAD=1, PF_CHANGERULE_ADD_TAIL=2, - PF_CHANGERULE_ADD_BEFORE=3, PF_CHANGERULE_ADD_AFTER=4, - PF_CHANGERULE_REMOVE=5 }; +enum { PF_CHANGE_ADD_HEAD=1, PF_CHANGE_ADD_TAIL=2, + PF_CHANGE_ADD_BEFORE=3, PF_CHANGE_ADD_AFTER=4, + PF_CHANGE_REMOVE=5 }; struct pf_rule_addr { u_int32_t addr; @@ -255,7 +255,6 @@ struct pfioc_rule { }; struct pfioc_changerule { - u_int32_t ticket; u_int32_t action; struct pf_rule oldrule; struct pf_rule newrule; @@ -267,12 +266,24 @@ struct pfioc_nat { struct pf_nat nat; }; +struct pfioc_changenat { + u_int32_t action; + struct pf_nat oldnat; + struct pf_nat newnat; +}; + struct pfioc_rdr { u_int32_t ticket; u_int32_t nr; struct pf_rdr rdr; }; +struct pfioc_changerdr { + u_int32_t action; + struct pf_rdr oldrdr; + struct pf_rdr newrdr; +}; + struct pfioc_state { u_int32_t nr; struct pf_state state; @@ -322,6 +333,8 @@ struct pfioc_if { #define DIOCSETDEBUG _IOWR('D', 24, u_int32_t) #define DIOCGETSTATES _IOWR('D', 25, struct pfioc_states) #define DIOCCHANGERULE _IOWR('D', 26, struct pfioc_changerule) +#define DIOCCHANGENAT _IOWR('D', 27, struct pfioc_changenat) +#define DIOCCHANGERDR _IOWR('D', 28, struct pfioc_changerdr) #ifdef _KERNEL |