summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorDaniel Hartmeier <dhartmei@cvs.openbsd.org>2001-08-19 20:25:23 +0000
committerDaniel Hartmeier <dhartmei@cvs.openbsd.org>2001-08-19 20:25:23 +0000
commit15d5ebc2f96992deedc9d65931a8b6f2c6d08c1e (patch)
tree8259df3efdbaa309a333764c78945df0c3beee1d /sys/net
parente116eae02a3afd7e92c9d2cb89287f3ed0a40a74 (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.c192
-rw-r--r--sys/net/pfvar.h23
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