summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorCedric Berger <cedric@cvs.openbsd.org>2003-12-31 11:18:26 +0000
committerCedric Berger <cedric@cvs.openbsd.org>2003-12-31 11:18:26 +0000
commitc11ee3b76194fad4678f4b80e323ed57e4ca2377 (patch)
tree3e4326ec5e36e4a40b4657afe67ea5b45b85560f /sys/net
parent8b4556f1666da7ac19e1c546ff8ce02c80ddebc3 (diff)
Many improvements to the handling of interfaces in PF.
1) PF should do the right thing when unplugging/replugging or cloning/ destroying NICs. 2) Rules can be loaded in the kernel for not-yet-existing devices (USB, PCMCIA, Cardbus). For example, it is valid to write: "pass in on kue0" before kue USB is plugged in. 3) It is possible to write rules that apply to group of interfaces (drivers), like "pass in on ppp all" 4) There is a new ":peer" modifier that completes the ":broadcast" and ":network" modifiers. 5) There is a new ":0" modifier that will filter out interface aliases. Can also be applied to DNS names to restore original PF behaviour. 6) The dynamic interface syntax (foo) has been vastly improved, and now support multiple addresses, v4 and v6 addresses, and all userland modifiers, like "pass in from (fxp0:network)" 7) Scrub rules now support the !if syntax. 8) States can be bound to the specific interface that created them or to a group of interfaces for example: - pass all keep state (if-bound) - pass all keep state (group-bound) - pass all keep state (floating) 9) The default value when only keep state is given can be selected by using the "set state-policy" statement. 10) "pfctl -ss" will now print the interface scope of the state. This diff change the pf_state structure slighltly, so you should recompile your userland tools (pfctl, authpf, pflogd, tcpdump...) Tested on i386, sparc, sparc64 by Ryan Tested on macppc, sparc64 by Daniel ok deraadt@ mcbride@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c18
-rw-r--r--sys/net/if_pflog.c8
-rw-r--r--sys/net/if_pfsync.c33
-rw-r--r--sys/net/if_pfsync.h5
-rw-r--r--sys/net/pf.c432
-rw-r--r--sys/net/pf_if.c822
-rw-r--r--sys/net/pf_ioctl.c253
-rw-r--r--sys/net/pf_norm.c32
-rw-r--r--sys/net/pf_table.c153
-rw-r--r--sys/net/pfvar.h211
10 files changed, 1508 insertions, 459 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 1aba9d82eaf..6a4bbdedf65 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.79 2003/12/16 20:33:24 markus Exp $ */
+/* $OpenBSD: if.c,v 1.80 2003/12/31 11:18:25 cedric Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -64,6 +64,7 @@
#include "bpfilter.h"
#include "bridge.h"
#include "carp.h"
+#include "pf.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -110,6 +111,10 @@
#include <netinet/ip_carp.h>
#endif
+#if NPF > 0
+#include <net/pfvar.h>
+#endif
+
void if_attachsetup(struct ifnet *);
void if_attachdomain1(struct ifnet *);
int if_detach_rtdelete(struct radix_node *, void *);
@@ -244,6 +249,9 @@ if_attachsetup(ifp)
if (domains)
if_attachdomain1(ifp);
+#if NPF > 0
+ pfi_attach_ifnet(ifp);
+#endif
}
/*
@@ -434,6 +442,10 @@ if_detach(ifp)
ifp->if_init = if_detached_init;
ifp->if_watchdog = if_detached_watchdog;
+#if NPF > 0
+ pfi_detach_ifnet(ifp);
+#endif
+
#if NBRIDGE > 0
/* Remove the interface from any bridge it is part of. */
if (ifp->if_bridge)
@@ -688,9 +700,11 @@ void
if_clone_attach(ifc)
struct if_clone *ifc;
{
-
LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
if_cloners_count++;
+#if NPF > 0
+ pfi_attach_clone(ifc);
+#endif
}
/*
diff --git a/sys/net/if_pflog.c b/sys/net/if_pflog.c
index 9def6c6371a..3b93226a439 100644
--- a/sys/net/if_pflog.c
+++ b/sys/net/if_pflog.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pflog.c,v 1.10 2003/10/01 21:21:35 canacar Exp $ */
+/* $OpenBSD: if_pflog.c,v 1.11 2003/12/31 11:18:25 cedric Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -172,7 +172,7 @@ pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
int
-pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
+pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
u_int8_t reason, struct pf_rule *rm, struct pf_rule *am,
struct pf_ruleset *ruleset)
{
@@ -181,7 +181,7 @@ pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
struct pfloghdr hdr;
struct mbuf m1;
- if (ifp == NULL || m == NULL || rm == NULL)
+ if (kif == NULL || m == NULL || rm == NULL)
return (-1);
bzero(&hdr, sizeof(hdr));
@@ -189,7 +189,7 @@ pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
hdr.af = af;
hdr.action = rm->action;
hdr.reason = reason;
- memcpy(hdr.ifname, ifp->if_xname, sizeof(hdr.ifname));
+ memcpy(hdr.ifname, kif->pfik_name, sizeof(hdr.ifname));
if (am == NULL) {
hdr.rulenr = htonl(rm->nr);
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c
index 0f00a29c367..89862b8ac50 100644
--- a/sys/net/if_pfsync.c
+++ b/sys/net/if_pfsync.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pfsync.c,v 1.13 2003/12/28 17:18:58 mcbride Exp $ */
+/* $OpenBSD: if_pfsync.c,v 1.14 2003/12/31 11:18:25 cedric Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff
@@ -149,6 +149,7 @@ pfsync_insert_net_state(struct pfsync_state *sp)
{
struct pf_state *st = NULL;
struct pf_rule *r = NULL;
+ struct pfi_kif *kif;
u_long secs;
if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) {
@@ -158,6 +159,15 @@ pfsync_insert_net_state(struct pfsync_state *sp)
return (EINVAL);
}
+ kif = pfi_lookup_create(sp->ifname);
+ if (kif == NULL) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync_insert_net_state: "
+ "unknown interface: %s\n", sp->ifname);
+ /* skip this state */
+ return (0);
+ }
+
/*
* Just use the default rule until we have infrastructure to find the
* best matching rule.
@@ -166,8 +176,10 @@ pfsync_insert_net_state(struct pfsync_state *sp)
if (!r->max_states || r->states < r->max_states)
st = pool_get(&pf_state_pl, PR_NOWAIT);
- if (st == NULL)
+ if (st == NULL) {
+ pfi_maybe_destroy(kif);
return (ENOMEM);
+ }
bzero(st, sizeof(*st));
st->rule.ptr = r;
@@ -201,7 +213,8 @@ pfsync_insert_net_state(struct pfsync_state *sp)
else
st->expire = ntohl(sp->expire) + secs;
- if (pf_insert_state(st)) {
+ if (pf_insert_state(kif, st)) {
+ pfi_maybe_destroy(kif);
pool_put(&pf_state_pl, st);
return (EINVAL);
}
@@ -291,7 +304,7 @@ pfsync_input(struct mbuf *m, ...)
cp = (void *)((char *)mp->m_data + iplen + PFSYNC_HDRLEN);
creatorid = cp->creatorid;
- RB_FOREACH(st, pf_state_tree_ext_gwy, &tree_ext_gwy) {
+ RB_FOREACH(st, pf_state_tree_id, &tree_id) {
if (st->creatorid == creatorid)
st->timeout = PFTM_PURGE;
}
@@ -337,7 +350,7 @@ pfsync_input(struct mbuf *m, ...)
key.id = sp->id;
key.creatorid = sp->creatorid;
- st = pf_find_state(&key, PF_ID);
+ st = pf_find_state_byid(&key);
if (st == NULL) {
/* insert the update */
if (pfsync_insert_net_state(sp))
@@ -368,7 +381,7 @@ pfsync_input(struct mbuf *m, ...)
key.id = sp->id;
key.creatorid = sp->creatorid;
- st = pf_find_state(&key, PF_ID);
+ st = pf_find_state_byid(&key);
if (st == NULL) {
pfsyncstats.pfsyncs_badstate++;
continue;
@@ -399,7 +412,7 @@ pfsync_input(struct mbuf *m, ...)
key.id = up->id;
key.creatorid = up->creatorid;
- st = pf_find_state(&key, PF_ID);
+ st = pf_find_state_byid(&key);
if (st == NULL) {
/* We don't have this state. Ask for it. */
pfsync_request_update(up, &src);
@@ -434,7 +447,7 @@ pfsync_input(struct mbuf *m, ...)
key.id = dp->id;
key.creatorid = dp->creatorid;
- st = pf_find_state(&key, PF_ID);
+ st = pf_find_state_byid(&key);
if (st == NULL) {
pfsyncstats.pfsyncs_badstate++;
continue;
@@ -471,7 +484,7 @@ pfsync_input(struct mbuf *m, ...)
key.id = rup->id;
key.creatorid = rup->creatorid;
- st = pf_find_state(&key, PF_ID);
+ st = pf_find_state_byid(&key);
if (st == NULL) {
pfsyncstats.pfsyncs_badstate++;
continue;
@@ -685,7 +698,6 @@ pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
return (m);
}
-
int
pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
{
@@ -770,6 +782,7 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
sp->id = st->id;
sp->creatorid = st->creatorid;
+ strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname));
pf_state_host_hton(&st->lan, &sp->lan);
pf_state_host_hton(&st->gwy, &sp->gwy);
pf_state_host_hton(&st->ext, &sp->ext);
diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h
index 70d6e1811a0..221cd93f537 100644
--- a/sys/net/if_pfsync.h
+++ b/sys/net/if_pfsync.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pfsync.h,v 1.7 2003/12/28 17:18:58 mcbride Exp $ */
+/* $OpenBSD: if_pfsync.h,v 1.8 2003/12/31 11:18:25 cedric Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -57,6 +57,7 @@ struct pfsync_state_peer {
struct pfsync_state {
u_int64_t id;
+ char ifname[IFNAMSIZ];
struct pfsync_state_host lan;
struct pfsync_state_host gwy;
struct pfsync_state_host ext;
@@ -143,7 +144,7 @@ struct pfsync_softc {
struct pfsync_header {
u_int8_t version;
-#define PFSYNC_VERSION 1
+#define PFSYNC_VERSION 2
u_int8_t af;
u_int8_t action;
#define PFSYNC_ACT_CLR 0 /* clear all states */
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 0b74b93a371..a74f21ecd73 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.413 2003/12/19 16:12:43 henning Exp $ */
+/* $OpenBSD: pf.c,v 1.414 2003/12/31 11:18:25 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -99,7 +99,6 @@ struct pf_palist pf_pabuf;
struct pf_altqqueue *pf_altqs_active;
struct pf_altqqueue *pf_altqs_inactive;
struct pf_status pf_status;
-struct ifnet *status_ifp;
u_int32_t ticket_altqs_active;
u_int32_t ticket_altqs_inactive;
@@ -108,7 +107,7 @@ u_int32_t ticket_pabuf;
struct timeout pf_expire_to; /* expire timeout */
-struct pool pf_src_tree_pl, pf_rule_pl, pf_addr_pl;
+struct pool pf_src_tree_pl, pf_rule_pl;
struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
@@ -135,45 +134,45 @@ void pf_send_tcp(const struct pf_rule *, sa_family_t,
void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
sa_family_t, struct pf_rule *);
struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
- int, int, struct ifnet *,
+ int, int, struct pfi_kif *,
struct pf_addr *, u_int16_t, struct pf_addr *,
u_int16_t, int);
struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *,
- int, int, struct ifnet *, struct pf_src_node **,
+ int, int, struct pfi_kif *, struct pf_src_node **,
struct pf_addr *, u_int16_t,
struct pf_addr *, u_int16_t,
struct pf_addr *, u_int16_t *);
int pf_test_tcp(struct pf_rule **, struct pf_state **,
- int, struct ifnet *, struct mbuf *, int,
+ int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_udp(struct pf_rule **, struct pf_state **,
- int, struct ifnet *, struct mbuf *, int,
+ int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_icmp(struct pf_rule **, struct pf_state **,
- int, struct ifnet *, struct mbuf *, int,
+ int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_other(struct pf_rule **, struct pf_state **,
- int, struct ifnet *, struct mbuf *, int, void *,
+ int, struct pfi_kif *, struct mbuf *, int, void *,
struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_fragment(struct pf_rule **, int,
- struct ifnet *, struct mbuf *, void *,
+ struct pfi_kif *, struct mbuf *, void *,
struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_state_tcp(struct pf_state **, int,
- struct ifnet *, struct mbuf *, int,
+ struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, u_short *);
int pf_test_state_udp(struct pf_state **, int,
- struct ifnet *, struct mbuf *, int,
+ struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *);
int pf_test_state_icmp(struct pf_state **, int,
- struct ifnet *, struct mbuf *, int,
+ struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *);
int pf_test_state_other(struct pf_state **, int,
- struct ifnet *, struct pf_pdesc *);
+ struct pfi_kif *, struct pf_pdesc *);
struct pf_tag *pf_get_tag(struct mbuf *);
int pf_match_tag(struct mbuf *, struct pf_rule *,
struct pf_rule *, struct pf_tag *, int *);
@@ -205,7 +204,8 @@ int pf_check_proto_cksum(struct mbuf *, int, int,
int pf_addr_wrap_neq(struct pf_addr_wrap *,
struct pf_addr_wrap *);
static int pf_add_mbuf_tag(struct mbuf *, u_int);
-
+struct pf_state *pf_find_state_recurse(struct pfi_kif *,
+ struct pf_state *, u_int8_t);
struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
{ { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
@@ -213,9 +213,11 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
#define STATE_LOOKUP() \
do { \
if (direction == PF_IN) \
- *state = pf_find_state(&key, PF_EXT_GWY); \
+ *state = pf_find_state_recurse( \
+ kif, &key, PF_EXT_GWY); \
else \
- *state = pf_find_state(&key, PF_LAN_EXT); \
+ *state = pf_find_state_recurse( \
+ kif, &key, PF_LAN_EXT); \
if (*state == NULL) \
return (PF_DROP); \
if (direction == PF_OUT && \
@@ -223,8 +225,8 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
(*state)->rule.ptr->direction == PF_OUT) || \
((*state)->rule.ptr->rt == PF_REPLYTO && \
(*state)->rule.ptr->direction == PF_IN)) && \
- (*state)->rt_ifp != NULL && \
- (*state)->rt_ifp != ifp) \
+ (*state)->rt_kif != NULL && \
+ (*state)->rt_kif != kif) \
return (PF_PASS); \
} while (0)
@@ -236,6 +238,10 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
(s)->lan.addr.addr32[3] != (s)->gwy.addr.addr32[3])) || \
(s)->lan.port != (s)->gwy.port
+#define LOCKED_IF(r, k) (((r)->rule_flag & PFRULE_IFBOUND) ? (k) : \
+ ((r)->rule_flag & PFRULE_GRBOUND) ? (k)->pfik_parent : \
+ (k)->pfik_parent->pfik_parent)
+
static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
static __inline int pf_state_compare_lan_ext(struct pf_state *,
struct pf_state *);
@@ -245,17 +251,16 @@ static __inline int pf_state_compare_id(struct pf_state *,
struct pf_state *);
struct pf_src_tree tree_src_tracking;
-struct pf_state_tree_lan_ext tree_lan_ext;
-struct pf_state_tree_ext_gwy tree_ext_gwy;
+
struct pf_state_tree_id tree_id;
RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare);
RB_GENERATE(pf_state_tree_lan_ext, pf_state,
- entry_lan_ext, pf_state_compare_lan_ext);
+ u.s.entry_lan_ext, pf_state_compare_lan_ext);
RB_GENERATE(pf_state_tree_ext_gwy, pf_state,
- entry_ext_gwy, pf_state_compare_ext_gwy);
+ u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
RB_GENERATE(pf_state_tree_id, pf_state,
- entry_id, pf_state_compare_id);
+ u.s.entry_id, pf_state_compare_id);
static __inline int
pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
@@ -473,29 +478,77 @@ pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
#endif
struct pf_state *
-pf_find_state(struct pf_state *key, u_int8_t tree)
+pf_find_state_byid(struct pf_state *key)
+{
+ pf_status.fcounters[FCNT_STATE_SEARCH]++;
+ return RB_FIND(pf_state_tree_id, &tree_id, key);
+}
+
+struct pf_state *
+pf_find_state_recurse(struct pfi_kif *kif, struct pf_state *key, u_int8_t tree)
{
- struct pf_state *s;
+ struct pf_state *s;
pf_status.fcounters[FCNT_STATE_SEARCH]++;
switch (tree) {
case PF_LAN_EXT:
- s = RB_FIND(pf_state_tree_lan_ext, &tree_lan_ext, key);
- break;
+ for (; kif != NULL; kif = kif->pfik_parent) {
+ s = RB_FIND(pf_state_tree_lan_ext,
+ &kif->pfik_lan_ext, key);
+ if (s != NULL)
+ return (s);
+ }
+ return (NULL);
case PF_EXT_GWY:
- s = RB_FIND(pf_state_tree_ext_gwy, &tree_ext_gwy, key);
- break;
- case PF_ID:
- s = RB_FIND(pf_state_tree_id, &tree_id, key);
- break;
+ for (; kif != NULL; kif = kif->pfik_parent) {
+ s = RB_FIND(pf_state_tree_ext_gwy,
+ &kif->pfik_ext_gwy, key);
+ if (s != NULL)
+ return (s);
+ }
+ return (NULL);
default:
- /* XXX should we just return NULL? */
- panic("pf_find_state");
- break;
+ panic("pf_find_state_recurse");
}
+}
+
+struct pf_state *
+pf_find_state_all(struct pf_state *key, u_int8_t tree, int *more)
+{
+ struct pf_state *s, *ss = NULL;
+ struct pfi_kif *kif;
- return (s);
+ pf_status.fcounters[FCNT_STATE_SEARCH]++;
+
+ switch(tree) {
+ case PF_LAN_EXT:
+ TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
+ s = RB_FIND(pf_state_tree_lan_ext,
+ &kif->pfik_lan_ext, key);
+ if (s == NULL)
+ continue;
+ if (more == NULL)
+ return (s);
+ ss = s;
+ (*more)++;
+ }
+ return (ss);
+ case PF_EXT_GWY:
+ TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
+ s = RB_FIND(pf_state_tree_ext_gwy,
+ &kif->pfik_ext_gwy, key);
+ if (s == NULL)
+ continue;
+ if (more == NULL)
+ return (s);
+ ss = s;
+ (*more)++;
+ }
+ return (ss);
+ default:
+ panic("pf_find_state_all");
+ }
}
int
@@ -554,10 +607,11 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
}
int
-pf_insert_state(struct pf_state *state)
+pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
{
/* Thou MUST NOT insert multiple duplicate keys */
- if (RB_INSERT(pf_state_tree_lan_ext, &tree_lan_ext, state)) {
+ state->u.s.kif = kif;
+ if (RB_INSERT(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state)) {
if (pf_status.debug >= PF_DEBUG_MISC) {
printf("pf: state insert failed: tree_lan_ext");
printf(" lan: ");
@@ -577,7 +631,7 @@ pf_insert_state(struct pf_state *state)
return (-1);
}
- if (RB_INSERT(pf_state_tree_ext_gwy, &tree_ext_gwy, state) != NULL) {
+ if (RB_INSERT(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state)) {
if (pf_status.debug >= PF_DEBUG_MISC) {
printf("pf: state insert failed: tree_ext_gwy");
printf(" lan: ");
@@ -593,7 +647,7 @@ pf_insert_state(struct pf_state *state)
printf(" (from sync)");
printf("\n");
}
- RB_REMOVE(pf_state_tree_lan_ext, &tree_lan_ext, state);
+ RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
pf_src_tree_remove_state(state);
return (-1);
}
@@ -611,13 +665,14 @@ pf_insert_state(struct pf_state *state)
printf(" (from sync)");
printf("\n");
}
- RB_REMOVE(pf_state_tree_lan_ext, &tree_lan_ext, state);
- RB_REMOVE(pf_state_tree_ext_gwy, &tree_ext_gwy, state);
+ RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
+ RB_REMOVE(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state);
return (-1);
}
pf_status.fcounters[FCNT_STATE_INSERT]++;
pf_status.states++;
+ pfi_attach_state(kif);
#if NPFSYNC
pfsync_insert_state(state);
#endif
@@ -726,8 +781,9 @@ pf_purge_expired_states(void)
{
struct pf_state *cur, *next;
- for (cur = RB_MIN(pf_state_tree_ext_gwy, &tree_ext_gwy); cur; cur = next) {
- next = RB_NEXT(pf_state_tree_ext_gwy, &tree_ext_gwy, cur);
+ for (cur = RB_MIN(pf_state_tree_id, &tree_id);
+ cur; cur = next) {
+ next = RB_NEXT(pf_state_tree_id, &tree_id, cur);
if (pf_state_expires(cur) <= time.tv_sec) {
if (cur->src.state == PF_TCPS_PROXY_DST)
@@ -736,10 +792,11 @@ pf_purge_expired_states(void)
cur->ext.port, cur->lan.port,
cur->src.seqhi, cur->src.seqlo + 1, 0,
TH_RST|TH_ACK, 0, 0);
- RB_REMOVE(pf_state_tree_ext_gwy, &tree_ext_gwy, cur);
- RB_REMOVE(pf_state_tree_lan_ext, &tree_lan_ext, cur);
+ RB_REMOVE(pf_state_tree_ext_gwy,
+ &cur->u.s.kif->pfik_ext_gwy, cur);
+ RB_REMOVE(pf_state_tree_lan_ext,
+ &cur->u.s.kif->pfik_lan_ext, cur);
RB_REMOVE(pf_state_tree_id, &tree_id, cur);
-
#if NPFSYNC
pfsync_delete_state(cur);
#endif
@@ -755,6 +812,7 @@ pf_purge_expired_states(void)
if (--cur->anchor.ptr->states <= 0)
pf_rm_rule(NULL, cur->anchor.ptr);
pf_normalize_tcp_cleanup(cur);
+ pfi_detach_state(cur->u.s.kif);
pool_put(&pf_state_pl, cur);
pf_status.fcounters[FCNT_STATE_REMOVALS]++;
pf_status.states--;
@@ -940,7 +998,7 @@ pf_calc_skip_steps(struct pf_rulequeue *rules)
head[i] = cur;
while (cur != NULL) {
- if (cur->ifp != prev->ifp || cur->ifnot != prev->ifnot)
+ if (cur->kif != prev->kif || cur->ifnot != prev->ifnot)
PF_SET_SKIP_STEPS(PF_SKIP_IFP);
if (cur->direction != prev->direction)
PF_SET_SKIP_STEPS(PF_SKIP_DIR);
@@ -983,11 +1041,7 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
return (1);
return (0);
case PF_ADDR_DYNIFTL:
- if (aw1->p.dyn->ifp != aw2->p.dyn->ifp)
- return (1);
- if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0))
- return (1);
- return (0);
+ return (aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt);
case PF_ADDR_NOROUTE:
return (0);
case PF_ADDR_TABLE:
@@ -1739,10 +1793,23 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
if (rpool->cur->addr.type == PF_ADDR_NOROUTE)
return (1);
- if (rpool->cur->addr.type == PF_ADDR_DYNIFTL &&
- rpool->cur->addr.p.dyn->undefined)
- return (1);
- if (rpool->cur->addr.type == PF_ADDR_TABLE) {
+ if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
+ if (af == AF_INET) {
+ if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
+ (rpool->opts & PF_POOL_TYPEMASK) !=
+ PF_POOL_ROUNDROBIN)
+ return (1);
+ raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
+ rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
+ } else {
+ if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
+ (rpool->opts & PF_POOL_TYPEMASK) !=
+ PF_POOL_ROUNDROBIN)
+ return (1);
+ raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
+ rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
+ }
+ } else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)
return (1); /* unsupported */
} else {
@@ -1802,6 +1869,11 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
&rpool->tblidx, &rpool->counter,
&raddr, &rmask, af))
goto get_addr;
+ } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
+ if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
+ &rpool->tblidx, &rpool->counter,
+ &raddr, &rmask, af))
+ goto get_addr;
} else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
goto get_addr;
@@ -1818,6 +1890,16 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
goto try_next;
return (1);
}
+ } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
+ rpool->tblidx = -1;
+ if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
+ &rpool->tblidx, &rpool->counter,
+ &raddr, &rmask, af)) {
+ /* table contain no address of type 'af' */
+ if (rpool->cur != acur)
+ goto try_next;
+ return (1);
+ }
} else {
raddr = &rpool->cur->addr.v.a.addr;
rmask = &rpool->cur->addr.v.a.mask;
@@ -1869,16 +1951,15 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
*/
if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP)) {
key.gwy.port = 0;
- if (pf_find_state(&key, PF_EXT_GWY) == NULL)
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
return (0);
} else if (low == 0 && high == 0) {
key.gwy.port = *nport;
- if (pf_find_state(&key, PF_EXT_GWY) == NULL) {
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
return (0);
- }
} else if (low == high) {
key.gwy.port = htons(low);
- if (pf_find_state(&key, PF_EXT_GWY) == NULL) {
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) {
*nport = htons(low);
return (0);
}
@@ -1895,7 +1976,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
/* low <= cut <= high */
for (tmp = cut; tmp <= high; ++(tmp)) {
key.gwy.port = htons(tmp);
- if (pf_find_state(&key, PF_EXT_GWY) ==
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
NULL) {
*nport = htons(tmp);
return (0);
@@ -1903,7 +1984,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
}
for (tmp = cut - 1; tmp >= low; --(tmp)) {
key.gwy.port = htons(tmp);
- if (pf_find_state(&key, PF_EXT_GWY) ==
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
NULL) {
*nport = htons(tmp);
return (0);
@@ -1931,7 +2012,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
struct pf_rule *
pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
- int direction, struct ifnet *ifp, struct pf_addr *saddr, u_int16_t sport,
+ int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
struct pf_addr *daddr, u_int16_t dport, int rs_num)
{
struct pf_rule *r, *rm = NULL, *anchorrule = NULL;
@@ -1952,8 +2033,8 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
}
r->evaluations++;
- if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
- (r->ifp == ifp && r->ifnot)))
+ if (r->kif != NULL &&
+ (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -1999,7 +2080,7 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
struct pf_rule *
pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
- struct ifnet *ifp, struct pf_src_node **sn,
+ struct pfi_kif *kif, struct pf_src_node **sn,
struct pf_addr *saddr, u_int16_t sport,
struct pf_addr *daddr, u_int16_t dport,
struct pf_addr *naddr, u_int16_t *nport)
@@ -2007,16 +2088,16 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
struct pf_rule *r = NULL;
if (direction == PF_OUT) {
- r = pf_match_translation(pd, m, off, direction, ifp, saddr,
+ r = pf_match_translation(pd, m, off, direction, kif, saddr,
sport, daddr, dport, PF_RULESET_BINAT);
if (r == NULL)
- r = pf_match_translation(pd, m, off, direction, ifp,
+ r = pf_match_translation(pd, m, off, direction, kif,
saddr, sport, daddr, dport, PF_RULESET_NAT);
} else {
- r = pf_match_translation(pd, m, off, direction, ifp, saddr,
+ r = pf_match_translation(pd, m, off, direction, kif, saddr,
sport, daddr, dport, PF_RULESET_RDR);
if (r == NULL)
- r = pf_match_translation(pd, m, off, direction, ifp,
+ r = pf_match_translation(pd, m, off, direction, kif,
saddr, sport, daddr, dport, PF_RULESET_BINAT);
}
@@ -2042,21 +2123,58 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
case PF_BINAT:
switch (direction) {
case PF_OUT:
- if (r->rpool.cur->addr.type ==
- PF_ADDR_DYNIFTL &&
- r->rpool.cur->addr.p.dyn->undefined)
- return (NULL);
- else
+ if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
+ if (pd->af == AF_INET) {
+ if (r->rpool.cur->addr.p.dyn->
+ pfid_acnt4 < 1)
+ return (NULL);
+ PF_POOLMASK(naddr,
+ &r->rpool.cur->addr.p.dyn->
+ pfid_addr4,
+ &r->rpool.cur->addr.p.dyn->
+ pfid_mask4,
+ saddr, AF_INET);
+ } else {
+ if (r->rpool.cur->addr.p.dyn->
+ pfid_acnt6 < 1)
+ return (NULL);
+ PF_POOLMASK(naddr,
+ &r->rpool.cur->addr.p.dyn->
+ pfid_addr6,
+ &r->rpool.cur->addr.p.dyn->
+ pfid_mask6,
+ saddr, AF_INET6);
+ }
+ } else
PF_POOLMASK(naddr,
&r->rpool.cur->addr.v.a.addr,
&r->rpool.cur->addr.v.a.mask,
saddr, pd->af);
break;
case PF_IN:
- if (r->src.addr.type == PF_ADDR_DYNIFTL &&
- r->src.addr.p.dyn->undefined)
- return (NULL);
- else
+ if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
+ if (pd->af == AF_INET) {
+ if (r->src.addr.p.dyn->
+ pfid_acnt4 < 1)
+ return (NULL);
+ PF_POOLMASK(naddr,
+ &r->src.addr.p.dyn->
+ pfid_addr4,
+ &r->src.addr.p.dyn->
+ pfid_mask4,
+ daddr, AF_INET);
+ } else {
+ if (r->src.addr.p.dyn->
+ pfid_acnt6 < 1)
+ return (NULL);
+ PF_POOLMASK(naddr,
+ &r->src.addr.p.dyn->
+ pfid_addr6,
+ &r->src.addr.p.dyn->
+ pfid_mask6,
+ daddr, AF_INET6);
+ }
+ } else
PF_POOLMASK(naddr,
&r->src.addr.v.a.addr,
&r->src.addr.v.a.mask, daddr,
@@ -2291,20 +2409,20 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
{
struct pf_rule *r = s->rule.ptr;
- s->rt_ifp = NULL;
+ s->rt_kif = NULL;
if (!r->rt || r->rt == PF_FASTROUTE)
return;
switch (s->af) {
#ifdef INET
case AF_INET:
pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, &s->nat_src_node);
- s->rt_ifp = r->rpool.cur->ifp;
+ s->rt_kif = r->rpool.cur->kif;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, &s->nat_src_node);
- s->rt_ifp = r->rpool.cur->ifp;
+ s->rt_kif = r->rpool.cur->kif;
break;
#endif /* INET6 */
}
@@ -2312,7 +2430,7 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
int
pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
- struct ifnet *ifp, struct mbuf *m, int off, void *h,
+ struct pfi_kif *kif, struct mbuf *m, int off, void *h,
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
{
struct pf_rule *nr = NULL;
@@ -2337,7 +2455,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (direction == PF_OUT) {
bport = nport = th->th_sport;
/* check outgoing packet for BINAT/NAT */
- if ((nr = pf_get_translation(pd, m, off, PF_OUT, ifp, &nsn,
+ if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
saddr, th->th_sport, daddr, th->th_dport,
&pd->naddr, &nport)) != NULL) {
PF_ACPY(&pd->baddr, saddr, af);
@@ -2351,7 +2469,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
} else {
bport = nport = th->th_dport;
/* check incoming packet for BINAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, PF_IN, ifp, &nsn,
+ if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
saddr, th->th_sport, daddr, th->th_dport,
&pd->naddr, &nport)) != NULL) {
PF_ACPY(&pd->baddr, daddr, af);
@@ -2366,8 +2484,8 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
while (r != NULL) {
r->evaluations++;
- if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
- (r->ifp == ifp && r->ifnot)))
+ if (r->kif != NULL &&
+ (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -2435,7 +2553,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (r->log) {
if (rewrite)
m_copyback(m, off, sizeof(*th), th);
- PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
}
if ((r->action == PF_DROP) &&
@@ -2623,7 +2741,7 @@ cleanup:
pool_put(&pf_state_pl, s);
return (PF_DROP);
}
- if (pf_insert_state(s)) {
+ if (pf_insert_state(LOCKED_IF(r, kif), s)) {
pf_normalize_tcp_cleanup(s);
REASON_SET(&reason, PFRES_MEMORY);
pf_src_tree_remove_state(s);
@@ -2667,7 +2785,7 @@ cleanup:
int
pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
- struct ifnet *ifp, struct mbuf *m, int off, void *h,
+ struct pfi_kif *kif, struct mbuf *m, int off, void *h,
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
{
struct pf_rule *nr = NULL;
@@ -2691,7 +2809,7 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (direction == PF_OUT) {
bport = nport = uh->uh_sport;
/* check outgoing packet for BINAT/NAT */
- if ((nr = pf_get_translation(pd, m, off, PF_OUT, ifp, &nsn,
+ if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
saddr, uh->uh_sport, daddr, uh->uh_dport,
&pd->naddr, &nport)) != NULL) {
PF_ACPY(&pd->baddr, saddr, af);
@@ -2705,7 +2823,7 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
} else {
bport = nport = uh->uh_dport;
/* check incoming packet for BINAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, PF_IN, ifp, &nsn,
+ if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
saddr, uh->uh_sport, daddr, uh->uh_dport, &pd->naddr,
&nport)) != NULL) {
PF_ACPY(&pd->baddr, daddr, af);
@@ -2720,8 +2838,8 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
while (r != NULL) {
r->evaluations++;
- if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
- (r->ifp == ifp && r->ifnot)))
+ if (r->kif != NULL &&
+ (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -2786,7 +2904,7 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (r->log) {
if (rewrite)
m_copyback(m, off, sizeof(*uh), uh);
- PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
}
if ((r->action == PF_DROP) &&
@@ -2912,7 +3030,7 @@ cleanup:
s->nat_src_node = nsn;
s->nat_src_node->states++;
}
- if (pf_insert_state(s)) {
+ if (pf_insert_state(LOCKED_IF(r, kif), s)) {
REASON_SET(&reason, PFRES_MEMORY);
pf_src_tree_remove_state(s);
pool_put(&pf_state_pl, s);
@@ -2930,7 +3048,7 @@ cleanup:
int
pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
- struct ifnet *ifp, struct mbuf *m, int off, void *h,
+ struct pfi_kif *kif, struct mbuf *m, int off, void *h,
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
{
struct pf_rule *nr = NULL;
@@ -2983,7 +3101,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (direction == PF_OUT) {
/* check outgoing packet for BINAT/NAT */
- if ((nr = pf_get_translation(pd, m, off, PF_OUT, ifp, &nsn,
+ if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
PF_ACPY(&pd->baddr, saddr, af);
switch (af) {
@@ -3007,7 +3125,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
}
} else {
/* check incoming packet for BINAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, PF_IN, ifp, &nsn,
+ if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
PF_ACPY(&pd->baddr, daddr, af);
switch (af) {
@@ -3033,8 +3151,8 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
while (r != NULL) {
r->evaluations++;
- if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
- (r->ifp == ifp && r->ifnot)))
+ if (r->kif != NULL &&
+ (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -3090,7 +3208,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
m_copyback(m, off, sizeof(struct icmp6_hdr),
pd->hdr.icmp6);
#endif /* INET6 */
- PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
}
if (r->action != PF_PASS)
@@ -3187,7 +3305,7 @@ cleanup:
s->nat_src_node = nsn;
s->nat_src_node->states++;
}
- if (pf_insert_state(s)) {
+ if (pf_insert_state(LOCKED_IF(r, kif), s)) {
REASON_SET(&reason, PFRES_MEMORY);
pf_src_tree_remove_state(s);
pool_put(&pf_state_pl, s);
@@ -3208,7 +3326,7 @@ cleanup:
int
pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
- struct ifnet *ifp, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
+ struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
struct pf_rule **am, struct pf_ruleset **rsm)
{
struct pf_rule *nr = NULL;
@@ -3225,7 +3343,7 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
if (direction == PF_OUT) {
/* check outgoing packet for BINAT/NAT */
- if ((nr = pf_get_translation(pd, m, off, PF_OUT, ifp, &nsn,
+ if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
PF_ACPY(&pd->baddr, saddr, af);
switch (af) {
@@ -3247,7 +3365,7 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
}
} else {
/* check incoming packet for BINAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, PF_IN, ifp, &nsn,
+ if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
PF_ACPY(&pd->baddr, daddr, af);
switch (af) {
@@ -3271,8 +3389,8 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
while (r != NULL) {
r->evaluations++;
- if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
- (r->ifp == ifp && r->ifnot)))
+ if (r->kif != NULL &&
+ (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -3319,7 +3437,7 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
REASON_SET(&reason, PFRES_MATCH);
if (r->log)
- PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
if ((r->action == PF_DROP) &&
((r->rule_flag & PFRULE_RETURNICMP) ||
@@ -3445,10 +3563,10 @@ cleanup:
s->nat_src_node = nsn;
s->nat_src_node->states++;
}
- if (pf_insert_state(s)) {
+ if (pf_insert_state(LOCKED_IF(r, kif), s)) {
REASON_SET(&reason, PFRES_MEMORY);
if (r->log)
- PFLOG_PACKET(ifp, h, m, af, direction, reason,
+ PFLOG_PACKET(kif, h, m, af, direction, reason,
r, a, ruleset);
pf_src_tree_remove_state(s);
pool_put(&pf_state_pl, s);
@@ -3461,7 +3579,7 @@ cleanup:
}
int
-pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
+pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am,
struct pf_ruleset **rsm)
{
@@ -3475,8 +3593,8 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
- (r->ifp == ifp && r->ifnot)))
+ if (r->kif != NULL &&
+ (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -3521,7 +3639,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
REASON_SET(&reason, PFRES_MATCH);
if (r->log)
- PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
if (r->action != PF_PASS)
return (PF_DROP);
@@ -3535,7 +3653,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
}
int
-pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp,
+pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
u_short *reason)
{
@@ -3943,7 +4061,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp,
}
int
-pf_test_state_udp(struct pf_state **state, int direction, struct ifnet *ifp,
+pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
{
struct pf_state_peer *src, *dst;
@@ -4004,7 +4122,7 @@ pf_test_state_udp(struct pf_state **state, int direction, struct ifnet *ifp,
}
int
-pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
+pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
{
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
@@ -4561,7 +4679,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
}
int
-pf_test_state_other(struct pf_state **state, int direction, struct ifnet *ifp,
+pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
struct pf_pdesc *pd)
{
struct pf_state_peer *src, *dst;
@@ -4782,12 +4900,13 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
&naddr, NULL, &sn);
if (!PF_AZERO(&naddr, AF_INET))
dst->sin_addr.s_addr = naddr.v4.s_addr;
- ifp = r->rpool.cur->ifp;
+ ifp = r->rpool.cur->kif ?
+ r->rpool.cur->kif->pfik_ifp : NULL;
} else {
if (!PF_AZERO(&s->rt_addr, AF_INET))
dst->sin_addr.s_addr =
s->rt_addr.v4.s_addr;
- ifp = s->rt_ifp;
+ ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
}
}
@@ -4973,12 +5092,12 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (!PF_AZERO(&naddr, AF_INET6))
PF_ACPY((struct pf_addr *)&dst->sin6_addr,
&naddr, AF_INET6);
- ifp = r->rpool.cur->ifp;
+ ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
} else {
if (!PF_AZERO(&s->rt_addr, AF_INET6))
PF_ACPY((struct pf_addr *)&dst->sin6_addr,
&s->rt_addr, AF_INET6);
- ifp = s->rt_ifp;
+ ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
}
if (ifp == NULL)
@@ -5132,6 +5251,7 @@ pf_add_mbuf_tag(struct mbuf *m, u_int tag)
int
pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
{
+ struct pfi_kif *kif = pfi_index2kif[ifp->if_index];
u_short action, reason = 0, log = 0;
struct mbuf *m = *m0;
struct ip *h;
@@ -5159,7 +5279,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
}
/* We do IP header normalization and packet reassembly here */
- if (pf_normalize_ip(m0, dir, ifp, &reason) != PF_PASS) {
+ if (pf_normalize_ip(m0, dir, kif, &reason) != PF_PASS) {
action = PF_DROP;
goto done;
}
@@ -5185,7 +5305,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
/* handle fragments that didn't get reassembled by normalization */
if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
- action = pf_test_fragment(&r, dir, ifp, m, h,
+ action = pf_test_fragment(&r, dir, kif, m, h,
&pd, &a, &ruleset);
goto done;
}
@@ -5209,10 +5329,10 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
pd.p_len = pd.tot_len - off - (th.th_off << 2);
if ((th.th_flags & TH_ACK) && pd.p_len == 0)
pqid = 1;
- action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd);
+ action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
if (action == PF_DROP)
goto done;
- action = pf_test_state_tcp(&s, dir, ifp, m, off, h, &pd,
+ action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
&reason);
if (action == PF_PASS) {
#if NPFSYNC
@@ -5222,7 +5342,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_tcp(&r, &s, dir, ifp,
+ action = pf_test_tcp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
break;
}
@@ -5241,7 +5361,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
action = PF_DROP;
goto done;
}
- action = pf_test_state_udp(&s, dir, ifp, m, off, h, &pd);
+ action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
if (action == PF_PASS) {
#if NPFSYNC
pfsync_update_state(s);
@@ -5250,7 +5370,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_udp(&r, &s, dir, ifp,
+ action = pf_test_udp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
break;
}
@@ -5269,23 +5389,22 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
action = PF_DROP;
goto done;
}
- action = pf_test_state_icmp(&s, dir, ifp, m, off, h, &pd);
+ action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd);
if (action == PF_PASS) {
#if NPFSYNC
pfsync_update_state(s);
#endif
-
r = s->rule.ptr;
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_icmp(&r, &s, dir, ifp,
+ action = pf_test_icmp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
break;
}
default:
- action = pf_test_state_other(&s, dir, ifp, &pd);
+ action = pf_test_state_other(&s, dir, kif, &pd);
if (action == PF_PASS) {
#if NPFSYNC
pfsync_update_state(s);
@@ -5294,7 +5413,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_other(&r, &s, dir, ifp, m, off, h,
+ action = pf_test_other(&r, &s, dir, kif, m, off, h,
&pd, &a, &ruleset);
break;
}
@@ -5345,12 +5464,10 @@ done:
}
if (log)
- PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, a, ruleset);
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, a, ruleset);
- if (ifp == status_ifp) {
- pf_status.bcounters[0][dir == PF_OUT] += pd.tot_len;
- pf_status.pcounters[0][dir == PF_OUT][action != PF_PASS]++;
- }
+ kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
+ kif->pfik_packets[0][dir == PF_OUT][action != PF_PASS]++;
if (action == PF_PASS || r->action == PF_DROP) {
r->packets++;
@@ -5429,6 +5546,7 @@ done:
int
pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
{
+ struct pfi_kif *kif = pfi_index2kif[ifp->if_index];
u_short action, reason = 0, log = 0;
struct mbuf *m = *m0;
struct ip6_hdr *h;
@@ -5456,7 +5574,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
}
/* We do IP header normalization and packet reassembly here */
- if (pf_normalize_ip6(m0, dir, ifp, &reason) != PF_PASS) {
+ if (pf_normalize_ip6(m0, dir, kif, &reason) != PF_PASS) {
action = PF_DROP;
goto done;
}
@@ -5476,7 +5594,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
do {
switch (pd.proto) {
case IPPROTO_FRAGMENT:
- action = pf_test_fragment(&r, dir, ifp, m, h,
+ action = pf_test_fragment(&r, dir, kif, m, h,
&pd, &a, &ruleset);
if (action == PF_DROP)
REASON_SET(&reason, PFRES_FRAG);
@@ -5528,10 +5646,10 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
goto done;
}
pd.p_len = pd.tot_len - off - (th.th_off << 2);
- action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd);
+ action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
if (action == PF_DROP)
goto done;
- action = pf_test_state_tcp(&s, dir, ifp, m, off, h, &pd,
+ action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
&reason);
if (action == PF_PASS) {
#if NPFSYNC
@@ -5541,7 +5659,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_tcp(&r, &s, dir, ifp,
+ action = pf_test_tcp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
break;
}
@@ -5560,7 +5678,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
action = PF_DROP;
goto done;
}
- action = pf_test_state_udp(&s, dir, ifp, m, off, h, &pd);
+ action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
if (action == PF_PASS) {
#if NPFSYNC
pfsync_update_state(s);
@@ -5569,7 +5687,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_udp(&r, &s, dir, ifp,
+ action = pf_test_udp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
break;
}
@@ -5588,7 +5706,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
action = PF_DROP;
goto done;
}
- action = pf_test_state_icmp(&s, dir, ifp,
+ action = pf_test_state_icmp(&s, dir, kif,
m, off, h, &pd);
if (action == PF_PASS) {
#if NPFSYNC
@@ -5598,19 +5716,19 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_icmp(&r, &s, dir, ifp,
+ action = pf_test_icmp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
break;
}
default:
- action = pf_test_state_other(&s, dir, ifp, &pd);
+ action = pf_test_state_other(&s, dir, kif, &pd);
if (action == PF_PASS) {
r = s->rule.ptr;
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_other(&r, &s, dir, ifp, m, off, h,
+ action = pf_test_other(&r, &s, dir, kif, m, off, h,
&pd, &a, &ruleset);
break;
}
@@ -5649,12 +5767,10 @@ done:
}
if (log)
- PFLOG_PACKET(ifp, h, m, AF_INET6, dir, reason, r, a, ruleset);
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, reason, r, a, ruleset);
- if (ifp == status_ifp) {
- pf_status.bcounters[1][dir == PF_OUT] += pd.tot_len;
- pf_status.pcounters[1][dir == PF_OUT][action != PF_PASS]++;
- }
+ kif->pfik_bytes[1][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
+ kif->pfik_packets[1][dir == PF_OUT][action != PF_PASS]++;
if (action == PF_PASS || r->action == PF_DROP) {
r->packets++;
diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c
index 21574183104..485511bc182 100644
--- a/sys/net/pf_if.c
+++ b/sys/net/pf_if.c
@@ -1,7 +1,8 @@
-/* $OpenBSD: pf_if.c,v 1.1 2003/12/12 20:05:45 cedric Exp $ */
+/* $OpenBSD: pf_if.c,v 1.2 2003/12/31 11:18:25 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
+ * Copyright (c) 2003 Cedric Berger
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,11 +28,6 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
- *
- * Effort sponsored in part by the Defense Advanced Research Projects
- * Agency (DARPA) and Air Force Research Laboratory, Air Force
- * Materiel Command, USAF, under agreement number F30602-01-2-0537.
- *
*/
#include <sys/param.h>
@@ -41,8 +37,8 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/kernel.h>
+#include <sys/device.h>
#include <sys/time.h>
-#include <sys/pool.h>
#include <net/if.h>
#include <net/if_types.h>
@@ -59,105 +55,781 @@
#include <netinet/ip6.h>
#endif /* INET6 */
-#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
+#define ACCEPT_FLAGS(oklist) \
+ do { \
+ if ((flags & ~(oklist)) & \
+ PFI_FLAG_ALLMASK) \
+ return (EINVAL); \
+ } while (0)
-/*
- * Global variables
- */
+#define senderr(e) do { rv = (e); goto _bad; } while (0)
+
+struct pfi_kif **pfi_index2kif;
+struct pfi_kif *pfi_self;
+int pfi_indexlim;
+struct pfi_ifhead pfi_ifs;
+struct pfi_statehead pfi_statehead;
+int pfi_ifcnt;
+struct pool pfi_addr_pl;
+long pfi_update = 1;
+struct pfr_addr *pfi_buffer;
+int pfi_buffer_cnt;
+int pfi_buffer_max;
+char pfi_reserved_anchor[PF_ANCHOR_NAME_SIZE] =
+ PF_RESERVED_ANCHOR;
+char pfi_interface_ruleset[PF_RULESET_NAME_SIZE] =
+ PF_INTERFACE_RULESET;
+
+void pfi_dynaddr_update(void *);
+void pfi_kifaddr_update(void *);
+void pfi_table_update(struct pfr_ktable *, struct pfi_kif *,
+ int, int);
+void pfi_instance_add(struct ifnet *, int, int);
+void pfi_address_add(struct sockaddr *, int, int);
+int pfi_if_compare(struct pfi_kif *, struct pfi_kif *);
+struct pfi_kif *pfi_if_create(const char *, struct pfi_kif *, int);
+void pfi_copy_group(char *, const char *, int);
+void pfi_dynamic_drivers(void);
+void pfi_newgroup(const char *, int);
+struct pfi_kif *pfi_lookup_if(const char *);
+int pfi_skip_if(const char *, struct pfi_kif *, int);
+int pfi_unmask(void *);
+void pfi_dohooks(struct pfi_kif *);
+
+RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
+RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
+
+#define PFI_DYNAMIC_BUSES { "pcmcia", "cardbus", "uhub" }
+#define PFI_BUFFER_MAX 0x10000
+#define PFI_MTYPE M_IFADDR
+
+void
+pfi_initialize(void)
+{
+ if (pfi_self != NULL) /* already initialized */
+ return;
+
+ TAILQ_INIT(&pfi_statehead);
+ pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
+ "pfiaddrpl", &pool_allocator_nointr);
+ pfi_dynamic_drivers();
+ pfi_buffer_max = 64;
+ pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer),
+ PFI_MTYPE, M_WAITOK);
+ pfi_self = pfi_if_create("self", NULL, PFI_IFLAG_GROUP);
+}
+
+void
+pfi_attach_clone(struct if_clone *ifc)
+{
+ pfi_initialize();
+ pfi_newgroup(ifc->ifc_name, PFI_IFLAG_CLONABLE);
+}
+
+void
+pfi_attach_ifnet(struct ifnet *ifp)
+{
+ struct pfi_kif *p, *q, key;
+ int s;
+
+ pfi_initialize();
+ s = splsoftnet();
+ pfi_update++;
+ if (ifp->if_index >= pfi_indexlim) {
+ /*
+ * grow pfi_index2kif, similar to ifindex2ifnet code in if.c
+ */
+ size_t m, n, oldlim;
+ struct pfi_kif **mp, **np;
+
+ oldlim = pfi_indexlim;
+ if (pfi_indexlim == 0)
+ pfi_indexlim = 64;
+ while (ifp->if_index >= pfi_indexlim)
+ pfi_indexlim <<= 1;
+
+ m = oldlim * sizeof(struct pfi_kif *);
+ mp = pfi_index2kif;
+ n = pfi_indexlim * sizeof(struct pfi_kif *);
+ np = malloc(n, PFI_MTYPE, M_DONTWAIT);
+ if (np == NULL)
+ panic("pfi_attach_ifnet: "
+ "cannot allocate translation table");
+ bzero(np, n);
+ if (mp != NULL)
+ bcopy(mp, np, m);
+ pfi_index2kif = np;
+ if (mp != NULL)
+ free(mp, PFI_MTYPE);
+ }
+
+ strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name));
+ p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
+ if (p == NULL) {
+ /* add group */
+ pfi_copy_group(key.pfik_name, ifp->if_xname,
+ sizeof(key.pfik_name));
+ q = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
+ if (q == NULL)
+ q = pfi_if_create(key.pfik_name, pfi_self, PFI_IFLAG_GROUP);
+ if (q == NULL)
+ panic("pfi_attach_ifnet: "
+ "cannot allocate '%s' group", key.pfik_name);
+
+ /* add interface */
+ p = pfi_if_create(ifp->if_xname, q, PFI_IFLAG_INSTANCE);
+ if (p == NULL)
+ panic("pfi_attach_ifnet: "
+ "cannot allocate '%s' interface", ifp->if_xname);
+ } else
+ q = p->pfik_parent;
+ p->pfik_ifp = ifp;
+ p->pfik_flags |= PFI_IFLAG_ATTACHED;
+ p->pfik_ah_cookie = hook_establish(ifp->if_addrhooks,
+ 1, pfi_kifaddr_update, p);
+ pfi_index2kif[ifp->if_index] = p;
+ pfi_dohooks(p);
+ splx(s);
+}
+
+void
+pfi_detach_ifnet(struct ifnet *ifp)
+{
+ struct pfi_kif *p, *q, key;
+ int s;
+
+ strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name));
+
+ s = splsoftnet();
+ pfi_update++;
+ p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
+ if (p == NULL) {
+ printf("pfi_detach_ifnet: cannot find %s", ifp->if_xname);
+ splx(s);
+ return;
+ }
+ hook_disestablish(p->pfik_ifp->if_addrhooks, p->pfik_ah_cookie);
+ q = p->pfik_parent;
+ p->pfik_ifp = NULL;
+ p->pfik_flags &= ~PFI_IFLAG_ATTACHED;
+ pfi_index2kif[ifp->if_index] = NULL;
+ pfi_dohooks(p);
+ pfi_maybe_destroy(p);
+ splx(s);
+}
+
+struct pfi_kif *
+pfi_lookup_create(const char *name)
+{
+ struct pfi_kif *p, *q, key;
+ int s;
-void pfi_dynaddr_update(void *);
+ s = splsoftnet();
+ p = pfi_lookup_if(name);
+ if (p == NULL) {
+ pfi_copy_group(key.pfik_name, name, sizeof(key.pfik_name));
+ q = pfi_lookup_if(key.pfik_name);
+ if (q != NULL)
+ p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE);
+ }
+ splx(s);
+ return (p);
+}
+
+struct pfi_kif *
+pfi_attach_rule(const char *name)
+{
+ struct pfi_kif *p;
+
+ p = pfi_lookup_create(name);
+ if (p != NULL)
+ p->pfik_rules++;
+ return (p);
+}
+
+void
+pfi_detach_rule(struct pfi_kif *p)
+{
+ if (p == NULL)
+ return;
+ if (p->pfik_rules > 0)
+ p->pfik_rules--;
+ else
+ printf("pfi_detach_rule: reference count at 0\n");
+ pfi_maybe_destroy(p);
+}
+
+void
+pfi_attach_state(struct pfi_kif *p)
+{
+ if (!p->pfik_states++)
+ TAILQ_INSERT_TAIL(&pfi_statehead, p, pfik_w_states);
+}
+
+void
+pfi_detach_state(struct pfi_kif *p)
+{
+ if (p == NULL)
+ return;
+ if (p->pfik_states <= 0) {
+ printf("pfi_detach_state: reference count <= 0\n");
+ return;
+ }
+ if (!--p->pfik_states)
+ TAILQ_REMOVE(&pfi_statehead, p, pfik_w_states);
+ pfi_maybe_destroy(p);
+}
int
pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
{
+ struct pfi_dynaddr *dyn;
+ char tblname[PF_TABLE_NAME_SIZE];
+ struct pf_ruleset *ruleset = NULL;
+ int s, rv = 0;
+
if (aw->type != PF_ADDR_DYNIFTL)
return (0);
- aw->p.dyn = pool_get(&pf_addr_pl, PR_NOWAIT);
- if (aw->p.dyn == NULL)
- return (1);
- bcopy(aw->v.ifname, aw->p.dyn->ifname, sizeof(aw->p.dyn->ifname));
- aw->p.dyn->ifp = ifunit(aw->p.dyn->ifname);
- if (aw->p.dyn->ifp == NULL) {
- pool_put(&pf_addr_pl, aw->p.dyn);
- aw->p.dyn = NULL;
- return (1);
- }
- aw->p.dyn->addr = &aw->v.a.addr;
- aw->p.dyn->af = af;
- aw->p.dyn->undefined = 1;
- aw->p.dyn->hook_cookie = hook_establish(
- aw->p.dyn->ifp->if_addrhooks, 1,
- pfi_dynaddr_update, aw->p.dyn);
- if (aw->p.dyn->hook_cookie == NULL) {
- pool_put(&pf_addr_pl, aw->p.dyn);
- aw->p.dyn = NULL;
+ dyn = pool_get(&pfi_addr_pl, PR_NOWAIT);
+ if (dyn == NULL)
return (1);
- }
+ bzero(dyn, sizeof(*dyn));
+
+ s = splsoftnet();
+ dyn->pfid_kif = pfi_attach_rule(aw->v.ifname);
+ if (dyn->pfid_kif == NULL)
+ senderr(1);
+
+ dyn->pfid_net = pfi_unmask(&aw->v.a.mask);
+ if (af == AF_INET && dyn->pfid_net == 32)
+ dyn->pfid_net = 128;
+ strlcpy(tblname, aw->v.ifname, sizeof(tblname));
+ if (aw->iflags & PFI_AFLAG_NETWORK)
+ strlcat(tblname, ":network", sizeof(tblname));
+ if (aw->iflags & PFI_AFLAG_BROADCAST)
+ strlcat(tblname, ":broadcast", sizeof(tblname));
+ if (aw->iflags & PFI_AFLAG_PEER)
+ strlcat(tblname, ":peer", sizeof(tblname));
+ if (aw->iflags & PFI_AFLAG_NOALIAS)
+ strlcat(tblname, ":0", sizeof(tblname));
+ if (dyn->pfid_net != 128)
+ snprintf(tblname+strlen(tblname),
+ sizeof(tblname)-strlen(tblname),
+ "/%d", dyn->pfid_net);
+ ruleset = pf_find_or_create_ruleset(pfi_reserved_anchor,
+ pfi_interface_ruleset);
+ if (ruleset == NULL)
+ senderr(1);
+
+ dyn->pfid_kt = pfr_attach_table(ruleset, tblname);
+ if (dyn->pfid_kt == NULL)
+ senderr(1);
+
+ dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE;
+ dyn->pfid_iflags = aw->iflags;
+ dyn->pfid_af = af;
+ dyn->pfid_hook_cookie = hook_establish(
+ dyn->pfid_kif->pfik_ah_head, 1,
+ pfi_dynaddr_update, dyn);
+ if (dyn->pfid_hook_cookie == NULL)
+ senderr(1);
+
+ aw->p.dyn = dyn;
pfi_dynaddr_update(aw->p.dyn);
+ splx(s);
return (0);
+
+_bad:
+ if (dyn->pfid_kt != NULL)
+ pfr_detach_table(dyn->pfid_kt);
+ if (ruleset != NULL)
+ pf_remove_if_empty_ruleset(ruleset);
+ if (dyn->pfid_kif != NULL)
+ pfi_detach_rule(dyn->pfid_kif);
+ pool_put(&pfi_addr_pl, dyn);
+ splx(s);
+ return (rv);
}
void
pfi_dynaddr_update(void *p)
{
- struct pf_addr_dyn *ad = (struct pf_addr_dyn *)p;
- struct ifaddr *ia;
- int s, changed = 0;
+ struct pfi_dynaddr *dyn = (struct pfi_dynaddr *)p;
+ struct pfi_kif *kif = dyn->pfid_kif;
+ struct pfr_ktable *kt = dyn->pfid_kt;
- if (ad == NULL || ad->ifp == NULL)
+ if (dyn == NULL || kif == NULL || kt == NULL)
panic("pfi_dynaddr_update");
- s = splsoftnet();
- TAILQ_FOREACH(ia, &ad->ifp->if_addrlist, ifa_list)
- if (ia->ifa_addr != NULL &&
- ia->ifa_addr->sa_family == ad->af) {
- if (ad->af == AF_INET) {
- struct in_addr *a, *b;
-
- a = &ad->addr->v4;
- b = &((struct sockaddr_in *)ia->ifa_addr)
- ->sin_addr;
- if (ad->undefined ||
- memcmp(a, b, sizeof(*a))) {
- bcopy(b, a, sizeof(*a));
- changed = 1;
- }
- } else if (ad->af == AF_INET6) {
- struct in6_addr *a, *b;
-
- a = &ad->addr->v6;
- b = &((struct sockaddr_in6 *)ia->ifa_addr)
- ->sin6_addr;
- if (ad->undefined ||
- memcmp(a, b, sizeof(*a))) {
- bcopy(b, a, sizeof(*a));
- changed = 1;
- }
+ if (kt->pfrkt_larg != pfi_update) {
+ /* this table need to be brought up-to-date */
+ pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags);
+ kt->pfrkt_larg = pfi_update;
+ }
+ pfr_dynaddr_update(kt, dyn);
+}
+
+void
+pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
+{
+ int e, size2 = 0;
+ struct pfi_kif *p;
+ struct pfr_table t;
+
+ if ((kif->pfik_flags & PFI_IFLAG_INSTANCE) && kif->pfik_ifp == NULL) {
+ pfr_clr_addrs(&kt->pfrkt_t, NULL, 0);
+ return;
+ }
+ pfi_buffer_cnt = 0;
+ if ((kif->pfik_flags & PFI_IFLAG_INSTANCE))
+ pfi_instance_add(kif->pfik_ifp, net, flags);
+ else if (strcmp(kif->pfik_name, "self")) {
+ TAILQ_FOREACH(p, &kif->pfik_grouphead, pfik_instances)
+ pfi_instance_add(p->pfik_ifp, net, flags);
+ } else {
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs)
+ if (p->pfik_flags & PFI_IFLAG_INSTANCE)
+ pfi_instance_add(p->pfik_ifp, net, flags);
+ }
+ t = kt->pfrkt_t;
+ t.pfrt_flags = 0;
+ if ((e = pfr_set_addrs(&t, pfi_buffer, pfi_buffer_cnt, &size2,
+ NULL, NULL, NULL, 0)))
+ printf("pfi_table_update: cannot set %d new addresses "
+ "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e);
+}
+
+void
+pfi_instance_add(struct ifnet *ifp, int net, int flags)
+{
+ struct ifaddr *ia;
+ int got4 = 0, got6 = 0;
+ int net2, af;
+
+ if (ifp == NULL)
+ return;
+ TAILQ_FOREACH(ia, &ifp->if_addrlist, ifa_list) {
+ if (ia->ifa_addr == NULL)
+ continue;
+ af = ia->ifa_addr->sa_family;
+ if (af != AF_INET && af != AF_INET6)
+ continue;
+ if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6)
+ continue;
+ if ((flags & PFI_AFLAG_BROADCAST) &&
+ !(ifp->if_flags & IFF_BROADCAST))
+ continue;
+ if ((flags & PFI_AFLAG_PEER) &&
+ !(ifp->if_flags & IFF_POINTOPOINT))
+ continue;
+ if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 &&
+ IN6_IS_ADDR_LINKLOCAL(
+ &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr))
+ continue;
+ if (flags & PFI_AFLAG_NOALIAS) {
+ if (af == AF_INET && got4)
+ continue;
+ if (af == AF_INET6 && got6)
+ continue;
+ }
+ if (af == AF_INET)
+ got4 = 1;
+ else
+ got6 = 1;
+ net2 = net;
+ if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) {
+ if (af == AF_INET) {
+ net2 = pfi_unmask(&((struct sockaddr_in *)
+ ia->ifa_netmask)->sin_addr);
+ } else {
+ net2 = pfi_unmask(&((struct sockaddr_in6 *)
+ ia->ifa_netmask)->sin6_addr);
}
- if (changed)
- ad->undefined = 0;
- break;
}
- if (ia == NULL)
- ad->undefined = 1;
- splx(s);
+ if (af == AF_INET && net2 > 32)
+ net2 = 32;
+ if (flags & PFI_AFLAG_BROADCAST)
+ pfi_address_add(ia->ifa_broadaddr, af, net2);
+ else if (flags & PFI_AFLAG_PEER)
+ pfi_address_add(ia->ifa_dstaddr, af, net2);
+ else
+ pfi_address_add(ia->ifa_addr, af, net2);
+ }
+}
+
+void
+pfi_address_add(struct sockaddr *sa, int af, int net)
+{
+ struct pfr_addr *p;
+ int i;
+
+ if (pfi_buffer_cnt >= pfi_buffer_max) {
+ int new_max = pfi_buffer_max * 2;
+
+ if (new_max > PFI_BUFFER_MAX) {
+ printf("pfi_address_add: address buffer full "
+ "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
+ return;
+ }
+ p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
+ M_DONTWAIT);
+ if (p == NULL) {
+ printf("pfi_address_add: no memory to grow buffer "
+ " (%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
+ return;
+ }
+ memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer));
+ /* no need to zero buffer */
+ free(pfi_buffer, PFI_MTYPE);
+ pfi_buffer = p;
+ pfi_buffer_max = new_max;
+ }
+ if (af == AF_INET && net > 32)
+ net = 128;
+ p = pfi_buffer + pfi_buffer_cnt++;
+ bzero(p, sizeof(*p));
+ p->pfra_af = af;
+ p->pfra_net = net;
+ if (af == AF_INET)
+ p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr;
+ if (af == AF_INET6) {
+ p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
+ if (IN6_IS_ADDR_LINKLOCAL(&p->pfra_ip6addr))
+ p->pfra_ip6addr.s6_addr16[1] = 0;
+ }
+ /* mask network address bits */
+ if (net < 128)
+ ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8));
+ for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++)
+ ((caddr_t)p)[i] = 0;
}
void
pfi_dynaddr_remove(struct pf_addr_wrap *aw)
{
- if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
+ int s;
+
+ if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
+ aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL)
return;
- hook_disestablish(aw->p.dyn->ifp->if_addrhooks,
- aw->p.dyn->hook_cookie);
- pool_put(&pf_addr_pl, aw->p.dyn);
+
+ s = splsoftnet();
+ hook_disestablish(aw->p.dyn->pfid_kif->pfik_ah_head,
+ aw->p.dyn->pfid_hook_cookie);
+ pfi_detach_rule(aw->p.dyn->pfid_kif);
+ aw->p.dyn->pfid_kif = NULL;
+ pfr_detach_table(aw->p.dyn->pfid_kt);
+ aw->p.dyn->pfid_kt = NULL;
+ pool_put(&pfi_addr_pl, aw->p.dyn);
aw->p.dyn = NULL;
+ splx(s);
}
void
pfi_dynaddr_copyout(struct pf_addr_wrap *aw)
{
- if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
+ if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
+ aw->p.dyn->pfid_kif == NULL)
+ return;
+ aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6;
+}
+
+void
+pfi_kifaddr_update(void *v)
+{
+ int s;
+
+ s = splsoftnet();
+ pfi_update++;
+ pfi_dohooks(v);
+ splx(s);
+}
+
+int
+pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q)
+{
+ return strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ);
+}
+
+struct pfi_kif *
+pfi_if_create(const char *name, struct pfi_kif *q, int flags)
+{
+ struct pfi_kif *p;
+
+ p = malloc(sizeof(*p), PFI_MTYPE, M_DONTWAIT);
+ if (p == NULL)
+ return (NULL);
+ bzero(p, sizeof(*p));
+ p->pfik_ah_head = malloc(sizeof(*p->pfik_ah_head), PFI_MTYPE,
+ M_DONTWAIT);
+ if (p->pfik_ah_head == NULL) {
+ free(p, PFI_MTYPE);
+ return (NULL);
+ }
+ bzero(p->pfik_ah_head, sizeof(*p->pfik_ah_head));
+ TAILQ_INIT(p->pfik_ah_head);
+ TAILQ_INIT(&p->pfik_grouphead);
+ strlcpy(p->pfik_name, name, sizeof(p->pfik_name));
+ RB_INIT(&p->pfik_lan_ext);
+ RB_INIT(&p->pfik_ext_gwy);
+ p->pfik_flags = flags;
+ p->pfik_parent = q;
+ p->pfik_tzero = time.tv_sec;
+
+ RB_INSERT(pfi_ifhead, &pfi_ifs, p);
+ if (q != NULL) {
+ q->pfik_addcnt++;
+ TAILQ_INSERT_TAIL(&q->pfik_grouphead, p, pfik_instances);
+ }
+ pfi_ifcnt++;
+ return (p);
+}
+
+int
+pfi_maybe_destroy(struct pfi_kif *p)
+{
+ int i, j, k, s;
+ struct pfi_kif *q = p->pfik_parent;
+
+ if ((p->pfik_flags & (PFI_IFLAG_ATTACHED | PFI_IFLAG_GROUP)) ||
+ p->pfik_rules > 0 || p->pfik_states > 0)
+ return (0);
+
+ s = splsoftnet();
+ if (q != NULL) {
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 2; j++)
+ for (k = 0; k < 2; k++) {
+ q->pfik_bytes[i][j][k] +=
+ p->pfik_bytes[i][j][k];
+ q->pfik_packets[i][j][k] +=
+ p->pfik_packets[i][j][k];
+ }
+ q->pfik_delcnt++;
+ TAILQ_REMOVE(&q->pfik_grouphead, p, pfik_instances);
+ }
+ pfi_ifcnt--;
+ RB_REMOVE(pfi_ifhead, &pfi_ifs, p);
+ splx(s);
+
+ free(p, PFI_MTYPE);
+ return (1);
+}
+
+void
+pfi_copy_group(char *p, const char *q, int m)
+{
+ while (m > 1 && *q && !(*q >= '0' && *q <= '9')) {
+ *p++ = *q++;
+ m--;
+ }
+ if (m > 0)
+ *p++ = '\0';
+}
+
+void
+pfi_dynamic_drivers(void)
+{
+ char *buses[] = PFI_DYNAMIC_BUSES;
+ int nbuses = sizeof(buses)/sizeof(buses[0]);
+ int enabled[sizeof(buses)/sizeof(buses[0])];
+ struct device *dev;
+ struct cfdata *cf;
+ struct cfdriver *drv;
+ short *p;
+ int i;
+
+ bzero(enabled, sizeof(enabled));
+ TAILQ_FOREACH(dev, &alldevs, dv_list) {
+ if (!(dev->dv_flags & DVF_ACTIVE))
+ continue;
+ for (i = 0; i < nbuses; i++)
+ if (!enabled[i] && !strcmp(buses[i],
+ dev->dv_cfdata->cf_driver->cd_name))
+ enabled[i] = 1;
+ }
+ for (cf = cfdata; cf->cf_driver; cf++) {
+ if (cf->cf_driver->cd_class != DV_IFNET)
+ continue;
+ for (p = cf->cf_parents; p && *p >= 0; p++) {
+ if ((drv = cfdata[*p].cf_driver) == NULL)
+ continue;
+ for (i = 0; i < nbuses; i++)
+ if (enabled[i] &&
+ !strcmp(drv->cd_name, buses[i]))
+ break;
+ if (i < nbuses) {
+ pfi_newgroup(cf->cf_driver->cd_name,
+ PFI_IFLAG_DYNAMIC);
+ break;
+ }
+ }
+ }
+}
+
+void
+pfi_newgroup(const char *name, int flags)
+{
+ struct pfi_kif *p;
+
+ p = pfi_lookup_if(name);
+ if (p == NULL)
+ p = pfi_if_create(name, pfi_self, PFI_IFLAG_GROUP);
+ if (p == NULL) {
+ printf("pfi_newgroup: cannot allocate '%s' group", name);
+ return;
+ }
+ p->pfik_flags |= flags;
+}
+
+void
+pfi_fill_oldstatus(struct pf_status *pfs)
+{
+ struct pfi_kif *p, key;
+ int i, j, k, s;
+
+ strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name));
+ s = splsoftnet();
+ p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
+ if (p == NULL) {
+ splx(s);
return;
- bcopy(aw->p.dyn->ifname, aw->v.ifname, sizeof(aw->v.ifname));
- aw->p.dyn = (struct pf_addr_dyn *)1;
+ }
+ bzero(pfs->pcounters, sizeof(pfs->pcounters));
+ bzero(pfs->bcounters, sizeof(pfs->bcounters));
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 2; j++)
+ for (k = 0; k < 2; k++) {
+ pfs->pcounters[i][j][k] =
+ p->pfik_packets[i][j][k];
+ pfs->bcounters[i][j] +=
+ p->pfik_bytes[i][j][k];
+ }
+ splx(s);
+}
+
+int
+pfi_clr_istats(const char *name, int *nzero, int flags)
+{
+ struct pfi_kif *p;
+ int n = 0, s;
+ long tzero = time.tv_sec;
+
+ s = splsoftnet();
+ ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE);
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+ if (pfi_skip_if(name, p, flags))
+ continue;
+ bzero(p->pfik_packets, sizeof(p->pfik_packets));
+ bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
+ p->pfik_tzero = tzero;
+ n++;
+ }
+ splx(s);
+ if (nzero != NULL)
+ *nzero = n;
+ return (0);
+}
+
+int
+pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags)
+{
+ struct pfi_kif *p;
+ int s, n = 0;
+
+ ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE);
+ s = splsoftnet();
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+ if (pfi_skip_if(name, p, flags))
+ continue;
+ if (*size > n++) {
+ if (!p->pfik_tzero)
+ p->pfik_tzero = boottime.tv_sec;
+ if (copyout(p, buf++, sizeof(*buf))) {
+ splx(s);
+ return (EFAULT);
+ }
+ }
+ }
+ splx(s);
+ *size = n;
+ return (0);
+}
+
+struct pfi_kif *
+pfi_lookup_if(const char *name)
+{
+ struct pfi_kif *p, key;
+
+ strlcpy(key.pfik_name, name, sizeof(key.pfik_name));
+ p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
+ return (p);
+}
+
+int
+pfi_skip_if(const char *filter, struct pfi_kif *p, int f)
+{
+ if ((p->pfik_flags & PFI_IFLAG_GROUP) && !(f & PFI_FLAG_GROUP))
+ return (1);
+ if ((p->pfik_flags & PFI_IFLAG_INSTANCE) && !(f & PFI_FLAG_INSTANCE))
+ return (1);
+ if (filter == NULL || !*filter)
+ return (0);
+ return !strncmp(p->pfik_name, filter, strlen(filter));
+}
+
+/* from pf_print_state.c */
+int
+pfi_unmask(void *addr)
+{
+ struct pf_addr *m = addr;
+ int i = 31, j = 0, b = 0;
+ u_int32_t tmp;
+
+ while (j < 4 && m->addr32[j] == 0xffffffff) {
+ b += 32;
+ j++;
+ }
+ if (j < 4) {
+ tmp = ntohl(m->addr32[j]);
+ for (i = 31; tmp & (1 << i); --i)
+ b++;
+ }
+ return (b);
+}
+
+void
+pfi_dohooks(struct pfi_kif *p)
+{
+ for (; p != NULL; p = p->pfik_parent)
+ dohooks(p->pfik_ah_head, 0);
+}
+
+int
+pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
+{
+ if (af == AF_INET) {
+ switch (dyn->pfid_acnt4) {
+ case 0:
+ return (0);
+ case 1:
+ if (PF_AZERO(&dyn->pfid_mask4, AF_INET))
+ return (1);
+ return (PF_MATCHA(0, &dyn->pfid_addr4,
+ &dyn->pfid_mask4, a, AF_INET));
+ default:
+ return pfr_match_addr(dyn->pfid_kt, a, AF_INET);
+ }
+ } else {
+ switch (dyn->pfid_acnt6) {
+ case (0):
+ return (0);
+ case 1:
+ if (PF_AZERO(&dyn->pfid_mask6, AF_INET6));
+ return (1);
+ return (PF_MATCHA(0, &dyn->pfid_addr6,
+ &dyn->pfid_mask6, a, AF_INET6));
+ default:
+ return pfr_match_addr(dyn->pfid_kt, a, AF_INET6);
+ }
+ }
}
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 3f1af4d5f5f..71e048c4233 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,8 +1,7 @@
-/* $OpenBSD: pf_ioctl.c,v 1.96 2003/12/22 10:10:06 dhartmei Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.97 2003/12/31 11:18:25 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
- * Copyright (c) 2002,2003 Henning Brauer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -107,8 +106,6 @@ pfattach(int num)
pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
&pool_allocator_nointr);
- pool_init(&pf_addr_pl, sizeof(struct pf_addr_dyn), 0, 0, 0, "pfaddrpl",
- &pool_allocator_nointr);
pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, 0, 0,
"pfsrctrpl", NULL);
pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
@@ -118,13 +115,12 @@ pfattach(int num)
pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
"pfpooladdrpl", NULL);
pfr_initialize();
+ pfi_initialize();
pf_osfp_initialize();
pool_sethardlimit(&pf_state_pl, pf_pool_limits[PF_LIMIT_STATES].limit,
NULL, 0);
- RB_INIT(&tree_lan_ext);
- RB_INIT(&tree_ext_gwy);
RB_INIT(&tree_src_tracking);
TAILQ_INIT(&pf_anchors);
pf_init_ruleset(&pf_main_ruleset);
@@ -313,7 +309,8 @@ pf_find_ruleset(char *anchorname, char *rulesetname)
}
struct pf_ruleset *
-pf_find_or_create_ruleset(char *anchorname, char *rulesetname)
+pf_find_or_create_ruleset(char anchorname[PF_ANCHOR_NAME_SIZE],
+ char rulesetname[PF_RULESET_NAME_SIZE])
{
struct pf_anchor *anchor, *a;
struct pf_ruleset *ruleset, *r;
@@ -404,6 +401,7 @@ pf_empty_pool(struct pf_palist *poola)
while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) {
pfi_dynaddr_remove(&empty_pool_pa->addr);
pf_tbladdr_remove(&empty_pool_pa->addr);
+ pfi_detach_rule(empty_pool_pa->kif);
TAILQ_REMOVE(poola, empty_pool_pa, entries);
pool_put(&pf_pooladdr_pl, empty_pool_pa);
}
@@ -438,6 +436,7 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
pf_tbladdr_remove(&rule->src.addr);
pf_tbladdr_remove(&rule->dst.addr);
}
+ pfi_detach_rule(rule->kif);
pf_empty_pool(&rule->rpool.list);
pool_put(&pf_rule_pl, rule);
}
@@ -748,7 +747,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCOSFPGET:
case DIOCGETSRCNODES:
case DIOCCLRSRCNODES:
- break;
+ case DIOCIGETIFACES:
+ case DIOCICLRISTATS:
+ break;
+ case DIOCRCLRTABLES:
+ case DIOCRADDTABLES:
+ case DIOCRDELTABLES:
+ case DIOCRSETTFLAGS:
+ if (((struct pfioc_table *)addr)->pfrio_flags &
+ PFR_FLAG_DUMMY)
+ break; /* dummy operation ok */
+ return (EPERM);
default:
return (EPERM);
}
@@ -778,7 +787,21 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCRTSTADDRS:
case DIOCOSFPGET:
case DIOCGETSRCNODES:
+ case DIOCIGETIFACES:
break;
+ case DIOCRCLRTABLES:
+ case DIOCRADDTABLES:
+ case DIOCRDELTABLES:
+ case DIOCRCLRTSTATS:
+ case DIOCRCLRADDRS:
+ case DIOCRADDADDRS:
+ case DIOCRDELADDRS:
+ case DIOCRSETADDRS:
+ case DIOCRSETTFLAGS:
+ if (((struct pfioc_table *)addr)->pfrio_flags &
+ PFR_FLAG_DUMMY)
+ break; /* dummy operation ok */
+ return (EACCES);
default:
return (EACCES);
}
@@ -800,11 +823,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pf_status.debug = debug;
pf_status.stateid = stateid;
pf_status.hostid = hostid;
- pf_status.src_nodes = src_nodes;
+ pf_status.states = src_nodes;
pf_status.since = time.tv_sec;
- if (status_ifp != NULL)
- strlcpy(pf_status.ifname,
- status_ifp->if_xname, IFNAMSIZ);
DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
}
break;
@@ -866,7 +886,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
bcopy(&pr->rule, rule, sizeof(struct pf_rule));
rule->anchor = NULL;
- rule->ifp = NULL;
+ rule->kif = NULL;
TAILQ_INIT(&rule->rpool.list);
/* initialize refcounting */
rule->states = 0;
@@ -893,8 +913,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
else
rule->nr = 0;
if (rule->ifname[0]) {
- rule->ifp = ifunit(rule->ifname);
- if (rule->ifp == NULL) {
+ rule->kif = pfi_attach_rule(rule->ifname);
+ if (rule->kif == NULL) {
pool_put(&pf_rule_pl, rule);
error = EINVAL;
break;
@@ -1091,14 +1111,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
#endif /* INET6 */
if (newrule->ifname[0]) {
- newrule->ifp = ifunit(newrule->ifname);
- if (newrule->ifp == NULL) {
+ newrule->kif = pfi_attach_rule(newrule->ifname);
+ if (newrule->kif == NULL) {
pool_put(&pf_rule_pl, newrule);
error = EINVAL;
break;
}
} else
- newrule->ifp = NULL;
+ newrule->kif = NULL;
#ifdef ALTQ
/* set queue IDs */
@@ -1205,14 +1225,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_state *state;
s = splsoftnet();
- RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy)
+ RB_FOREACH(state, pf_state_tree_id, &tree_id)
state->timeout = PFTM_PURGE;
pf_purge_expired_states();
pf_status.states = 0;
splx(s);
-#if NPFSYNC
pfsync_clear_states(pf_status.hostid);
-#endif
break;
}
@@ -1222,17 +1240,18 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
int killed = 0;
s = splsoftnet();
- RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy) {
- if ((!psk->psk_af || state->af == psk->psk_af) &&
- (!psk->psk_proto || psk->psk_proto == state->proto) &&
+ RB_FOREACH(state, pf_state_tree_id, &tree_id) {
+ if ((!psk->psk_af || state->af == psk->psk_af)
+ && (!psk->psk_proto || psk->psk_proto ==
+ state->proto) &&
PF_MATCHA(psk->psk_src.not,
&psk->psk_src.addr.v.a.addr,
- &psk->psk_src.addr.v.a.mask, &state->lan.addr,
- state->af) &&
+ &psk->psk_src.addr.v.a.mask,
+ &state->lan.addr, state->af) &&
PF_MATCHA(psk->psk_dst.not,
&psk->psk_dst.addr.v.a.addr,
- &psk->psk_dst.addr.v.a.mask, &state->ext.addr,
- state->af) &&
+ &psk->psk_dst.addr.v.a.mask,
+ &state->ext.addr, state->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],
@@ -1254,6 +1273,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCADDSTATE: {
struct pfioc_state *ps = (struct pfioc_state *)addr;
struct pf_state *state;
+ struct pfi_kif *kif;
if (ps->state.timeout >= PFTM_MAX &&
ps->state.timeout != PFTM_UNTIL_PACKET) {
@@ -1266,15 +1286,23 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
s = splsoftnet();
+ kif = pfi_lookup_create(ps->state.u.ifname);
+ if (kif == NULL) {
+ error = ENOENT;
+ splx(s);
+ }
bcopy(&ps->state, state, sizeof(struct pf_state));
+ bzero(&state->u, sizeof(state->u));
state->rule.ptr = NULL;
state->nat_rule.ptr = NULL;
state->anchor.ptr = NULL;
- state->rt_ifp = NULL;
+ state->rt_kif = NULL;
state->creation = time.tv_sec;
state->packets[0] = state->packets[1] = 0;
state->bytes[0] = state->bytes[1] = 0;
- if (pf_insert_state(state)) {
+
+ if (pf_insert_state(kif, state)) {
+ pfi_maybe_destroy(kif);
pool_put(&pf_state_pl, state);
error = ENOMEM;
}
@@ -1289,7 +1317,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
nr = 0;
s = splsoftnet();
- RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy) {
+ RB_FOREACH(state, pf_state_tree_id, &tree_id) {
if (nr >= ps->nr)
break;
nr++;
@@ -1318,13 +1346,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pfioc_states *ps = (struct pfioc_states *)addr;
struct pf_state *state;
struct pf_state *p, pstore;
+ struct pfi_kif *kif;
u_int32_t nr = 0;
int space = ps->ps_len;
if (space == 0) {
s = splsoftnet();
- RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy)
- nr++;
+ TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states)
+ nr += kif->pfik_states;
splx(s);
ps->ps_len = sizeof(struct pf_state) * nr;
return (0);
@@ -1332,32 +1361,36 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
s = splsoftnet();
p = ps->ps_states;
- RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy) {
- int secs = time.tv_sec;
+ TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states)
+ RB_FOREACH(state, pf_state_tree_ext_gwy,
+ &kif->pfik_ext_gwy) {
+ int secs = time.tv_sec;
- if ((nr + 1) * sizeof(*p) > (unsigned)ps->ps_len)
- break;
+ if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len)
+ break;
- bcopy(state, &pstore, sizeof(pstore));
- pstore.rule.nr = state->rule.ptr->nr;
- pstore.nat_rule.nr = (state->nat_rule.ptr == NULL) ?
- -1 : state->nat_rule.ptr->nr;
- pstore.anchor.nr = (state->anchor.ptr == NULL) ?
- -1 : state->anchor.ptr->nr;
- pstore.creation = secs - pstore.creation;
- pstore.expire = pf_state_expires(state);
- if (pstore.expire > secs)
- pstore.expire -= secs;
- else
- pstore.expire = 0;
- error = copyout(&pstore, p, sizeof(*p));
- if (error) {
- splx(s);
- goto fail;
+ bcopy(state, &pstore, sizeof(pstore));
+ strlcpy(pstore.u.ifname, kif->pfik_name,
+ sizeof(pstore.u.ifname));
+ pstore.rule.nr = state->rule.ptr->nr;
+ pstore.nat_rule.nr = (state->nat_rule.ptr ==
+ NULL) ? -1 : state->nat_rule.ptr->nr;
+ pstore.anchor.nr = (state->anchor.ptr ==
+ NULL) ? -1 : state->anchor.ptr->nr;
+ pstore.creation = secs - pstore.creation;
+ pstore.expire = pf_state_expires(state);
+ if (pstore.expire > secs)
+ pstore.expire -= secs;
+ else
+ pstore.expire = 0;
+ error = copyout(&pstore, p, sizeof(*p));
+ if (error) {
+ splx(s);
+ goto fail;
+ }
+ p++;
+ nr++;
}
- p++;
- nr++;
- }
ps->ps_len = sizeof(struct pf_state) * nr;
splx(s);
break;
@@ -1366,35 +1399,31 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCGETSTATUS: {
struct pf_status *s = (struct pf_status *)addr;
bcopy(&pf_status, s, sizeof(struct pf_status));
+ pfi_fill_oldstatus(s);
break;
}
case DIOCSETSTATUSIF: {
struct pfioc_if *pi = (struct pfioc_if *)addr;
- struct ifnet *ifp;
if (pi->ifname[0] == 0) {
- status_ifp = NULL;
bzero(pf_status.ifname, IFNAMSIZ);
break;
}
- if ((ifp = ifunit(pi->ifname)) == NULL) {
+ if (ifunit(pi->ifname) == NULL) {
error = EINVAL;
break;
- } else if (ifp == status_ifp)
- break;
- status_ifp = ifp;
- /* fallthrough into DIOCCLRSTATUS */
+ }
+ strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ);
+ break;
}
case DIOCCLRSTATUS: {
- u_int64_t stateid = pf_status.stateid;
u_int32_t running = pf_status.running;
u_int32_t states = pf_status.states;
u_int32_t src_nodes = pf_status.src_nodes;
u_int32_t since = pf_status.since;
u_int32_t debug = pf_status.debug;
- u_int32_t hostid = pf_status.hostid;
bzero(&pf_status, sizeof(struct pf_status));
pf_status.running = running;
@@ -1402,11 +1431,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pf_status.src_nodes = src_nodes;
pf_status.since = since;
pf_status.debug = debug;
- pf_status.hostid = hostid;
- pf_status.stateid = stateid;
- if (status_ifp != NULL)
- strlcpy(pf_status.ifname,
- status_ifp->if_xname, IFNAMSIZ);
+ if (*pf_status.ifname)
+ pfi_clr_istats(pf_status.ifname, NULL, 0);
break;
}
@@ -1414,7 +1440,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
struct pf_state *state;
struct pf_state key;
- int direction = pnl->direction;
+ int m = 0, direction = pnl->direction;
key.af = pnl->af;
key.proto = pnl->proto;
@@ -1438,15 +1464,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
key.ext.port = pnl->dport;
PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af);
key.gwy.port = pnl->sport;
- state = pf_find_state(&key, PF_EXT_GWY);
+ state = pf_find_state_all(&key, PF_EXT_GWY, &m);
} else {
PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af);
key.lan.port = pnl->dport;
PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af);
key.ext.port = pnl->sport;
- state = pf_find_state(&key, PF_LAN_EXT);
+ state = pf_find_state_all(&key, PF_LAN_EXT, &m);
}
- if (state != NULL) {
+ if (m > 1)
+ error = E2BIG; /* more than one state */
+ else if (state != NULL) {
if (direction == PF_IN) {
PF_ACPY(&pnl->rsaddr, &state->lan.addr,
state->af);
@@ -1780,8 +1808,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr));
if (pa->ifname[0]) {
- pa->ifp = ifunit(pa->ifname);
- if (pa->ifp == NULL) {
+ pa->kif = pfi_attach_rule(pa->ifname);
+ if (pa->kif == NULL) {
pool_put(&pf_pooladdr_pl, pa);
error = EINVAL;
break;
@@ -1789,6 +1817,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
pfi_dynaddr_remove(&pa->addr);
+ pfi_detach_rule(pa->kif);
pool_put(&pf_pooladdr_pl, pa);
error = EINVAL;
break;
@@ -1894,17 +1923,18 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
#endif /* INET6 */
if (newpa->ifname[0]) {
- newpa->ifp = ifunit(newpa->ifname);
- if (newpa->ifp == NULL) {
+ newpa->kif = pfi_attach_rule(newpa->ifname);
+ if (newpa->kif == NULL) {
pool_put(&pf_pooladdr_pl, newpa);
error = EINVAL;
break;
}
} else
- newpa->ifp = NULL;
+ newpa->kif = NULL;
if (pfi_dynaddr_setup(&newpa->addr, pca->af) ||
pf_tbladdr_setup(ruleset, &newpa->addr)) {
pfi_dynaddr_remove(&newpa->addr);
+ pfi_detach_rule(newpa->kif);
pool_put(&pf_pooladdr_pl, newpa);
error = EINVAL;
break;
@@ -1936,6 +1966,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
TAILQ_REMOVE(&pool->list, oldpa, entries);
pfi_dynaddr_remove(&oldpa->addr);
pf_tbladdr_remove(&oldpa->addr);
+ pfi_detach_rule(oldpa->kif);
pool_put(&pf_pooladdr_pl, oldpa);
} else {
if (oldpa == NULL)
@@ -2028,7 +2059,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
- io->pfrio_flags);
+ io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2040,7 +2071,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
- &io->pfrio_nadd, io->pfrio_flags);
+ &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2052,7 +2083,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
- &io->pfrio_ndel, io->pfrio_flags);
+ &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2064,7 +2095,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
- &io->pfrio_size, io->pfrio_flags);
+ &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2076,7 +2107,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
- &io->pfrio_size, io->pfrio_flags);
+ &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2088,7 +2119,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
- &io->pfrio_nzero, io->pfrio_flags);
+ &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2101,7 +2132,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
- &io->pfrio_ndel, io->pfrio_flags);
+ &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2113,7 +2144,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
- io->pfrio_flags);
+ io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2125,7 +2156,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
- io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags);
+ io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
break;
}
@@ -2137,7 +2169,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
- io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags);
+ io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
break;
}
@@ -2150,7 +2183,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
- &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags);
+ &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
break;
}
@@ -2162,7 +2196,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
- &io->pfrio_size, io->pfrio_flags);
+ &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2174,7 +2208,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer,
- &io->pfrio_size, io->pfrio_flags);
+ &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2186,7 +2220,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
- io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags);
+ io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
break;
}
@@ -2198,7 +2233,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
- io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags);
+ io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
break;
}
@@ -2210,7 +2246,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_ina_begin(&io->pfrio_table, &io->pfrio_ticket,
- &io->pfrio_ndel, io->pfrio_flags);
+ &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2222,7 +2258,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_ina_commit(&io->pfrio_table, io->pfrio_ticket,
- &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags);
+ &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
break;
}
@@ -2235,7 +2272,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
- io->pfrio_ticket, io->pfrio_flags);
+ io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
break;
}
@@ -2490,7 +2527,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_state *state;
s = splsoftnet();
- RB_FOREACH(state, pf_state_tree_lan_ext, &tree_lan_ext) {
+ RB_FOREACH(state, pf_state_tree_id, &tree_id) {
state->src_node = NULL;
state->nat_src_node = NULL;
}
@@ -2521,6 +2558,26 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
splx(s);
break;
+ case DIOCIGETIFACES: {
+ struct pfioc_iface *io = (struct pfioc_iface *)addr;
+
+ if (io->pfiio_esize != sizeof(struct pfi_if)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer,
+ &io->pfiio_size, io->pfiio_flags);
+ break;
+ }
+
+ case DIOCICLRISTATS: {
+ struct pfioc_iface *io = (struct pfioc_iface *)addr;
+
+ error = pfi_clr_istats(io->pfiio_name, &io->pfiio_nzero,
+ io->pfiio_flags);
+ break;
+ }
+
default:
error = ENODEV;
break;
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index 13c7f50eaf2..cf2e897baba 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.76 2003/12/18 20:13:23 dhartmei Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.77 2003/12/31 11:18:25 cedric Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -807,7 +807,7 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
}
int
-pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
+pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
{
struct mbuf *m = *m0;
struct pf_rule *r;
@@ -824,7 +824,8 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->ifp != NULL && r->ifp != ifp)
+ if (r->kif != NULL &&
+ (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -987,13 +988,13 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
no_mem:
REASON_SET(reason, PFRES_MEMORY);
if (r != NULL && r->log)
- PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
return (PF_DROP);
drop:
REASON_SET(reason, PFRES_NORM);
if (r != NULL && r->log)
- PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
return (PF_DROP);
bad:
@@ -1005,14 +1006,15 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
REASON_SET(reason, PFRES_FRAG);
if (r != NULL && r->log)
- PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
return (PF_DROP);
}
#ifdef INET6
int
-pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
+pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
+ u_short *reason)
{
struct mbuf *m = *m0;
struct pf_rule *r;
@@ -1032,7 +1034,8 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->ifp != NULL && r->ifp != ifp)
+ if (r->kif != NULL &&
+ (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -1166,25 +1169,25 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
shortpkt:
REASON_SET(reason, PFRES_SHORT);
if (r != NULL && r->log)
- PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
return (PF_DROP);
drop:
REASON_SET(reason, PFRES_NORM);
if (r != NULL && r->log)
- PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
return (PF_DROP);
badfrag:
REASON_SET(reason, PFRES_FRAG);
if (r != NULL && r->log)
- PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
return (PF_DROP);
}
#endif
int
-pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff,
+pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
int off, void *h, struct pf_pdesc *pd)
{
struct pf_rule *r, *rm = NULL;
@@ -1197,7 +1200,8 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->ifp != NULL && r->ifp != ifp)
+ if (r->kif != NULL &&
+ (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -1290,7 +1294,7 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff,
tcp_drop:
REASON_SET(&reason, PFRES_NORM);
if (rm != NULL && r->log)
- PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, NULL, NULL);
return (PF_DROP);
}
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
index 490edb2393c..8862b22b647 100644
--- a/sys/net/pf_table.c
+++ b/sys/net/pf_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_table.c,v 1.42 2003/09/26 21:44:09 cedric Exp $ */
+/* $OpenBSD: pf_table.c,v 1.43 2003/12/31 11:18:25 cedric Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -49,6 +49,16 @@
return (EINVAL); \
} while (0)
+#define COPYIN(from, to, size) \
+ ((flags & PFR_FLAG_USERIOCTL) ? \
+ copyin((from), (to), (size)) : \
+ (bcopy((from), (to), (size)), 0))
+
+#define COPYOUT(from, to, size) \
+ ((flags & PFR_FLAG_USERIOCTL) ? \
+ copyout((from), (to), (size)) : \
+ (bcopy((from), (to), (size)), 0))
+
#define FILLIN_SIN(sin, addr) \
do { \
(sin).sin_len = sizeof(sin); \
@@ -91,20 +101,24 @@ struct pfr_walktree {
PFRW_ENQUEUE,
PFRW_GET_ADDRS,
PFRW_GET_ASTATS,
- PFRW_POOL_GET
+ PFRW_POOL_GET,
+ PFRW_DYNADDR_UPDATE
} pfrw_op;
union {
struct pfr_addr *pfrw1_addr;
struct pfr_astats *pfrw1_astats;
struct pfr_kentryworkq *pfrw1_workq;
struct pfr_kentry *pfrw1_kentry;
+ struct pfi_dynaddr *pfrw1_dyn;
} pfrw_1;
int pfrw_free;
+ int pfrw_flags;
};
#define pfrw_addr pfrw_1.pfrw1_addr
#define pfrw_astats pfrw_1.pfrw1_astats
#define pfrw_workq pfrw_1.pfrw1_workq
#define pfrw_kentry pfrw_1.pfrw1_kentry
+#define pfrw_dyn pfrw_1.pfrw1_dyn
#define pfrw_cnt pfrw_free
#define senderr(e) do { rv = (e); goto _bad; } while (0)
@@ -133,14 +147,14 @@ void pfr_remove_kentries(struct pfr_ktable *,
struct pfr_kentryworkq *);
void pfr_clstats_kentries(struct pfr_kentryworkq *, long,
int);
-void pfr_reset_feedback(struct pfr_addr *, int);
+void pfr_reset_feedback(struct pfr_addr *, int, int);
void pfr_prepare_network(union sockaddr_union *, int, int);
int pfr_route_kentry(struct pfr_ktable *,
struct pfr_kentry *);
int pfr_unroute_kentry(struct pfr_ktable *,
struct pfr_kentry *);
int pfr_walktree(struct radix_node *, void *);
-int pfr_validate_table(struct pfr_table *, int);
+int pfr_validate_table(struct pfr_table *, int, int);
void pfr_commit_ktable(struct pfr_ktable *, long);
void pfr_insert_ktables(struct pfr_ktableworkq *);
void pfr_insert_ktable(struct pfr_ktable *);
@@ -193,7 +207,7 @@ pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
int s;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
- if (pfr_validate_table(tbl, 0))
+ if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -229,7 +243,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
long tzero = time.tv_sec;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
- if (pfr_validate_table(tbl, 0))
+ if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -241,7 +255,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (ENOMEM);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (copyin(addr+i, &ad, sizeof(ad)))
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@@ -270,7 +284,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
}
}
if (flags & PFR_FLAG_FEEDBACK)
- if (copyout(&ad, addr+i, sizeof(ad)))
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
}
pfr_clean_node_mask(tmpkt, &workq);
@@ -290,7 +304,7 @@ _bad:
pfr_clean_node_mask(tmpkt, &workq);
pfr_destroy_kentries(&workq);
if (flags & PFR_FLAG_FEEDBACK)
- pfr_reset_feedback(addr, size);
+ pfr_reset_feedback(addr, size, flags);
pfr_destroy_ktable(tmpkt, 0);
return (rv);
}
@@ -306,7 +320,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
int i, rv, s, xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
- if (pfr_validate_table(tbl, 0))
+ if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -316,7 +330,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
pfr_mark_addrs(kt);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (copyin(addr+i, &ad, sizeof(ad)))
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@@ -338,7 +352,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
xdel++;
}
if (flags & PFR_FLAG_FEEDBACK)
- if (copyout(&ad, addr+i, sizeof(ad)))
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
}
if (!(flags & PFR_FLAG_DUMMY)) {
@@ -353,7 +367,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (0);
_bad:
if (flags & PFR_FLAG_FEEDBACK)
- pfr_reset_feedback(addr, size);
+ pfr_reset_feedback(addr, size, flags);
return (rv);
}
@@ -369,7 +383,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
long tzero = time.tv_sec;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
- if (pfr_validate_table(tbl, 0))
+ if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -384,7 +398,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
SLIST_INIT(&delq);
SLIST_INIT(&changeq);
for (i = 0; i < size; i++) {
- if (copyin(addr+i, &ad, sizeof(ad)))
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@@ -421,7 +435,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
}
_skip:
if (flags & PFR_FLAG_FEEDBACK)
- if (copyout(&ad, addr+i, sizeof(ad)))
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
}
pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY);
@@ -434,7 +448,7 @@ _skip:
SLIST_FOREACH(p, &delq, pfrke_workq) {
pfr_copyout_addr(&ad, p);
ad.pfra_fback = PFR_FB_DELETED;
- if (copyout(&ad, addr+size+i, sizeof(ad)))
+ if (COPYOUT(&ad, addr+size+i, sizeof(ad)))
senderr(EFAULT);
i++;
}
@@ -456,7 +470,7 @@ _skip:
*ndel = xdel;
if (nchange != NULL)
*nchange = xchange;
- if ((flags & PFR_FLAG_FEEDBACK) && *size2)
+ if ((flags & PFR_FLAG_FEEDBACK) && size2)
*size2 = size+xdel;
pfr_destroy_ktable(tmpkt, 0);
return (0);
@@ -464,7 +478,7 @@ _bad:
pfr_clean_node_mask(tmpkt, &addq);
pfr_destroy_kentries(&addq);
if (flags & PFR_FLAG_FEEDBACK)
- pfr_reset_feedback(addr, size);
+ pfr_reset_feedback(addr, size, flags);
pfr_destroy_ktable(tmpkt, 0);
return (rv);
}
@@ -479,14 +493,14 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
int i, xmatch = 0;
ACCEPT_FLAGS(PFR_FLAG_REPLACE);
- if (pfr_validate_table(tbl, 0))
+ if (pfr_validate_table(tbl, 0, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
return (ESRCH);
for (i = 0; i < size; i++) {
- if (copyin(addr+i, &ad, sizeof(ad)))
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
return (EFAULT);
if (pfr_validate_addr(&ad))
return (EINVAL);
@@ -499,7 +513,7 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
(p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH);
if (p != NULL && !p->pfrke_not)
xmatch++;
- if (copyout(&ad, addr+i, sizeof(ad)))
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
return (EFAULT);
}
if (nmatch != NULL)
@@ -516,7 +530,7 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
int rv;
ACCEPT_FLAGS(0);
- if (pfr_validate_table(tbl, 0))
+ if (pfr_validate_table(tbl, 0, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -530,6 +544,7 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
w.pfrw_op = PFRW_GET_ADDRS;
w.pfrw_addr = addr;
w.pfrw_free = kt->pfrkt_cnt;
+ w.pfrw_flags = flags;
rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
if (!rv)
rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
@@ -556,7 +571,7 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
long tzero = time.tv_sec;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
- if (pfr_validate_table(tbl, 0))
+ if (pfr_validate_table(tbl, 0, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -570,6 +585,7 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
w.pfrw_op = PFRW_GET_ASTATS;
w.pfrw_astats = addr;
w.pfrw_free = kt->pfrkt_cnt;
+ w.pfrw_flags = flags;
if (flags & PFR_FLAG_ATOMIC)
s = splsoftnet();
rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
@@ -604,14 +620,14 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
int i, rv, s, xzero = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
- if (pfr_validate_table(tbl, 0))
+ if (pfr_validate_table(tbl, 0, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
return (ESRCH);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (copyin(addr+i, &ad, sizeof(ad)))
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@@ -619,7 +635,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
if (flags & PFR_FLAG_FEEDBACK) {
ad.pfra_fback = (p != NULL) ?
PFR_FB_CLEARED : PFR_FB_NONE;
- if (copyout(&ad, addr+i, sizeof(ad)))
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
}
if (p != NULL) {
@@ -640,7 +656,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (0);
_bad:
if (flags & PFR_FLAG_FEEDBACK)
- pfr_reset_feedback(addr, size);
+ pfr_reset_feedback(addr, size, flags);
return (rv);
}
@@ -841,16 +857,16 @@ pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange)
}
void
-pfr_reset_feedback(struct pfr_addr *addr, int size)
+pfr_reset_feedback(struct pfr_addr *addr, int size, int flags)
{
struct pfr_addr ad;
int i;
for (i = 0; i < size; i++) {
- if (copyin(addr+i, &ad, sizeof(ad)))
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
break;
ad.pfra_fback = PFR_FB_NONE;
- if (copyout(&ad, addr+i, sizeof(ad)))
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
break;
}
}
@@ -953,7 +969,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
{
struct pfr_kentry *ke = (struct pfr_kentry *)rn;
struct pfr_walktree *w = arg;
- int s;
+ int s, flags = w->pfrw_flags;
switch (w->pfrw_op) {
case PFRW_MARK:
@@ -991,7 +1007,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
splx(s);
as.pfras_tzero = ke->pfrke_tzero;
- if (copyout(&as, w->pfrw_astats, sizeof(as)))
+ if (COPYOUT(&as, w->pfrw_astats, sizeof(as)))
return (EFAULT);
w->pfrw_astats++;
}
@@ -1004,6 +1020,24 @@ pfr_walktree(struct radix_node *rn, void *arg)
return (1); /* finish search */
}
break;
+ case PFRW_DYNADDR_UPDATE:
+ if (ke->pfrke_af == AF_INET) {
+ if (w->pfrw_dyn->pfid_acnt4++ > 0)
+ break;
+ pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net);
+ w->pfrw_dyn->pfid_addr4 = *SUNION2PF(
+ &ke->pfrke_sa, AF_INET);
+ w->pfrw_dyn->pfid_mask4 = *SUNION2PF(
+ &pfr_mask, AF_INET);
+ } else {
+ if (w->pfrw_dyn->pfid_acnt6++ > 0)
+ break;
+ pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net);
+ w->pfrw_dyn->pfid_addr6 = *SUNION2PF(
+ &ke->pfrke_sa, AF_INET6);
+ w->pfrw_dyn->pfid_mask6 = *SUNION2PF(
+ &pfr_mask, AF_INET6);
+ }
}
return (0);
}
@@ -1023,6 +1057,8 @@ pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
if (pfr_skip_table(filter, p, flags))
continue;
+ if (!strcmp(p->pfrkt_anchor, PF_RESERVED_ANCHOR))
+ continue;
if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE))
continue;
p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
@@ -1053,9 +1089,10 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
SLIST_INIT(&addq);
SLIST_INIT(&changeq);
for (i = 0; i < size; i++) {
- if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+ if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
senderr(EFAULT);
- if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK))
+ if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK,
+ flags & PFR_FLAG_USERIOCTL))
senderr(EINVAL);
key.pfrkt_flags |= PFR_TFLAG_ACTIVE;
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
@@ -1131,9 +1168,10 @@ pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+ if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
return (EFAULT);
- if (pfr_validate_table(&key.pfrkt_t, 0))
+ if (pfr_validate_table(&key.pfrkt_t, 0,
+ flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
@@ -1180,7 +1218,7 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
continue;
if (n-- <= 0)
continue;
- if (copyout(&p->pfrkt_t, tbl++, sizeof(*tbl)))
+ if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl)))
return (EFAULT);
}
if (n) {
@@ -1219,7 +1257,7 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
continue;
if (!(flags & PFR_FLAG_ATOMIC))
s = splsoftnet();
- if (copyout(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
+ if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
splx(s);
return (EFAULT);
}
@@ -1251,9 +1289,9 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+ if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
return (EFAULT);
- if (pfr_validate_table(&key.pfrkt_t, 0))
+ if (pfr_validate_table(&key.pfrkt_t, 0, 0))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL) {
@@ -1288,9 +1326,10 @@ pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
return (EINVAL);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+ if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
return (EFAULT);
- if (pfr_validate_table(&key.pfrkt_t, 0))
+ if (pfr_validate_table(&key.pfrkt_t, 0,
+ flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
@@ -1374,7 +1413,8 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
ACCEPT_FLAGS(PFR_FLAG_DUMMY|PFR_FLAG_ADDRSTOO);
if (size && !(flags & PFR_FLAG_ADDRSTOO))
return (EINVAL);
- if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK))
+ if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
+ flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
rs = pf_find_ruleset(tbl->pfrt_anchor, tbl->pfrt_ruleset);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
@@ -1416,7 +1456,7 @@ _skip:
}
SLIST_INIT(&addrq);
for (i = 0; i < size; i++) {
- if (copyin(addr+i, &ad, sizeof(ad)))
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@@ -1594,12 +1634,14 @@ pfr_commit_ktable(struct pfr_ktable *kt, long tzero)
}
int
-pfr_validate_table(struct pfr_table *tbl, int allowedflags)
+pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
{
int i;
if (!tbl->pfrt_name[0])
return (-1);
+ if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR))
+ return (-1);
if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1])
return (-1);
for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++)
@@ -2047,3 +2089,22 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
}
}
+void
+pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
+{
+ struct pfr_walktree w;
+ int s;
+
+ bzero(&w, sizeof(w));
+ w.pfrw_op = PFRW_DYNADDR_UPDATE;
+ w.pfrw_dyn = dyn;
+
+ s = splsoftnet();
+ dyn->pfid_acnt4 = 0;
+ dyn->pfid_acnt6 = 0;
+ if (!dyn->pfid_af || dyn->pfid_af == AF_INET)
+ rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+ if (!dyn->pfid_af || dyn->pfid_af == AF_INET6)
+ rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+ splx(s);
+}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index cc9081f887d..1b3fa417756 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.179 2003/12/15 09:10:26 henning Exp $ */
+/* $OpenBSD: pfvar.h,v 1.180 2003/12/31 11:18:25 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -99,6 +99,12 @@ struct pf_addr {
#define PF_TABLE_NAME_SIZE 32
+#define PFI_AFLAG_NETWORK 0x01
+#define PFI_AFLAG_BROADCAST 0x02
+#define PFI_AFLAG_PEER 0x04
+#define PFI_AFLAG_MODEMASK 0x07
+#define PFI_AFLAG_NOALIAS 0x08
+
struct pf_addr_wrap {
union {
struct {
@@ -109,28 +115,36 @@ struct pf_addr_wrap {
char tblname[PF_TABLE_NAME_SIZE];
} v;
union {
- struct pf_addr_dyn *dyn;
+ struct pfi_dynaddr *dyn;
struct pfr_ktable *tbl;
+ int dyncnt;
int tblcnt;
} p;
u_int8_t type; /* PF_ADDR_* */
+ u_int8_t iflags; /* PFI_AFLAG_* */
};
-struct pf_addr_dyn {
- char ifname[IFNAMSIZ];
- struct ifnet *ifp;
- struct pf_addr *addr;
- sa_family_t af;
- void *hook_cookie;
- u_int8_t undefined;
+#ifdef _KERNEL
+
+struct pfi_dynaddr {
+ struct pf_addr pfid_addr4;
+ struct pf_addr pfid_mask4;
+ struct pf_addr pfid_addr6;
+ struct pf_addr pfid_mask6;
+ struct pfr_ktable *pfid_kt;
+ struct pfi_kif *pfid_kif;
+ void *pfid_hook_cookie;
+ int pfid_net; /* optional mask, or 128 */
+ int pfid_acnt4; /* address count, IPv4 */
+ int pfid_acnt6; /* address count, IPv6 */
+ sa_family_t pfid_af; /* rule address family */
+ u_int8_t pfid_iflags; /* PFI_AFLAG_* */
};
/*
* Address manipulation macros
*/
-#ifdef _KERNEL
-
#ifdef INET
#ifndef INET6
#define PF_INET_ONLY
@@ -267,10 +281,7 @@ struct pf_addr_dyn {
((aw)->type == PF_ADDR_TABLE && \
!pfr_match_addr((aw)->p.tbl, (x), (af))) || \
((aw)->type == PF_ADDR_DYNIFTL && \
- ((aw)->p.dyn->undefined || \
- (!PF_AZERO(&(aw)->v.a.mask, (af)) && \
- !PF_MATCHA(0, &(aw)->v.a.addr, \
- &(aw)->v.a.mask, (x), (af))))) || \
+ !pfi_match_addr((aw)->p.dyn, (x), (af))) || \
((aw)->type == PF_ADDR_ADDRMASK && \
!PF_AZERO(&(aw)->v.a.mask, (af)) && \
!PF_MATCHA(0, &(aw)->v.a.addr, \
@@ -299,7 +310,7 @@ struct pf_pooladdr {
struct pf_addr_wrap addr;
TAILQ_ENTRY(pf_pooladdr) entries;
char ifname[IFNAMSIZ];
- struct ifnet *ifp;
+ struct pfi_kif *kif;
};
TAILQ_HEAD(pf_palist, pf_pooladdr);
@@ -465,7 +476,7 @@ struct pf_rule {
u_int64_t packets;
u_int64_t bytes;
- struct ifnet *ifp;
+ struct pfi_kif *kif;
struct pf_anchor *anchor;
pf_osfp_t os_fingerprint;
@@ -533,6 +544,10 @@ struct pf_rule {
#define PFRULE_RANDOMID 0x0800
#define PFRULE_REASSEMBLE_TCP 0x1000
+/* rule flags again */
+#define PFRULE_IFBOUND 0x00010000 /* if-bound */
+#define PFRULE_GRBOUND 0x00020000 /* group-bound */
+
#define PFSTATE_HIWAT 10000 /* default state table size */
struct pf_src_node {
@@ -540,7 +555,7 @@ struct pf_src_node {
struct pf_addr addr;
struct pf_addr raddr;
union pf_rule_ptr rule;
- struct ifnet *ifp;
+ struct pfi_kif *kif;
u_int32_t bytes;
u_int32_t packets;
u_int32_t states;
@@ -577,9 +592,15 @@ struct pf_state_peer {
struct pf_state {
u_int64_t id;
- RB_ENTRY(pf_state) entry_lan_ext;
- RB_ENTRY(pf_state) entry_ext_gwy;
- RB_ENTRY(pf_state) entry_id;
+ union {
+ struct {
+ RB_ENTRY(pf_state) entry_lan_ext;
+ RB_ENTRY(pf_state) entry_ext_gwy;
+ RB_ENTRY(pf_state) entry_id;
+ struct pfi_kif *kif;
+ } s;
+ char ifname[IFNAMSIZ];
+ } u;
struct pf_state_host lan;
struct pf_state_host gwy;
struct pf_state_host ext;
@@ -589,7 +610,7 @@ struct pf_state {
union pf_rule_ptr anchor;
union pf_rule_ptr nat_rule;
struct pf_addr rt_addr;
- struct ifnet *rt_ifp;
+ struct pfi_kif *rt_kif;
struct pf_src_node *src_node;
struct pf_src_node *nat_src_node;
u_int32_t creation;
@@ -642,6 +663,9 @@ struct pf_anchor {
TAILQ_HEAD(pf_anchorqueue, pf_anchor);
+#define PF_RESERVED_ANCHOR "_pf"
+#define PF_INTERFACE_RULESET "_if"
+
#define PFR_TFLAG_PERSIST 0x00000001
#define PFR_TFLAG_CONST 0x00000002
#define PFR_TFLAG_ACTIVE 0x00000004
@@ -728,6 +752,7 @@ struct pfr_ktable {
struct pfr_ktable *pfrkt_shadow;
struct pfr_ktable *pfrkt_root;
struct pf_ruleset *pfrkt_rs;
+ long pfrkt_larg;
int pfrkt_nflags;
};
#define pfrkt_t pfrkt_ts.pfrts_t
@@ -743,6 +768,60 @@ struct pfr_ktable {
#define pfrkt_nomatch pfrkt_ts.pfrts_nomatch
#define pfrkt_tzero pfrkt_ts.pfrts_tzero
+RB_HEAD(pf_state_tree_lan_ext, pf_state);
+RB_PROTOTYPE(pf_state_tree_lan_ext, pf_state,
+ u.s.entry_lan_ext, pf_state_compare_lan_ext);
+
+RB_HEAD(pf_state_tree_ext_gwy, pf_state);
+RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state,
+ u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
+
+struct pfi_if {
+ char pfif_name[IFNAMSIZ];
+ u_int64_t pfif_packets[2][2][2];
+ u_int64_t pfif_bytes[2][2][2];
+ u_int64_t pfif_addcnt;
+ u_int64_t pfif_delcnt;
+ long pfif_tzero;
+ int pfif_states;
+ int pfif_rules;
+ int pfif_flags;
+};
+
+TAILQ_HEAD(pfi_grouphead, pfi_kif);
+TAILQ_HEAD(pfi_statehead, pfi_kif);
+RB_HEAD(pfi_ifhead, pfi_kif);
+struct pfi_kif {
+ struct pfi_if pfik_if;
+ RB_ENTRY(pfi_kif) pfik_tree;
+ struct pf_state_tree_lan_ext pfik_lan_ext;
+ struct pf_state_tree_ext_gwy pfik_ext_gwy;
+ struct pfi_grouphead pfik_grouphead;
+ TAILQ_ENTRY(pfi_kif) pfik_instances;
+ TAILQ_ENTRY(pfi_kif) pfik_w_states;
+ struct hook_desc_head *pfik_ah_head;
+ void *pfik_ah_cookie;
+ struct pfi_kif *pfik_parent;
+ struct ifnet *pfik_ifp;
+ int pfik_states;
+ int pfik_rules;
+};
+#define pfik_name pfik_if.pfif_name
+#define pfik_packets pfik_if.pfif_packets
+#define pfik_bytes pfik_if.pfif_bytes
+#define pfik_tzero pfik_if.pfif_tzero
+#define pfik_flags pfik_if.pfif_flags
+#define pfik_addcnt pfik_if.pfif_addcnt
+#define pfik_delcnt pfik_if.pfif_delcnt
+#define pfik_states pfik_if.pfif_states
+#define pfik_rules pfik_if.pfif_rules
+
+#define PFI_IFLAG_GROUP 0x0001 /* group of interfaces */
+#define PFI_IFLAG_INSTANCE 0x0002 /* single instance */
+#define PFI_IFLAG_CLONABLE 0x0010 /* clonable group */
+#define PFI_IFLAG_DYNAMIC 0x0020 /* dynamic group */
+#define PFI_IFLAG_ATTACHED 0x0040 /* interface attached */
+
struct pf_pdesc {
u_int64_t tot_len; /* Make Mickey money */
union {
@@ -1071,6 +1150,9 @@ struct pfioc_trans {
#define PFR_FLAG_REPLACE 0x00000020
#define PFR_FLAG_ALLRSETS 0x00000040
#define PFR_FLAG_ALLMASK 0x0000007F
+#ifdef _KERNEL
+#define PFR_FLAG_USERIOCTL 0x10000000
+#endif
struct pfioc_table {
struct pfr_table pfrio_table;
@@ -1092,6 +1174,20 @@ struct pfioc_table {
#define pfrio_clrflag pfrio_nadd
+#define PFI_FLAG_GROUP 0x0001 /* gets groups of interfaces */
+#define PFI_FLAG_INSTANCE 0x0002 /* gets single interfaces */
+#define PFI_FLAG_ALLMASK 0x0003
+
+struct pfioc_iface {
+ char pfiio_name[IFNAMSIZ];
+ void *pfiio_buffer;
+ int pfiio_esize;
+ int pfiio_size;
+ int pfiio_nzero;
+ int pfiio_flags;
+};
+
+
/*
* ioctl operations
*/
@@ -1166,35 +1262,27 @@ struct pfioc_table {
#define DIOCGETSRCNODES _IOWR('D', 84, struct pfioc_src_nodes)
#define DIOCCLRSRCNODES _IO('D', 85)
#define DIOCSETHOSTID _IOWR('D', 86, u_int32_t)
+#define DIOCIGETIFACES _IOWR('D', 87, struct pfioc_iface)
+#define DIOCICLRISTATS _IOWR('D', 88, struct pfioc_iface)
#ifdef _KERNEL
RB_HEAD(pf_src_tree, pf_src_node);
RB_PROTOTYPE(pf_src_tree, pf_src_node, entry, pf_src_compare);
extern struct pf_src_tree tree_src_tracking;
-RB_HEAD(pf_state_tree_lan_ext, pf_state);
-RB_PROTOTYPE(pf_state_tree_lan_ext, pf_state,
- entry_lan_ext, pf_state_compare_lan_ext);
-extern struct pf_state_tree_lan_ext tree_lan_ext;
-
-RB_HEAD(pf_state_tree_ext_gwy, pf_state);
-RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state,
- entry_ext_gwy, pf_state_compare_ext_gwy);
-extern struct pf_state_tree_ext_gwy tree_ext_gwy;
-
RB_HEAD(pf_state_tree_id, pf_state);
RB_PROTOTYPE(pf_state_tree_id, pf_state,
entry_id, pf_state_compare_id);
extern struct pf_state_tree_id tree_id;
-extern struct pf_anchorqueue pf_anchors;
-extern struct pf_ruleset pf_main_ruleset;
+extern struct pf_anchorqueue pf_anchors;
+extern struct pf_ruleset pf_main_ruleset;
TAILQ_HEAD(pf_poolqueue, pf_pool);
-extern struct pf_poolqueue pf_pools[2];
+extern struct pf_poolqueue pf_pools[2];
TAILQ_HEAD(pf_altqqueue, pf_altq);
-extern struct pf_altqqueue pf_altqs[2];
-extern struct pf_palist pf_pabuf;
-
+extern struct pf_altqqueue pf_altqs[2];
+extern struct pf_palist pf_pabuf;
+extern struct pfi_kif **pfi_index2kif;
extern u_int32_t ticket_altqs_active;
extern u_int32_t ticket_altqs_inactive;
@@ -1212,25 +1300,30 @@ extern void pf_calc_skip_steps(struct pf_rulequeue *);
extern void pf_rule_set_qid(struct pf_rulequeue *);
extern u_int32_t pf_qname_to_qid(char *);
extern void pf_update_anchor_rules(void);
-extern struct pool pf_src_tree_pl, pf_rule_pl, pf_addr_pl;
+extern struct pool pf_src_tree_pl, pf_rule_pl;
extern struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
extern struct pool pf_state_scrub_pl;
extern void pf_purge_timeout(void *);
extern void pf_purge_expired_src_nodes(void);
extern void pf_purge_expired_states(void);
-extern int pf_insert_state(struct pf_state *);
+extern int pf_insert_state(struct pfi_kif *,
+ struct pf_state *);
extern int pf_insert_src_node(struct pf_src_node **,
struct pf_rule *, struct pf_addr *,
sa_family_t);
void pf_src_tree_remove_state(struct pf_state *);
-extern struct pf_state *pf_find_state(struct pf_state *, u_int8_t);
+extern struct pf_state *pf_find_state_byid(struct pf_state *);
+extern struct pf_state *pf_find_state_all(struct pf_state *key,
+ u_int8_t tree, int *more);
extern struct pf_anchor *pf_find_anchor(const char *);
extern struct pf_ruleset *pf_find_ruleset(char *, char *);
-extern struct pf_ruleset *pf_find_or_create_ruleset(char *, char *);
+extern struct pf_ruleset *pf_find_or_create_ruleset(
+ char[PF_ANCHOR_NAME_SIZE],
+ char[PF_RULESET_NAME_SIZE]);
extern void pf_remove_if_empty_ruleset(
struct pf_ruleset *);
-extern struct ifnet *status_ifp, *sync_ifp;
+extern struct ifnet *sync_ifp;
extern struct pf_rule pf_default_rule;
extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
u_int8_t);
@@ -1251,7 +1344,7 @@ void pf_addr_inc(struct pf_addr *, sa_family_t);
void *pf_pull_hdr(struct mbuf *, int, void *, int, u_short *, u_short *,
sa_family_t);
void pf_change_a(void *, u_int16_t *, u_int32_t, u_int8_t);
-int pflog_packet(struct ifnet *, struct mbuf *, sa_family_t, u_int8_t,
+int pflog_packet(struct pfi_kif *, struct mbuf *, sa_family_t, u_int8_t,
u_int8_t, struct pf_rule *, struct pf_rule *, struct pf_ruleset *);
int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *,
struct pf_addr *, sa_family_t);
@@ -1261,9 +1354,9 @@ int pf_match_uid(u_int8_t, uid_t, uid_t, uid_t);
int pf_match_gid(u_int8_t, gid_t, gid_t, gid_t);
void pf_normalize_init(void);
-int pf_normalize_ip(struct mbuf **, int, struct ifnet *, u_short *);
-int pf_normalize_ip6(struct mbuf **, int, struct ifnet *, u_short *);
-int pf_normalize_tcp(int, struct ifnet *, struct mbuf *, int, int, void *,
+int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *);
+int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *);
+int pf_normalize_tcp(int, struct pfi_kif *, struct mbuf *, int, int, void *,
struct pf_pdesc *);
void pf_normalize_tcp_cleanup(struct pf_state *);
int pf_normalize_tcp_init(struct mbuf *, int, struct pf_pdesc *,
@@ -1281,6 +1374,7 @@ void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
u_int64_t, int, int, int);
int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *,
struct pf_addr **, struct pf_addr **, sa_family_t);
+void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *);
struct pfr_ktable *
pfr_attach_table(struct pf_ruleset *, char *);
void pfr_detach_table(struct pfr_ktable *);
@@ -1310,9 +1404,26 @@ int pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int);
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
int *, u_int32_t, int);
-int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t);
-void pfi_dynaddr_copyout(struct pf_addr_wrap *);
-void pfi_dynaddr_remove(struct pf_addr_wrap *);
+void pfi_initialize(void);
+void pfi_attach_clone(struct if_clone *);
+void pfi_attach_ifnet(struct ifnet *);
+void pfi_detach_ifnet(struct ifnet *);
+struct pfi_kif *pfi_lookup_create(const char *);
+int pfi_maybe_destroy(struct pfi_kif *);
+struct pfi_kif *pfi_attach_rule(const char *);
+void pfi_detach_rule(struct pfi_kif *);
+void pfi_attach_state(struct pfi_kif *);
+void pfi_detach_state(struct pfi_kif *);
+int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t);
+void pfi_dynaddr_copyout(struct pf_addr_wrap *);
+void pfi_dynaddr_remove(struct pf_addr_wrap *);
+void pfi_fill_oldstatus(struct pf_status *);
+int pfi_clr_istats(const char *, int *, int);
+int pfi_get_ifaces(const char *, struct pfi_if *, int *, int);
+int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *,
+ sa_family_t);
+
+extern struct pfi_statehead pfi_statehead;
u_int16_t pf_tagname2tag(char *);
void pf_tag2tagname(u_int16_t, char *);