summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
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 *);