summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPhilipp Buehler <pb@cvs.openbsd.org>2002-06-09 08:53:09 +0000
committerPhilipp Buehler <pb@cvs.openbsd.org>2002-06-09 08:53:09 +0000
commit3ddbf2fd86133f78ccaec5e590ce9109dd6a536e (patch)
treee884d8264ae3bf01fc557708557ec77e9cf834d8 /sys
parent3ed8b10a8df515c0cb5a2a6a0962c67f1c697164 (diff)
split ioctl functions out of pf.c into pf_ioctl.c
frantzen@, dhartmei@ ok, tested kernel & userland. checked for colliding commits
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files3
-rw-r--r--sys/net/pf.c1467
-rw-r--r--sys/net/pfvar.h73
3 files changed, 92 insertions, 1451 deletions
diff --git a/sys/conf/files b/sys/conf/files
index d56221b8bd0..673347f4e90 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.251 2002/06/09 04:44:31 pb Exp $
+# $OpenBSD: files,v 1.252 2002/06/09 08:53:08 pb Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -335,6 +335,7 @@ file dev/ksyms.c ksyms needs-flag
pseudo-device pf: ifnet
file net/pf.c pf needs-flag
file net/pf_norm.c pf
+file net/pf_ioctl.c pf
# XXX machine-independent SCSI files should live somewhere here, maybe
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 23d0309d641..086f8d0db8e 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.224 2002/06/09 04:44:34 pb Exp $ */
+/* $OpenBSD: pf.c,v 1.225 2002/06/09 08:53:08 pb Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -38,7 +38,6 @@
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/filio.h>
-#include <sys/fcntl.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/kernel.h>
@@ -83,19 +82,10 @@
#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
struct pf_state_tree;
-struct pf_port_node {
- LIST_ENTRY(pf_port_node) next;
- u_int16_t port;
-};
-LIST_HEAD(pf_port_list, pf_port_node);
-
/*
* Global variables
*/
-TAILQ_HEAD(pf_natqueue, pf_nat) pf_nats[2];
-TAILQ_HEAD(pf_binatqueue, pf_binat) pf_binats[2];
-TAILQ_HEAD(pf_rdrqueue, pf_rdr) pf_rdrs[2];
struct pf_rulequeue pf_rules[2];
struct pf_rulequeue *pf_rules_active;
struct pf_rulequeue *pf_rules_inactive;
@@ -156,12 +146,6 @@ int *pftm_timeouts[PFTM_MAX] = { &pftm_tcp_first_packet,
struct pool pf_tree_pl, pf_rule_pl, pf_nat_pl, pf_sport_pl;
struct pool pf_rdr_pl, pf_state_pl, pf_binat_pl, pf_addr_pl;
-struct pf_pool_limit {
- void *pp;
- unsigned limit;
-} pf_pool_limits[PF_LIMIT_MAX] = { { &pf_state_pl, UINT_MAX },
- { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
-
void pf_addrcpy(struct pf_addr *, struct pf_addr *,
u_int8_t);
int pf_compare_rules(struct pf_rule *,
@@ -184,11 +168,6 @@ void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
void pf_print_state(struct pf_state *);
void pf_print_flags(u_int8_t);
-void pfattach(int);
-int pfopen(dev_t, int, int, struct proc *);
-int pfclose(dev_t, int, int, struct proc *);
-int pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
-
u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,
u_int8_t);
void pf_change_ap(struct pf_addr *, u_int16_t *,
@@ -250,6 +229,9 @@ void pf_route(struct mbuf **, struct pf_rule *, int);
void pf_route6(struct mbuf **, struct pf_rule *, int);
int pf_socket_lookup(uid_t *, gid_t *, int, int, int,
struct pf_pdesc *);
+struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = { { &pf_state_pl, UINT_MAX },
+ { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
+
#if NPFLOG > 0
@@ -282,10 +264,15 @@ int pf_socket_lookup(uid_t *, gid_t *, int, int, int,
static __inline int pf_state_compare(struct pf_tree_node *,
struct pf_tree_node *);
-RB_HEAD(pf_state_tree, pf_tree_node) tree_lan_ext, tree_ext_gwy;
-RB_PROTOTYPE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
+
+struct pf_state_tree tree_lan_ext, tree_ext_gwy;
RB_GENERATE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
+struct pf_rulequeue pf_rules[2];
+struct pf_natqueue pf_nats[2];
+struct pf_binatqueue pf_binats[2];
+struct pf_rdrqueue pf_rdrs[2];
+
static __inline int
pf_state_compare(struct pf_tree_node *a, struct pf_tree_node *b)
{
@@ -852,1416 +839,6 @@ pf_print_flags(u_int8_t f)
printf("W");
}
-void
-pfattach(int num)
-{
- pool_init(&pf_tree_pl, sizeof(struct pf_tree_node), 0, 0, 0, "pftrpl",
- NULL);
- pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
- &pool_allocator_nointr);
- pool_init(&pf_nat_pl, sizeof(struct pf_nat), 0, 0, 0, "pfnatpl",
- &pool_allocator_nointr);
- pool_init(&pf_binat_pl, sizeof(struct pf_binat), 0, 0, 0, "pfbinatpl",
- &pool_allocator_nointr);
- pool_init(&pf_rdr_pl, sizeof(struct pf_rdr), 0, 0, 0, "pfrdrpl",
- &pool_allocator_nointr);
- pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
- NULL);
- pool_init(&pf_sport_pl, sizeof(struct pf_port_node), 0, 0, 0, "pfsport",
- NULL);
- pool_init(&pf_addr_pl, sizeof(struct pf_addr_dyn), 0, 0, 0, "pfaddr",
- NULL);
-
- TAILQ_INIT(&pf_rules[0]);
- TAILQ_INIT(&pf_rules[1]);
- TAILQ_INIT(&pf_nats[0]);
- TAILQ_INIT(&pf_nats[1]);
- TAILQ_INIT(&pf_binats[0]);
- TAILQ_INIT(&pf_binats[1]);
- TAILQ_INIT(&pf_rdrs[0]);
- TAILQ_INIT(&pf_rdrs[1]);
- pf_rules_active = &pf_rules[0];
- pf_rules_inactive = &pf_rules[1];
- pf_nats_active = &pf_nats[0];
- pf_nats_inactive = &pf_nats[1];
- pf_binats_active = &pf_binats[0];
- pf_binats_inactive = &pf_binats[1];
- pf_rdrs_active = &pf_rdrs[0];
- pf_rdrs_inactive = &pf_rdrs[1];
-
- LIST_INIT(&pf_tcp_ports);
- LIST_INIT(&pf_udp_ports);
-
- timeout_set(&pf_expire_to, pf_purge_timeout, &pf_expire_to);
- timeout_add(&pf_expire_to, pftm_interval * hz);
-
- pf_normalize_init();
- pf_status.debug = PF_DEBUG_URGENT;
-}
-
-int
-pfopen(dev_t dev, int flags, int fmt, struct proc *p)
-{
- if (minor(dev) >= 1)
- return (ENXIO);
- return (0);
-}
-
-int
-pfclose(dev_t dev, int flags, int fmt, struct proc *p)
-{
- if (minor(dev) >= 1)
- return (ENXIO);
- return (0);
-}
-
-int
-pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
-{
- int error = 0;
- int s;
-
- /* XXX keep in sync with switch() below */
- if (securelevel > 1)
- switch (cmd) {
- case DIOCGETRULES:
- case DIOCGETRULE:
- case DIOCGETNATS:
- case DIOCGETNAT:
- case DIOCGETBINATS:
- case DIOCGETBINAT:
- case DIOCGETRDRS:
- case DIOCGETRDR:
- case DIOCGETSTATE:
- case DIOCSETSTATUSIF:
- case DIOCGETSTATUS:
- case DIOCCLRSTATUS:
- case DIOCNATLOOK:
- case DIOCSETDEBUG:
- case DIOCGETSTATES:
- case DIOCGETTIMEOUT:
- case DIOCCLRRULECTRS:
- case DIOCGETLIMIT:
- break;
- default:
- return (EPERM);
- }
-
- if (!(flags & FWRITE))
- switch (cmd) {
- case DIOCGETRULES:
- case DIOCGETRULE:
- case DIOCGETNATS:
- case DIOCGETNAT:
- case DIOCGETRDRS:
- case DIOCGETRDR:
- case DIOCGETSTATE:
- case DIOCGETSTATUS:
- case DIOCGETSTATES:
- case DIOCGETTIMEOUT:
- case DIOCGETBINATS:
- case DIOCGETBINAT:
- case DIOCGETLIMIT:
- break;
- default:
- return (EACCES);
- }
-
- switch (cmd) {
-
- case DIOCSTART:
- if (pf_status.running)
- error = EEXIST;
- else {
- u_int32_t states = pf_status.states;
- bzero(&pf_status, sizeof(struct pf_status));
- pf_status.running = 1;
- pf_status.states = states;
- pf_status.since = time.tv_sec;
- DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
- }
- break;
-
- case DIOCSTOP:
- if (!pf_status.running)
- error = ENOENT;
- else {
- pf_status.running = 0;
- DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
- }
- break;
-
- case DIOCBEGINRULES: {
- u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_rule *rule;
-
- while ((rule = TAILQ_FIRST(pf_rules_inactive)) != NULL) {
- TAILQ_REMOVE(pf_rules_inactive, rule, entries);
- pf_dynaddr_remove(&rule->src.addr);
- pf_dynaddr_remove(&rule->dst.addr);
- pool_put(&pf_rule_pl, rule);
- }
- *ticket = ++ticket_rules_inactive;
- break;
- }
-
- case DIOCADDRULE: {
- struct pfioc_rule *pr = (struct pfioc_rule *)addr;
- struct pf_rule *rule, *tail;
-
- if (pr->ticket != ticket_rules_inactive) {
- error = EBUSY;
- break;
- }
- rule = pool_get(&pf_rule_pl, PR_NOWAIT);
- if (rule == NULL) {
- error = ENOMEM;
- break;
- }
- bcopy(&pr->rule, rule, sizeof(struct pf_rule));
-#ifndef INET
- if (rule->af == AF_INET) {
- pool_put(&pf_rule_pl, rule);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET */
-#ifndef INET6
- if (rule->af == AF_INET6) {
- pool_put(&pf_rule_pl, rule);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET6 */
- tail = TAILQ_LAST(pf_rules_inactive, pf_rulequeue);
- if (tail)
- rule->nr = tail->nr + 1;
- else
- rule->nr = 0;
- if (rule->ifname[0]) {
- rule->ifp = ifunit(rule->ifname);
- if (rule->ifp == NULL) {
- pool_put(&pf_rule_pl, rule);
- error = EINVAL;
- break;
- }
- } else
- rule->ifp = NULL;
- if (rule->rt_ifname[0]) {
- rule->rt_ifp = ifunit(rule->rt_ifname);
- if (rule->rt_ifname == NULL) {
- pool_put(&pf_rule_pl, rule);
- error = EINVAL;
- break;
- }
- } else
- rule->rt_ifp = NULL;
- if (pf_dynaddr_setup(&rule->src.addr, rule->af) ||
- pf_dynaddr_setup(&rule->dst.addr, rule->af)) {
- pf_dynaddr_remove(&rule->src.addr);
- pf_dynaddr_remove(&rule->dst.addr);
- pool_put(&pf_rule_pl, rule);
- error = EINVAL;
- break;
- }
- rule->evaluations = rule->packets = rule->bytes = 0;
- TAILQ_INSERT_TAIL(pf_rules_inactive, rule, entries);
- break;
- }
-
- case DIOCCOMMITRULES: {
- u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_rulequeue *old_rules;
- struct pf_rule *rule;
- struct pf_tree_node *n;
-
- if (*ticket != ticket_rules_inactive) {
- error = EBUSY;
- break;
- }
-
- /* Swap rules, keep the old. */
- s = splsoftnet();
- /*
- * Rules are about to get freed, clear rule pointers in states
- */
- RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
- n->state->rule.ptr = NULL;
- old_rules = pf_rules_active;
- pf_rules_active = pf_rules_inactive;
- pf_rules_inactive = old_rules;
- ticket_rules_active = ticket_rules_inactive;
- pf_calc_skip_steps(pf_rules_active);
- splx(s);
-
- /* Purge the old rule list. */
- while ((rule = TAILQ_FIRST(old_rules)) != NULL) {
- TAILQ_REMOVE(old_rules, rule, entries);
- pf_dynaddr_remove(&rule->src.addr);
- pf_dynaddr_remove(&rule->dst.addr);
- pool_put(&pf_rule_pl, rule);
- }
- break;
- }
-
- case DIOCGETRULES: {
- struct pfioc_rule *pr = (struct pfioc_rule *)addr;
- struct pf_rule *tail;
-
- s = splsoftnet();
- tail = TAILQ_LAST(pf_rules_active, pf_rulequeue);
- if (tail)
- pr->nr = tail->nr + 1;
- else
- pr->nr = 0;
- pr->ticket = ticket_rules_active;
- splx(s);
- break;
- }
-
- case DIOCGETRULE: {
- struct pfioc_rule *pr = (struct pfioc_rule *)addr;
- struct pf_rule *rule;
-
- if (pr->ticket != ticket_rules_active) {
- error = EBUSY;
- break;
- }
- s = splsoftnet();
- rule = TAILQ_FIRST(pf_rules_active);
- while ((rule != NULL) && (rule->nr != pr->nr))
- rule = TAILQ_NEXT(rule, entries);
- if (rule == NULL) {
- error = EBUSY;
- splx(s);
- break;
- }
- bcopy(rule, &pr->rule, sizeof(struct pf_rule));
- pf_dynaddr_copyout(&pr->rule.src.addr);
- pf_dynaddr_copyout(&pr->rule.dst.addr);
- splx(s);
- break;
- }
-
- case DIOCCHANGERULE: {
- struct pfioc_changerule *pcr = (struct pfioc_changerule *)addr;
- struct pf_rule *oldrule = NULL, *newrule = NULL;
- u_int32_t nr = 0;
-
- if (pcr->action < PF_CHANGE_ADD_HEAD ||
- pcr->action > PF_CHANGE_REMOVE) {
- error = EINVAL;
- break;
- }
-
- if (pcr->action != PF_CHANGE_REMOVE) {
- newrule = pool_get(&pf_rule_pl, PR_NOWAIT);
- if (newrule == NULL) {
- error = ENOMEM;
- break;
- }
- bcopy(&pcr->newrule, newrule, sizeof(struct pf_rule));
-#ifndef INET
- if (newrule->af == AF_INET) {
- pool_put(&pf_rule_pl, newrule);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET */
-#ifndef INET6
- if (newrule->af == AF_INET6) {
- pool_put(&pf_rule_pl, newrule);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET6 */
- if (newrule->ifname[0]) {
- newrule->ifp = ifunit(newrule->ifname);
- if (newrule->ifp == NULL) {
- pool_put(&pf_rule_pl, newrule);
- error = EINVAL;
- break;
- }
- } else
- newrule->ifp = NULL;
- if (newrule->rt_ifname[0]) {
- newrule->rt_ifp = ifunit(newrule->rt_ifname);
- if (newrule->rt_ifname == NULL) {
- pool_put(&pf_rule_pl, newrule);
- error = EINVAL;
- break;
- }
- } else
- newrule->rt_ifp = NULL;
- if (pf_dynaddr_setup(&newrule->src.addr, newrule->af) ||
- pf_dynaddr_setup(&newrule->dst.addr, newrule->af)) {
- pf_dynaddr_remove(&newrule->src.addr);
- pf_dynaddr_remove(&newrule->dst.addr);
- pool_put(&pf_rule_pl, newrule);
- error = EINVAL;
- break;
- }
- newrule->evaluations = newrule->packets = 0;
- newrule->bytes = 0;
- }
-
- s = splsoftnet();
-
- if (pcr->action == PF_CHANGE_ADD_HEAD)
- oldrule = TAILQ_FIRST(pf_rules_active);
- else if (pcr->action == PF_CHANGE_ADD_TAIL)
- oldrule = TAILQ_LAST(pf_rules_active, pf_rulequeue);
- else {
- oldrule = TAILQ_FIRST(pf_rules_active);
- while ((oldrule != NULL) && pf_compare_rules(oldrule,
- &pcr->oldrule))
- oldrule = TAILQ_NEXT(oldrule, entries);
- if (oldrule == NULL) {
- error = EINVAL;
- splx(s);
- break;
- }
- }
-
- if (pcr->action == PF_CHANGE_REMOVE) {
- struct pf_tree_node *n;
-
- RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
- if (n->state->rule.ptr == oldrule)
- n->state->rule.ptr = NULL;
- TAILQ_REMOVE(pf_rules_active, oldrule, entries);
- pf_dynaddr_remove(&oldrule->src.addr);
- pf_dynaddr_remove(&oldrule->dst.addr);
- pool_put(&pf_rule_pl, oldrule);
- } else {
- if (oldrule == NULL)
- TAILQ_INSERT_TAIL(pf_rules_active, newrule,
- entries);
- 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,
- newrule, entries);
- }
-
- TAILQ_FOREACH(oldrule, pf_rules_active, entries)
- oldrule->nr = nr++;
-
- pf_calc_skip_steps(pf_rules_active);
-
- ticket_rules_active++;
- splx(s);
- break;
- }
-
- case DIOCBEGINNATS: {
- u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_nat *nat;
-
- while ((nat = TAILQ_FIRST(pf_nats_inactive)) != NULL) {
- pf_dynaddr_remove(&nat->saddr);
- pf_dynaddr_remove(&nat->daddr);
- pf_dynaddr_remove(&nat->raddr);
- TAILQ_REMOVE(pf_nats_inactive, nat, entries);
- pool_put(&pf_nat_pl, nat);
- }
- *ticket = ++ticket_nats_inactive;
- break;
- }
-
- case DIOCADDNAT: {
- struct pfioc_nat *pn = (struct pfioc_nat *)addr;
- struct pf_nat *nat;
-
- if (pn->ticket != ticket_nats_inactive) {
- error = EBUSY;
- break;
- }
- nat = pool_get(&pf_nat_pl, PR_NOWAIT);
- if (nat == NULL) {
- error = ENOMEM;
- break;
- }
- bcopy(&pn->nat, nat, sizeof(struct pf_nat));
-#ifndef INET
- if (nat->af == AF_INET) {
- pool_put(&pf_nat_pl, nat);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET */
-#ifndef INET6
- if (nat->af == AF_INET6) {
- pool_put(&pf_nat_pl, nat);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET6 */
- if (nat->ifname[0]) {
- nat->ifp = ifunit(nat->ifname);
- if (nat->ifp == NULL) {
- pool_put(&pf_nat_pl, nat);
- error = EINVAL;
- break;
- }
- } else
- nat->ifp = NULL;
- if (pf_dynaddr_setup(&nat->saddr, nat->af) ||
- pf_dynaddr_setup(&nat->daddr, nat->af) ||
- pf_dynaddr_setup(&nat->raddr, nat->af)) {
- pf_dynaddr_remove(&nat->saddr);
- pf_dynaddr_remove(&nat->daddr);
- pf_dynaddr_remove(&nat->raddr);
- pool_put(&pf_nat_pl, nat);
- error = EINVAL;
- break;
- }
- TAILQ_INSERT_TAIL(pf_nats_inactive, nat, entries);
- break;
- }
-
- case DIOCCOMMITNATS: {
- u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_natqueue *old_nats;
- struct pf_nat *nat;
-
- if (*ticket != ticket_nats_inactive) {
- error = EBUSY;
- break;
- }
-
- /* Swap nats, keep the old. */
- s = splsoftnet();
- old_nats = pf_nats_active;
- pf_nats_active = pf_nats_inactive;
- pf_nats_inactive = old_nats;
- ticket_nats_active = ticket_nats_inactive;
- splx(s);
-
- /* Purge the old nat list */
- while ((nat = TAILQ_FIRST(old_nats)) != NULL) {
- pf_dynaddr_remove(&nat->saddr);
- pf_dynaddr_remove(&nat->daddr);
- pf_dynaddr_remove(&nat->raddr);
- TAILQ_REMOVE(old_nats, nat, entries);
- pool_put(&pf_nat_pl, nat);
- }
- break;
- }
-
- case DIOCGETNATS: {
- struct pfioc_nat *pn = (struct pfioc_nat *)addr;
- struct pf_nat *nat;
-
- pn->nr = 0;
- s = splsoftnet();
- TAILQ_FOREACH(nat, pf_nats_active, entries)
- pn->nr++;
- pn->ticket = ticket_nats_active;
- splx(s);
- break;
- }
-
- case DIOCGETNAT: {
- struct pfioc_nat *pn = (struct pfioc_nat *)addr;
- struct pf_nat *nat;
- u_int32_t nr;
-
- if (pn->ticket != ticket_nats_active) {
- error = EBUSY;
- break;
- }
- nr = 0;
- s = splsoftnet();
- nat = TAILQ_FIRST(pf_nats_active);
- while ((nat != NULL) && (nr < pn->nr)) {
- nat = TAILQ_NEXT(nat, entries);
- nr++;
- }
- if (nat == NULL) {
- error = EBUSY;
- splx(s);
- break;
- }
- bcopy(nat, &pn->nat, sizeof(struct pf_nat));
- pf_dynaddr_copyout(&pn->nat.saddr);
- pf_dynaddr_copyout(&pn->nat.daddr);
- pf_dynaddr_copyout(&pn->nat.raddr);
- splx(s);
- 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));
-#ifndef INET
- if (newnat->af == AF_INET) {
- pool_put(&pf_nat_pl, newnat);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET */
-#ifndef INET6
- if (newnat->af == AF_INET6) {
- pool_put(&pf_nat_pl, newnat);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET6 */
- if (newnat->ifname[0]) {
- newnat->ifp = ifunit(newnat->ifname);
- if (newnat->ifp == NULL) {
- pool_put(&pf_nat_pl, newnat);
- error = EINVAL;
- break;
- }
- } else
- newnat->ifp = NULL;
- if (pf_dynaddr_setup(&newnat->saddr, newnat->af) ||
- pf_dynaddr_setup(&newnat->daddr, newnat->af) ||
- pf_dynaddr_setup(&newnat->raddr, newnat->af)) {
- pf_dynaddr_remove(&newnat->saddr);
- pf_dynaddr_remove(&newnat->daddr);
- pf_dynaddr_remove(&newnat->raddr);
- 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) {
- pf_dynaddr_remove(&oldnat->saddr);
- pf_dynaddr_remove(&oldnat->daddr);
- pf_dynaddr_remove(&oldnat->raddr);
- 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 DIOCBEGINBINATS: {
- u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_binat *binat;
-
- while ((binat = TAILQ_FIRST(pf_binats_inactive)) != NULL) {
- TAILQ_REMOVE(pf_binats_inactive, binat, entries);
- pf_dynaddr_remove(&binat->saddr);
- pf_dynaddr_remove(&binat->daddr);
- pf_dynaddr_remove(&binat->raddr);
- pool_put(&pf_binat_pl, binat);
- }
- *ticket = ++ticket_binats_inactive;
- break;
- }
-
- case DIOCADDBINAT: {
- struct pfioc_binat *pb = (struct pfioc_binat *)addr;
- struct pf_binat *binat;
-
- if (pb->ticket != ticket_binats_inactive) {
- error = EBUSY;
- break;
- }
- binat = pool_get(&pf_binat_pl, PR_NOWAIT);
- if (binat == NULL) {
- error = ENOMEM;
- break;
- }
- bcopy(&pb->binat, binat, sizeof(struct pf_binat));
-#ifndef INET
- if (binat->af == AF_INET) {
- pool_put(&pf_binat_pl, binat);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET */
-#ifndef INET6
- if (binat->af == AF_INET6) {
- pool_put(&pf_binat_pl, binat);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET6 */
- if (binat->ifname[0]) {
- binat->ifp = ifunit(binat->ifname);
- if (binat->ifp == NULL) {
- pool_put(&pf_binat_pl, binat);
- error = EINVAL;
- break;
- }
- } else
- binat->ifp = NULL;
- if (pf_dynaddr_setup(&binat->saddr, binat->af) ||
- pf_dynaddr_setup(&binat->daddr, binat->af) ||
- pf_dynaddr_setup(&binat->raddr, binat->af)) {
- pf_dynaddr_remove(&binat->saddr);
- pf_dynaddr_remove(&binat->daddr);
- pf_dynaddr_remove(&binat->raddr);
- pool_put(&pf_binat_pl, binat);
- error = EINVAL;
- break;
- }
- TAILQ_INSERT_TAIL(pf_binats_inactive, binat, entries);
- break;
- }
-
- case DIOCCOMMITBINATS: {
- u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_binatqueue *old_binats;
- struct pf_binat *binat;
-
- if (*ticket != ticket_binats_inactive) {
- error = EBUSY;
- break;
- }
-
- /* Swap binats, keep the old. */
- s = splsoftnet();
- old_binats = pf_binats_active;
- pf_binats_active = pf_binats_inactive;
- pf_binats_inactive = old_binats;
- ticket_binats_active = ticket_binats_inactive;
- splx(s);
-
- /* Purge the old binat list */
- while ((binat = TAILQ_FIRST(old_binats)) != NULL) {
- TAILQ_REMOVE(old_binats, binat, entries);
- pf_dynaddr_remove(&binat->saddr);
- pf_dynaddr_remove(&binat->daddr);
- pf_dynaddr_remove(&binat->raddr);
- pool_put(&pf_binat_pl, binat);
- }
- break;
- }
-
- case DIOCGETBINATS: {
- struct pfioc_binat *pb = (struct pfioc_binat *)addr;
- struct pf_binat *binat;
-
- pb->nr = 0;
- s = splsoftnet();
- TAILQ_FOREACH(binat, pf_binats_active, entries)
- pb->nr++;
- pb->ticket = ticket_binats_active;
- splx(s);
- break;
- }
-
- case DIOCGETBINAT: {
- struct pfioc_binat *pb = (struct pfioc_binat *)addr;
- struct pf_binat *binat;
- u_int32_t nr;
-
- if (pb->ticket != ticket_binats_active) {
- error = EBUSY;
- break;
- }
- nr = 0;
- s = splsoftnet();
- binat = TAILQ_FIRST(pf_binats_active);
- while ((binat != NULL) && (nr < pb->nr)) {
- binat = TAILQ_NEXT(binat, entries);
- nr++;
- }
- if (binat == NULL) {
- error = EBUSY;
- splx(s);
- break;
- }
- bcopy(binat, &pb->binat, sizeof(struct pf_binat));
- pf_dynaddr_copyout(&pb->binat.saddr);
- pf_dynaddr_copyout(&pb->binat.daddr);
- pf_dynaddr_copyout(&pb->binat.raddr);
- splx(s);
- break;
- }
-
- case DIOCCHANGEBINAT: {
- struct pfioc_changebinat *pcn = (struct pfioc_changebinat *)addr;
- struct pf_binat *oldbinat = NULL, *newbinat = NULL;
-
- if (pcn->action < PF_CHANGE_ADD_HEAD ||
- pcn->action > PF_CHANGE_REMOVE) {
- error = EINVAL;
- break;
- }
-
- if (pcn->action != PF_CHANGE_REMOVE) {
- newbinat = pool_get(&pf_binat_pl, PR_NOWAIT);
- if (newbinat == NULL) {
- error = ENOMEM;
- break;
- }
- bcopy(&pcn->newbinat, newbinat,
- sizeof(struct pf_binat));
-#ifndef INET
- if (newbinat->af == AF_INET) {
- pool_put(&pf_binat_pl, newbinat);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET */
-#ifndef INET6
- if (newbinat->af == AF_INET6) {
- pool_put(&pf_binat_pl, newbinat);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET6 */
- if (newbinat->ifname[0]) {
- newbinat->ifp = ifunit(newbinat->ifname);
- if (newbinat->ifp == NULL) {
- pool_put(&pf_binat_pl, newbinat);
- error = EINVAL;
- break;
- }
- } else
- newbinat->ifp = NULL;
- if (pf_dynaddr_setup(&newbinat->saddr, newbinat->af) ||
- pf_dynaddr_setup(&newbinat->daddr, newbinat->af) ||
- pf_dynaddr_setup(&newbinat->raddr, newbinat->af)) {
- pf_dynaddr_remove(&newbinat->saddr);
- pf_dynaddr_remove(&newbinat->daddr);
- pf_dynaddr_remove(&newbinat->raddr);
- pool_put(&pf_binat_pl, newbinat);
- error = EINVAL;
- break;
- }
- }
-
- s = splsoftnet();
-
- if (pcn->action == PF_CHANGE_ADD_HEAD)
- oldbinat = TAILQ_FIRST(pf_binats_active);
- else if (pcn->action == PF_CHANGE_ADD_TAIL)
- oldbinat = TAILQ_LAST(pf_binats_active, pf_binatqueue);
- else {
- oldbinat = TAILQ_FIRST(pf_binats_active);
- while ((oldbinat != NULL) && pf_compare_binats(oldbinat,
- &pcn->oldbinat))
- oldbinat = TAILQ_NEXT(oldbinat, entries);
- if (oldbinat == NULL) {
- error = EINVAL;
- splx(s);
- break;
- }
- }
-
- if (pcn->action == PF_CHANGE_REMOVE) {
- TAILQ_REMOVE(pf_binats_active, oldbinat, entries);
- pf_dynaddr_remove(&oldbinat->saddr);
- pf_dynaddr_remove(&oldbinat->daddr);
- pf_dynaddr_remove(&oldbinat->raddr);
- pool_put(&pf_binat_pl, oldbinat);
- } else {
- if (oldbinat == NULL)
- TAILQ_INSERT_TAIL(pf_binats_active, newbinat,
- entries);
- else if (pcn->action == PF_CHANGE_ADD_HEAD ||
- pcn->action == PF_CHANGE_ADD_BEFORE)
- TAILQ_INSERT_BEFORE(oldbinat, newbinat,
- entries);
- else
- TAILQ_INSERT_AFTER(pf_binats_active, oldbinat,
- newbinat, entries);
- }
-
- ticket_binats_active++;
- splx(s);
- break;
- }
-
- case DIOCBEGINRDRS: {
- u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_rdr *rdr;
-
- while ((rdr = TAILQ_FIRST(pf_rdrs_inactive)) != NULL) {
- TAILQ_REMOVE(pf_rdrs_inactive, rdr, entries);
- pf_dynaddr_remove(&rdr->saddr);
- pf_dynaddr_remove(&rdr->daddr);
- pf_dynaddr_remove(&rdr->raddr);
- pool_put(&pf_rdr_pl, rdr);
- }
- *ticket = ++ticket_rdrs_inactive;
- break;
- }
-
- case DIOCADDRDR: {
- struct pfioc_rdr *pr = (struct pfioc_rdr *)addr;
- struct pf_rdr *rdr;
-
- if (pr->ticket != ticket_rdrs_inactive) {
- error = EBUSY;
- break;
- }
- rdr = pool_get(&pf_rdr_pl, PR_NOWAIT);
- if (rdr == NULL) {
- error = ENOMEM;
- break;
- }
- bcopy(&pr->rdr, rdr, sizeof(struct pf_rdr));
-#ifndef INET
- if (rdr->af == AF_INET) {
- pool_put(&pf_rdr_pl, rdr);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET */
-#ifndef INET6
- if (rdr->af == AF_INET6) {
- pool_put(&pf_rdr_pl, rdr);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET6 */
- if (rdr->ifname[0]) {
- rdr->ifp = ifunit(rdr->ifname);
- if (rdr->ifp == NULL) {
- pool_put(&pf_rdr_pl, rdr);
- error = EINVAL;
- break;
- }
- } else
- rdr->ifp = NULL;
- if (pf_dynaddr_setup(&rdr->saddr, rdr->af) ||
- pf_dynaddr_setup(&rdr->daddr, rdr->af) ||
- pf_dynaddr_setup(&rdr->raddr, rdr->af)) {
- pf_dynaddr_remove(&rdr->saddr);
- pf_dynaddr_remove(&rdr->daddr);
- pf_dynaddr_remove(&rdr->raddr);
- pool_put(&pf_rdr_pl, rdr);
- error = EINVAL;
- break;
- }
- TAILQ_INSERT_TAIL(pf_rdrs_inactive, rdr, entries);
- break;
- }
-
- case DIOCCOMMITRDRS: {
- u_int32_t *ticket = (u_int32_t *)addr;
- struct pf_rdrqueue *old_rdrs;
- struct pf_rdr *rdr;
-
- if (*ticket != ticket_rdrs_inactive) {
- error = EBUSY;
- break;
- }
-
- /* Swap rdrs, keep the old. */
- s = splsoftnet();
- old_rdrs = pf_rdrs_active;
- pf_rdrs_active = pf_rdrs_inactive;
- pf_rdrs_inactive = old_rdrs;
- ticket_rdrs_active = ticket_rdrs_inactive;
- splx(s);
-
- /* Purge the old rdr list */
- while ((rdr = TAILQ_FIRST(old_rdrs)) != NULL) {
- TAILQ_REMOVE(old_rdrs, rdr, entries);
- pf_dynaddr_remove(&rdr->saddr);
- pf_dynaddr_remove(&rdr->daddr);
- pf_dynaddr_remove(&rdr->raddr);
- pool_put(&pf_rdr_pl, rdr);
- }
- break;
- }
-
- case DIOCGETRDRS: {
- struct pfioc_rdr *pr = (struct pfioc_rdr *)addr;
- struct pf_rdr *rdr;
-
- pr->nr = 0;
- s = splsoftnet();
- TAILQ_FOREACH(rdr, pf_rdrs_active, entries)
- pr->nr++;
- pr->ticket = ticket_rdrs_active;
- splx(s);
- break;
- }
-
- case DIOCGETRDR: {
- struct pfioc_rdr *pr = (struct pfioc_rdr *)addr;
- struct pf_rdr *rdr;
- u_int32_t nr;
-
- if (pr->ticket != ticket_rdrs_active) {
- error = EBUSY;
- break;
- }
- nr = 0;
- s = splsoftnet();
- rdr = TAILQ_FIRST(pf_rdrs_active);
- while ((rdr != NULL) && (nr < pr->nr)) {
- rdr = TAILQ_NEXT(rdr, entries);
- nr++;
- }
- if (rdr == NULL) {
- error = EBUSY;
- splx(s);
- break;
- }
- bcopy(rdr, &pr->rdr, sizeof(struct pf_rdr));
- pf_dynaddr_copyout(&pr->rdr.saddr);
- pf_dynaddr_copyout(&pr->rdr.daddr);
- pf_dynaddr_copyout(&pr->rdr.raddr);
- splx(s);
- 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));
-#ifndef INET
- if (newrdr->af == AF_INET) {
- pool_put(&pf_rdr_pl, newrdr);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET */
-#ifndef INET6
- if (newrdr->af == AF_INET6) {
- pool_put(&pf_rdr_pl, newrdr);
- error = EAFNOSUPPORT;
- break;
- }
-#endif /* INET6 */
- if (newrdr->ifname[0]) {
- newrdr->ifp = ifunit(newrdr->ifname);
- if (newrdr->ifp == NULL) {
- pool_put(&pf_rdr_pl, newrdr);
- error = EINVAL;
- break;
- }
- } else
- newrdr->ifp = NULL;
- if (pf_dynaddr_setup(&newrdr->saddr, newrdr->af) ||
- pf_dynaddr_setup(&newrdr->daddr, newrdr->af) ||
- pf_dynaddr_setup(&newrdr->raddr, newrdr->af)) {
- pf_dynaddr_remove(&newrdr->saddr);
- pf_dynaddr_remove(&newrdr->daddr);
- pf_dynaddr_remove(&newrdr->raddr);
- 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);
- pf_dynaddr_remove(&oldrdr->saddr);
- pf_dynaddr_remove(&oldrdr->daddr);
- pf_dynaddr_remove(&oldrdr->raddr);
- 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;
-
- s = splsoftnet();
- RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
- n->state->expire = 0;
- pf_purge_expired_states();
- pf_status.states = 0;
- splx(s);
- break;
- }
-
- case DIOCKILLSTATES: {
- struct pf_tree_node *n;
- struct pf_state *st;
- struct pfioc_state_kill *psk =
- (struct pfioc_state_kill *)addr;
- int killed = 0;
-
- s = splsoftnet();
- RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) {
- st = n->state;
- if ((!psk->psk_af || st->af == psk->psk_af) &&
- (!psk->psk_proto || psk->psk_proto == st->proto) &&
- PF_MATCHA(psk->psk_src.not, &psk->psk_src.addr.addr,
- &psk->psk_src.mask, &st->lan.addr, st->af) &&
- PF_MATCHA(psk->psk_dst.not, &psk->psk_dst.addr.addr,
- &psk->psk_dst.mask, &st->ext.addr, st->af) &&
- (psk->psk_src.port_op == 0 ||
- pf_match_port(psk->psk_src.port_op,
- psk->psk_src.port[0], psk->psk_src.port[1],
- st->lan.port)) &&
- (psk->psk_dst.port_op == 0 ||
- pf_match_port(psk->psk_dst.port_op,
- psk->psk_dst.port[0], psk->psk_dst.port[1],
- st->ext.port))) {
- st->expire = 0;
- killed++;
- }
- }
- pf_purge_expired_states();
- splx(s);
- psk->psk_af = killed;
- break;
- }
-
- case DIOCADDSTATE: {
- struct pfioc_state *ps = (struct pfioc_state *)addr;
- struct pf_state *state;
-
- state = pool_get(&pf_state_pl, PR_NOWAIT);
- if (state == NULL) {
- error = ENOMEM;
- break;
- }
- s = splsoftnet();
- bcopy(&ps->state, state, sizeof(struct pf_state));
- state->rule.ptr = NULL;
- state->creation = time.tv_sec;
- state->expire += state->creation;
- state->packets = 0;
- state->bytes = 0;
- if (pf_insert_state(state)) {
- pool_put(&pf_state_pl, state);
- error = ENOMEM;
- }
- splx(s);
- }
-
- case DIOCGETSTATE: {
- struct pfioc_state *ps = (struct pfioc_state *)addr;
- struct pf_tree_node *n;
- u_int32_t nr;
- int secs;
-
- nr = 0;
- s = splsoftnet();
- RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) {
- if (nr >= ps->nr)
- break;
- nr++;
- }
- if (n == NULL) {
- error = EBUSY;
- splx(s);
- break;
- }
- bcopy(n->state, &ps->state, sizeof(struct pf_state));
- if (n->state->rule.ptr == NULL)
- ps->state.rule.nr = -1;
- else
- ps->state.rule.nr = n->state->rule.ptr->nr;
- splx(s);
- secs = time.tv_sec;
- ps->state.creation = secs - ps->state.creation;
- if (ps->state.expire <= secs)
- ps->state.expire = 0;
- else
- ps->state.expire -= secs;
- break;
- }
-
- case DIOCGETSTATES: {
- struct pfioc_states *ps = (struct pfioc_states *)addr;
- struct pf_tree_node *n;
- struct pf_state *p, pstore;
- u_int32_t nr = 0;
- int space = ps->ps_len;
-
- if (space == 0) {
- s = splsoftnet();
- RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
- nr++;
- splx(s);
- ps->ps_len = sizeof(struct pf_state) * nr;
- return (0);
- }
-
- s = splsoftnet();
- p = ps->ps_states;
- RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) {
- int secs = time.tv_sec;
-
- if ((nr + 1) * sizeof(*p) > ps->ps_len)
- break;
-
- bcopy(n->state, &pstore, sizeof(pstore));
- if (n->state->rule.ptr == NULL)
- pstore.rule.nr = -1;
- else
- pstore.rule.nr = n->state->rule.ptr->nr;
- pstore.creation = secs - pstore.creation;
- if (pstore.expire <= secs)
- pstore.expire = 0;
- else
- pstore.expire -= secs;
- error = copyout(&pstore, p, sizeof(*p));
- if (error) {
- splx(s);
- goto fail;
- }
- p++;
- nr++;
- }
- ps->ps_len = sizeof(struct pf_state) * nr;
- splx(s);
- break;
- }
-
- case DIOCSETSTATUSIF: {
- struct pfioc_if *pi = (struct pfioc_if *)addr;
- struct ifnet *ifp;
-
- if ((ifp = ifunit(pi->ifname)) == NULL)
- error = EINVAL;
- else
- status_ifp = ifp;
- break;
- }
-
- case DIOCGETSTATUS: {
- struct pf_status *s = (struct pf_status *)addr;
- bcopy(&pf_status, s, sizeof(struct pf_status));
- break;
- }
-
- case DIOCCLRSTATUS: {
- u_int32_t running = pf_status.running;
- u_int32_t states = pf_status.states;
- u_int32_t since = pf_status.since;
- u_int32_t debug = pf_status.debug;
-
- bzero(&pf_status, sizeof(struct pf_status));
- pf_status.running = running;
- pf_status.states = states;
- pf_status.since = since;
- pf_status.debug = debug;
- break;
- }
-
- case DIOCNATLOOK: {
- struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
- struct pf_state *st;
- struct pf_tree_node key;
- int direction = pnl->direction;
-
- key.af = pnl->af;
- key.proto = pnl->proto;
-
- /*
- * userland gives us source and dest of connetion, reverse
- * the lookup so we ask for what happens with the return
- * traffic, enabling us to find it in the state tree.
- */
- PF_ACPY(&key.addr[1], &pnl->saddr, pnl->af);
- key.port[1] = pnl->sport;
- PF_ACPY(&key.addr[0], &pnl->daddr, pnl->af);
- key.port[0] = pnl->dport;
-
- if (!pnl->proto ||
- PF_AZERO(&pnl->saddr, pnl->af) ||
- PF_AZERO(&pnl->daddr, pnl->af) ||
- !pnl->dport || !pnl->sport)
- error = EINVAL;
- else {
- s = splsoftnet();
- if (direction == PF_IN)
- st = pf_find_state(&tree_ext_gwy, &key);
- else
- st = pf_find_state(&tree_lan_ext, &key);
- if (st != NULL) {
- if (direction == PF_IN) {
- PF_ACPY(&pnl->rsaddr, &st->lan.addr,
- st->af);
- pnl->rsport = st->lan.port;
- PF_ACPY(&pnl->rdaddr, &pnl->daddr,
- pnl->af);
- pnl->rdport = pnl->dport;
- } else {
- PF_ACPY(&pnl->rdaddr, &st->gwy.addr,
- st->af);
- pnl->rdport = st->gwy.port;
- PF_ACPY(&pnl->rsaddr, &pnl->saddr,
- pnl->af);
- pnl->rsport = pnl->sport;
- }
- } else
- error = ENOENT;
- splx(s);
- }
- break;
- }
-
- 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 = *pftm_timeouts[pt->timeout];
- *pftm_timeouts[pt->timeout] = pt->seconds;
- pt->seconds = old;
- break;
- }
-
- case DIOCGETTIMEOUT: {
- struct pfioc_tm *pt = (struct pfioc_tm *)addr;
-
- if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
- error = EINVAL;
- goto fail;
- }
- pt->seconds = *pftm_timeouts[pt->timeout];
- break;
- }
-
- case DIOCGETLIMIT: {
- struct pfioc_limit *pl = (struct pfioc_limit *)addr;
-
- if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
- error = EINVAL;
- goto fail;
- }
- pl->limit = pf_pool_limits[pl->index].limit;
- break;
- }
-
- case DIOCSETLIMIT: {
- struct pfioc_limit *pl = (struct pfioc_limit *)addr;
- int old_limit;
-
- if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
- error = EINVAL;
- goto fail;
- }
- if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
- pl->limit, NULL, 0) != 0) {
- error = EBUSY;
- goto fail;
- }
- old_limit = pf_pool_limits[pl->index].limit;
- pf_pool_limits[pl->index].limit = pl->limit;
- pl->limit = old_limit;
- break;
- }
-
- case DIOCSETDEBUG: {
- u_int32_t *level = (u_int32_t *)addr;
- pf_status.debug = *level;
- break;
- }
-
- case DIOCCLRRULECTRS: {
- struct pf_rule *rule;
-
- s = splsoftnet();
- TAILQ_FOREACH(rule, pf_rules_active, entries)
- rule->evaluations = rule->packets =
- rule->bytes = 0;
- splx(s);
- break;
- }
-
- default:
- error = ENODEV;
- break;
- }
-fail:
-
- return (error);
-}
-
#define PF_CALC_SKIP_STEP(i, c) \
do { \
if (a & 1 << i) { \
@@ -5112,13 +3689,9 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir)
* Must be able to put at least 8 bytes per fragment.
*/
if (ip->ip_off & IP_DF) {
+ error = EMSGSIZE;
ipstat.ips_cantfrag++;
- if (r->rt != PF_DUPTO) {
- icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
- ifp);
- goto done;
- } else
- goto bad;
+ goto bad;
}
m1 = m0;
@@ -5221,19 +3794,15 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir)
}
/*
- * If the packet is too large for the outgoing interface,
- * send back an icmp6 error.
+ * Do not fragment packets (yet). Not much is done here for dealing
+ * with errors. Actions on errors depend on whether the packet
+ * was generated locally or being forwarded.
*/
if (m0->m_pkthdr.len <= ifp->if_mtu) {
error = (*ifp->if_output)(ifp, m0, (struct sockaddr *)dst,
NULL);
- } else {
- in6_ifstat_inc(ifp, ifs6_in_toobig);
- if (r->rt != PF_DUPTO)
- icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
- else
- goto bad;
- }
+ } else
+ m_freem(m0);
done:
if (r->rt != PF_DUPTO)
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index db3f4d0158b..0741f8f4ac0 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.80 2002/06/09 04:50:27 deraadt Exp $ */
+/* $OpenBSD: pfvar.h,v 1.81 2002/06/09 08:53:08 pb Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -379,6 +379,12 @@ struct pf_rdr {
u_int8_t no;
};
+struct pf_port_node {
+ LIST_ENTRY(pf_port_node) next;
+ u_int16_t port;
+};
+LIST_HEAD(pf_port_list, pf_port_node);
+
TAILQ_HEAD(pf_rulequeue, pf_rule);
struct pf_pdesc {
@@ -614,7 +620,67 @@ struct pfioc_limit {
#define DIOCSETLIMIT _IOWR('D', 40, struct pfioc_limit)
#define DIOCKILLSTATES _IOWR('D', 41, struct pfioc_state_kill)
+
#ifdef _KERNEL
+RB_HEAD(pf_state_tree, pf_tree_node);
+RB_PROTOTYPE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
+extern struct pf_state_tree tree_lan_ext, tree_ext_gwy;
+
+extern struct pf_rulequeue pf_rules[2];
+TAILQ_HEAD(pf_natqueue, pf_nat);
+extern struct pf_natqueue pf_nats[2];
+TAILQ_HEAD(pf_binatqueue, pf_binat);
+extern struct pf_binatqueue pf_binats[2];
+TAILQ_HEAD(pf_rdrqueue, pf_rdr);
+extern struct pf_rdrqueue pf_rdrs[2];
+
+
+extern u_int32_t ticket_rules_active;
+extern u_int32_t ticket_rules_active;
+extern u_int32_t ticket_rules_inactive;
+extern u_int32_t ticket_nats_active;
+extern u_int32_t ticket_nats_inactive;
+extern u_int32_t ticket_binats_active;
+extern u_int32_t ticket_binats_inactive;
+extern u_int32_t ticket_rdrs_active;
+extern u_int32_t ticket_rdrs_inactive;
+extern u_int32_t ticket_rules_inactive;
+extern struct pf_rulequeue *pf_rules_active;
+extern struct pf_rulequeue *pf_rules_inactive;
+extern struct pf_natqueue *pf_nats_active;
+extern struct pf_natqueue *pf_nats_inactive;
+extern struct pf_binatqueue *pf_binats_active;
+extern struct pf_binatqueue *pf_binats_inactive;
+extern struct pf_rdrqueue *pf_rdrs_active;
+extern struct pf_rdrqueue *pf_rdrs_inactive;
+extern struct pf_port_list pf_tcp_ports;
+extern struct pf_port_list pf_udp_ports;
+extern void pf_dynaddr_remove(struct pf_addr_wrap *);
+extern int pf_dynaddr_setup(struct pf_addr_wrap *,
+ u_int8_t);
+extern void pf_calc_skip_steps(struct pf_rulequeue *);
+extern void pf_dynaddr_copyout(struct pf_addr_wrap *);
+extern struct pool pf_tree_pl, pf_rule_pl, pf_nat_pl, pf_sport_pl;
+extern struct pool pf_rdr_pl, pf_state_pl, pf_binat_pl,
+ pf_addr_pl;
+extern void pf_purge_timeout(void *);
+extern int pftm_interval;
+extern int pf_compare_rules(struct pf_rule *,
+ struct pf_rule *);
+extern int pf_compare_nats(struct pf_nat *,
+ struct pf_nat *);
+extern int pf_compare_binats(struct pf_binat *,
+ struct pf_binat *);
+extern int pf_compare_rdrs(struct pf_rdr *,
+ struct pf_rdr *);
+extern void pf_purge_expired_states(void);
+extern int pf_insert_state(struct pf_state *);
+extern struct pf_state *pf_find_state(struct pf_state_tree *,
+ struct pf_tree_node *);
+extern struct ifnet *status_ifp;
+extern int *pftm_timeouts[PFTM_MAX];
+extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
+ u_int8_t);
#ifdef INET
int pf_test(int, struct ifnet *, struct mbuf **);
@@ -641,6 +707,11 @@ int pf_routable(struct pf_addr *addr, int af);
extern struct pf_rulequeue *pf_rules_active;
extern struct pf_status pf_status;
extern struct pool pf_frent_pl, pf_frag_pl;
+struct pf_pool_limit {
+ void *pp;
+ unsigned limit;
+};
+extern struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];
#endif /* _KERNEL */