[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

important pf diff, needs lots of testiing and review



this diff is really important. it cleans up the interface abstraction 
code big time and is a prerequisite for more changes coming. Ryan and 
myself worked our asses off getting this right in montreal last week and 
did quite a bit of testing on the flight to vancouver yesterday; please 
help us to get this so well tested that we can get it in thursday 
(we'll be mostly away 'til then).

known and expected breakage:
-interface groups are gone (i. e. "em" for em0, em1 ..., will be back 
 later, but different)
-I think the "self" handling is broken, needs verification

important to test (besides lots of general testing) is hotplugging 
interfaces, and removal. load rulesets referring to not yet existant 
interfaces and plug em later and verify the rules work as intended and 
such.

thanks.

Index: sys/net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.109
diff -u -p -r1.109 if.c
--- sys/net/if.c	9 May 2005 08:08:47 -0000	1.109
+++ sys/net/if.c	16 May 2005 16:26:32 -0000
@@ -293,7 +293,7 @@ if_alloc_sadl(struct ifnet *ifp)
 	if (ifp->if_sadl != NULL)
 		if_free_sadl(ifp);
 
-	namelen = strlen(ifp->if_xname);
+	namelen = strlen(ifp->if_xname) + 1;
 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
 	masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
 	socksize = masklen + ifp->if_addrlen;
@@ -307,8 +307,8 @@ if_alloc_sadl(struct ifnet *ifp)
 	sdl = (struct sockaddr_dl *)(ifa + 1);
 	sdl->sdl_len = socksize;
 	sdl->sdl_family = AF_LINK;
-	bcopy(ifp->if_xname, sdl->sdl_data, namelen);
-	sdl->sdl_nlen = namelen;
+	strlcpy(sdl->sdl_data, ifp->if_xname, namelen);
+	sdl->sdl_nlen = namelen - 1;
 	sdl->sdl_alen = ifp->if_addrlen;
 	sdl->sdl_index = ifp->if_index;
 	sdl->sdl_type = ifp->if_type;
@@ -776,9 +776,6 @@ if_clone_attach(struct if_clone *ifc)
 {
 	LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
 	if_cloners_count++;
-#if NPF > 0
-	pfi_attach_clone(ifc);
-#endif
 }
 
 /*
Index: sys/net/if.h
===================================================================
RCS file: /cvs/src/sys/net/if.h,v
retrieving revision 1.65
diff -u -p -r1.65 if.h
--- sys/net/if.h	20 Apr 2005 23:00:40 -0000	1.65
+++ sys/net/if.h	16 May 2005 16:26:32 -0000
@@ -181,6 +181,7 @@ struct ifnet {				/* and the entries */
 	int	if_pcount;		/* number of promiscuous listeners */
 	caddr_t	if_bpf;			/* packet filter structure */
 	caddr_t	if_bridge;		/* bridge structure */
+	caddr_t	if_pf_kif;		/* pf interface abstraction */
 	union {
 		caddr_t	carp_s;		/* carp structure (used by !carp ifs) */
 		struct ifnet *carp_d;	/* ptr to carpdev (used by carp ifs) */
Index: sys/net/if_pfsync.c
===================================================================
RCS file: /cvs/src/sys/net/if_pfsync.c,v
retrieving revision 1.46
diff -u -p -r1.46 if_pfsync.c
--- sys/net/if_pfsync.c	20 Feb 2005 15:58:38 -0000	1.46
+++ sys/net/if_pfsync.c	16 May 2005 16:26:33 -0000
@@ -173,7 +173,7 @@ pfsync_insert_net_state(struct pfsync_st
 		return (EINVAL);
 	}
 
-	kif = pfi_lookup_create(sp->ifname);
+	kif = pfi_kif_get(sp->ifname);
 	if (kif == NULL) {
 		if (pf_status.debug >= PF_DEBUG_MISC)
 			printf("pfsync_insert_net_state: "
@@ -191,7 +191,7 @@ pfsync_insert_net_state(struct pfsync_st
 	if (!r->max_states || r->states < r->max_states)
 		st = pool_get(&pf_state_pl, PR_NOWAIT);
 	if (st == NULL) {
-		pfi_maybe_destroy(kif);
+		pfi_kif_unref(kif, PFI_KIF_REF_NONE);
 		return (ENOMEM);
 	}
 	bzero(st, sizeof(*st));
@@ -227,7 +227,7 @@ pfsync_insert_net_state(struct pfsync_st
 
 
 	if (pf_insert_state(kif, st)) {
-		pfi_maybe_destroy(kif);
+		pfi_kif_unref(kif, PFI_KIF_REF_NONE);
 		/* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
 		r->states--;
 		pool_put(&pf_state_pl, st);
@@ -330,14 +330,7 @@ pfsync_input(struct mbuf *m, ...)
 				}
 			}
 		} else {
-			kif = pfi_lookup_if(cp->ifname);
-			if (kif == NULL) {
-				if (pf_status.debug >= PF_DEBUG_MISC)
-					printf("pfsync_input: PFSYNC_ACT_CLR "
-					    "bad interface: %s\n", cp->ifname);
-				splx(s);
-				goto done;
-			}
+			kif = pfi_kif_get(cp->ifname);
 			for (st = RB_MIN(pf_state_tree_lan_ext,
 			    &kif->pfik_lan_ext); st; st = nexts) {
 				nexts = RB_NEXT(pf_state_tree_lan_ext,
Index: sys/net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.488
diff -u -p -r1.488 pf.c
--- sys/net/pf.c	25 Apr 2005 17:55:51 -0000	1.488
+++ sys/net/pf.c	16 May 2005 16:26:34 -0000
@@ -252,9 +252,8 @@ struct pf_pool_limit pf_pool_limits[PF_L
 	(s)->lan.addr.addr32[3] != (s)->gwy.addr.addr32[3])) || \
 	(s)->lan.port != (s)->gwy.port
 
-#define BOUND_IFACE(r, k) (((r)->rule_flag & PFRULE_IFBOUND) ? (k) :   \
-	((r)->rule_flag & PFRULE_GRBOUND) ? (k)->pfik_parent :	       \
-	(k)->pfik_parent->pfik_parent)
+#define BOUND_IFACE(r, k) \
+	((r)->rule_flag & PFRULE_IFBOUND) ? (k) : pfi_all
 
 #define STATE_INC_COUNTERS(s)				\
 	do {						\
@@ -537,20 +536,20 @@ pf_find_state_recurse(struct pfi_kif *ki
 
 	switch (tree) {
 	case PF_LAN_EXT:
-		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);
-		}
+		if ((s = RB_FIND(pf_state_tree_lan_ext, &kif->pfik_lan_ext,
+		    key)) != NULL)
+			return (s);
+		if ((s = RB_FIND(pf_state_tree_lan_ext, &pfi_all->pfik_lan_ext,
+		    key)) != NULL)
+			return (s);
 		return (NULL);
 	case PF_EXT_GWY:
-		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);
-		}
+		if ((s = RB_FIND(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy,
+		    key)) != NULL)
+			return (s);
+		if ((s = RB_FIND(pf_state_tree_ext_gwy, &pfi_all->pfik_ext_gwy,
+		    key)) != NULL)
+			return (s);
 		return (NULL);
 	default:
 		panic("pf_find_state_recurse");
@@ -849,7 +848,7 @@ pf_insert_state(struct pfi_kif *kif, str
 
 	pf_status.fcounters[FCNT_STATE_INSERT]++;
 	pf_status.states++;
-	pfi_attach_state(kif);
+	pfi_kif_ref(kif, PFI_KIF_REF_STATE);
 #if NPFSYNC
 	pfsync_insert_state(state);
 #endif
@@ -990,7 +989,7 @@ pf_purge_expired_state(struct pf_state *
 		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);
+	pfi_kif_unref(cur->u.s.kif, PFI_KIF_REF_STATE);
 	TAILQ_REMOVE(&state_updates, cur, u.s.entry_updates);
 	if (cur->tag)
 		pf_tag_unref(cur->tag);
@@ -2255,8 +2254,7 @@ pf_match_translation(struct pf_pdesc *pd
 		}
 
 		r->evaluations++;
-		if (r->kif != NULL &&
-		    (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+		if (pfi_kif_match(r->kif, kif) == !r->ifnot)
 			r = r->skip[PF_SKIP_IFP].ptr;
 		else if (r->direction && r->direction != direction)
 			r = r->skip[PF_SKIP_DIR].ptr;
@@ -2737,8 +2735,7 @@ pf_test_tcp(struct pf_rule **rm, struct 
 
 	while (r != NULL) {
 		r->evaluations++;
-		if (r->kif != NULL &&
-		    (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+		if (pfi_kif_match(r->kif, kif) == !r->ifnot)
 			r = r->skip[PF_SKIP_IFP].ptr;
 		else if (r->direction && r->direction != direction)
 			r = r->skip[PF_SKIP_DIR].ptr;
@@ -3112,8 +3109,7 @@ pf_test_udp(struct pf_rule **rm, struct 
 
 	while (r != NULL) {
 		r->evaluations++;
-		if (r->kif != NULL &&
-		    (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+		if (pfi_kif_match(r->kif, kif) == !r->ifnot)
 			r = r->skip[PF_SKIP_IFP].ptr;
 		else if (r->direction && r->direction != direction)
 			r = r->skip[PF_SKIP_DIR].ptr;
@@ -3440,8 +3436,7 @@ pf_test_icmp(struct pf_rule **rm, struct
 
 	while (r != NULL) {
 		r->evaluations++;
-		if (r->kif != NULL &&
-		    (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+		if (pfi_kif_match(r->kif, kif) == !r->ifnot)
 			r = r->skip[PF_SKIP_IFP].ptr;
 		else if (r->direction && r->direction != direction)
 			r = r->skip[PF_SKIP_DIR].ptr;
@@ -3692,8 +3687,7 @@ pf_test_other(struct pf_rule **rm, struc
 
 	while (r != NULL) {
 		r->evaluations++;
-		if (r->kif != NULL &&
-		    (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+		if (pfi_kif_match(r->kif, kif) == !r->ifnot)
 			r = r->skip[PF_SKIP_IFP].ptr;
 		else if (r->direction && r->direction != direction)
 			r = r->skip[PF_SKIP_DIR].ptr;
@@ -3902,8 +3896,7 @@ pf_test_fragment(struct pf_rule **rm, in
 	r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
 	while (r != NULL) {
 		r->evaluations++;
-		if (r->kif != NULL &&
-		    (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+		if (pfi_kif_match(r->kif, kif) == !r->ifnot)
 			r = r->skip[PF_SKIP_IFP].ptr;
 		else if (r->direction && r->direction != direction)
 			r = r->skip[PF_SKIP_DIR].ptr;
@@ -5708,7 +5701,7 @@ pf_test(int dir, struct ifnet *ifp, stru
 	if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
 		ifp = ifp->if_carpdev;
 
-	kif = pfi_index2kif[ifp->if_index];
+	kif = (struct pfi_kif *)ifp->if_pf_kif;
 	if (kif == NULL) {
 		DPFPRINTF(PF_DEBUG_URGENT,
 		    ("pf_test: kif == NULL, if_xname %s\n", ifp->if_xname));
@@ -6027,7 +6020,7 @@ pf_test6(int dir, struct ifnet *ifp, str
 	if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
 		ifp = ifp->if_carpdev;
 
-	kif = pfi_index2kif[ifp->if_index];
+	kif = (struct pfi_kif *)ifp->if_pf_kif;
 	if (kif == NULL) {
 		DPFPRINTF(PF_DEBUG_URGENT,
 		    ("pf_test6: kif == NULL, if_xname %s\n", ifp->if_xname));
Index: sys/net/pf_if.c
===================================================================
RCS file: /cvs/src/sys/net/pf_if.c,v
retrieving revision 1.24
diff -u -p -r1.24 pf_if.c
--- sys/net/pf_if.c	21 Apr 2005 13:34:45 -0000	1.24
+++ sys/net/pf_if.c	16 May 2005 16:26:34 -0000
@@ -1,6 +1,8 @@
 /*	$OpenBSD: pf_if.c,v 1.24 2005/04/21 13:34:45 pascoe Exp $ */
 
 /*
+ * Copyright 2005 Henning Brauer <henning_(_at_)_openbsd_(_dot_)_org>
+ * Copyright 2005 Ryan McBride <mcbride_(_at_)_openbsd_(_dot_)_org>
  * Copyright (c) 2001 Daniel Hartmeier
  * Copyright (c) 2003 Cedric Berger
  * All rights reserved.
@@ -55,40 +57,27 @@
 #include <netinet/ip6.h>
 #endif /* INET6 */
 
-#define ACCEPT_FLAGS(oklist)			\
-	do {					\
-		if ((flags & ~(oklist)) &	\
-		    PFI_FLAG_ALLMASK)		\
-			return (EINVAL);	\
-	} while (0)
-
-#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_kif		 *pfi_all = NULL;
 struct pfi_ifhead	  pfi_ifs;
 struct pfi_statehead	  pfi_statehead;
-int			  pfi_ifcnt;
 struct pool		  pfi_addr_pl;
+struct pfi_ifhead	  pfi_ifs;
 long			  pfi_update = 1;
 struct pfr_addr		 *pfi_buffer;
 int			  pfi_buffer_cnt;
 int			  pfi_buffer_max;
 
 void		 pfi_dynaddr_update(void *);
+void		 pfi_table_update(struct pfr_ktable *, struct pfi_kif *,
+		    int, int);
 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_newgroup(const char *, int);
-int		 pfi_skip_if(const char *, struct pfi_kif *, int);
+int		 pfi_skip_if(const char *, struct pfi_kif *);
 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);
@@ -99,7 +88,7 @@ RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tr
 void
 pfi_initialize(void)
 {
-	if (pfi_self != NULL)	/* already initialized */
+	if (pfi_all != NULL)	/* already initialized */
 		return;
 
 	TAILQ_INIT(&pfi_statehead);
@@ -108,176 +97,187 @@ pfi_initialize(void)
 	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);
+	pfi_all = pfi_kif_get("all");
 }
 
-void
-pfi_attach_ifnet(struct ifnet *ifp)
+struct pfi_kif *
+pfi_kif_get(char *kif_name)
 {
-	struct pfi_kif	*p, *q, key;
-	int		 s;
+	struct pfi_kif	s, *kif;
 
-	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);
+	bzero(&s, sizeof(s));
+	strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name));
+	if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, &s)) != NULL)
+		return (kif);
+
+	/* create new one */
+	if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT)) == NULL)
+		return (NULL);
+
+	bzero(kif, sizeof(*kif));
+	strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
+	kif->pfik_tzero = time_second;
+
+	if ((kif->pfik_ah_head = malloc(sizeof(*kif->pfik_ah_head), PFI_MTYPE,
+	    M_DONTWAIT)) == NULL) {
+		free(kif, PFI_MTYPE);
+		return (NULL);
 	}
 
-	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);
-	if (p->pfik_ah_cookie == NULL)
-		panic("pfi_attach_ifnet: cannot allocate '%s' address hook",
-		    ifp->if_xname);
-	pfi_index2kif[ifp->if_index] = p;
-	pfi_dohooks(p);
-	splx(s);
+	bzero(kif->pfik_ah_head, sizeof(*kif->pfik_ah_head));
+	TAILQ_INIT(kif->pfik_ah_head);
+
+	RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
+
+	return (kif);
 }
 
 void
-pfi_detach_ifnet(struct ifnet *ifp)
+pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what)
 {
-	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;
+	switch (what) {
+	case PFI_KIF_REF_RULE:
+		kif->pfik_rules++;
+		break;
+	case PFI_KIF_REF_STATE:
+		if (!kif->pfik_states++)
+			TAILQ_INSERT_TAIL(&pfi_statehead, kif, pfik_w_states);
+		break;
+	default:
+		panic("pfi_kif_ref with unknown type");
 	}
-	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)
+void
+pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what)
 {
-	struct pfi_kif	*p, *q, key;
-	int		 s;
+	if (kif == NULL)
+		return;
 
-	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) {
-			pfi_newgroup(key.pfik_name, PFI_IFLAG_DYNAMIC);
-			q = pfi_lookup_if(key.pfik_name);
+	switch (what) {
+	case PFI_KIF_REF_NONE:
+		break;
+	case PFI_KIF_REF_RULE:
+		if (kif->pfik_rules <= 0) {
+			printf("pfi_kif_unref: rules refcount <= 0\n");
+			return;
+		}
+		kif->pfik_rules--;
+		break;
+	case PFI_KIF_REF_STATE:
+		if (kif->pfik_states <= 0) {
+			printf("pfi_kif_unref: state refcount <= 0\n");
+			return;
 		}
-		p = pfi_lookup_if(name);
-		if (p == NULL && q != NULL)
-			p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE);
+		if (!--kif->pfik_states)
+			TAILQ_REMOVE(&pfi_statehead, kif, pfik_w_states);
+		break;
+	default:
+		panic("pfi_kif_unref with unknown type");
 	}
-	splx(s);
-	return (p);
+
+	/* XXX check for ifgroups ptr too */
+	if (kif->pfik_ifp != NULL || kif == pfi_all)
+		return;
+
+	if (kif->pfik_rules || kif->pfik_states)
+		return;
+
+	RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
+	free(kif->pfik_ah_head, PFI_MTYPE);
+	free(kif, PFI_MTYPE);
 }
 
-struct pfi_kif *
-pfi_attach_rule(const char *name)
+int
+pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif)
 {
-	struct pfi_kif	*p;
+	if (rule_kif == packet_kif)
+		return (1);
+
+	/* XXX walk rule_kif's ifgroups and check for match */
 
-	p = pfi_lookup_create(name);
-	if (p != NULL)
-		p->pfik_rules++;
-	return (p);
+	return (0);
 }
 
 void
-pfi_detach_rule(struct pfi_kif *p)
+pfi_attach_ifnet(struct ifnet *ifp)
 {
-	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);
+	struct pfi_kif	*kif, key;
+	int		 s;
+
+	pfi_initialize();
+	s = splsoftnet();
+
+	strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name));
+	if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, &key)) == NULL)
+		if ((kif = pfi_kif_get(ifp->if_xname)) == NULL)
+			panic("pfi_kif_get failed");
+
+	kif->pfik_ifp = ifp;
+	ifp->if_pf_kif = (caddr_t)kif;
+
+	if ((kif->pfik_ah_cookie = hook_establish(ifp->if_addrhooks, 1,
+	    pfi_kifaddr_update, kif)) == NULL)
+		panic("pfi_attach_ifnet: cannot allocate '%s' address hook",
+		    ifp->if_xname);
+	dohooks(kif->pfik_ah_head, 0);
+
+	splx(s);
 }
 
 void
-pfi_attach_state(struct pfi_kif *p)
+pfi_detach_ifnet(struct ifnet *ifp)
 {
-	if (!p->pfik_states++)
-		TAILQ_INSERT_TAIL(&pfi_statehead, p, pfik_w_states);
+	int		 s;
+	struct pfi_kif	*kif;
+
+	if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL)
+		return;
+
+	s = splsoftnet();
+	hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie);
+	dohooks(kif->pfik_ah_head, 0);
+
+	pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+	kif->pfik_ifp = NULL;
+	ifp->if_pf_kif = NULL;	
+	splx(s);
 }
 
-void
-pfi_detach_state(struct pfi_kif *p)
+int
+pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
 {
-	if (p == NULL)
-		return;
-	if (p->pfik_states <= 0) {
-		printf("pfi_detach_state: reference count <= 0\n");
-		return;
+	switch (af) {
+#ifdef INET
+	case AF_INET:
+		switch (dyn->pfid_acnt4) {
+		case 0:
+			return (0);
+		case 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));
+		}
+		break;
+#endif /* INET */
+#ifdef INET6
+	case AF_INET6:
+		switch (dyn->pfid_acnt6) {
+		case 0:
+			return (0);
+		case 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));
+		}
+		break;
+#endif /* INET6 */
+	default:
+		return (0);
 	}
-	if (!--p->pfik_states)
-		TAILQ_REMOVE(&pfi_statehead, p, pfik_w_states);
-	pfi_maybe_destroy(p);
 }
 
 int
@@ -296,9 +296,12 @@ pfi_dynaddr_setup(struct pf_addr_wrap *a
 	bzero(dyn, sizeof(*dyn));
 
 	s = splsoftnet();
-	dyn->pfid_kif = pfi_attach_rule(aw->v.ifname);
-	if (dyn->pfid_kif == NULL)
-		senderr(1);
+	dyn->pfid_kif = pfi_kif_get(aw->v.ifname);
+	if (dyn->pfid_kif == NULL) {
+		rv = 1;
+		goto _bad;
+	}
+	pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE);
 
 	dyn->pfid_net = pfi_unmask(&aw->v.a.mask);
 	if (af == AF_INET && dyn->pfid_net == 32)
@@ -316,20 +319,26 @@ pfi_dynaddr_setup(struct pf_addr_wrap *a
 		snprintf(tblname + strlen(tblname),
 		    sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net);
 	ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR);
-	if (ruleset == NULL)
-		senderr(1);
+	if (ruleset == NULL) {
+		rv = 1;
+		goto _bad;
+	}
 
 	dyn->pfid_kt = pfr_attach_table(ruleset, tblname);
-	if (dyn->pfid_kt == NULL)
-		senderr(1);
+	if (dyn->pfid_kt == NULL) {
+		rv = 1;
+		goto _bad;
+	}
 
 	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);
+	if (dyn->pfid_hook_cookie == NULL) {
+		rv = 1;
+		goto _bad;
+	}
 
 	aw->p.dyn = dyn;
 	pfi_dynaddr_update(aw->p.dyn);
@@ -342,7 +351,7 @@ _bad:
 	if (ruleset != NULL)
 		pf_remove_if_empty_ruleset(ruleset);
 	if (dyn->pfid_kif != NULL)
-		pfi_detach_rule(dyn->pfid_kif);
+		pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE);
 	pool_put(&pfi_addr_pl, dyn);
 	splx(s);
 	return (rv);
@@ -375,21 +384,20 @@ pfi_table_update(struct pfr_ktable *kt, 
 	struct pfi_kif		*p;
 	struct pfr_table	 t;
 
-	if ((kif->pfik_flags & PFI_IFLAG_INSTANCE) && kif->pfik_ifp == NULL) {
+	if (kif->pfik_ifp == NULL) {
 		pfr_clr_addrs(&kt->pfrkt_t, NULL, 0);
 		return;
 	}
 	pfi_buffer_cnt = 0;
-	if ((kif->pfik_flags & PFI_IFLAG_INSTANCE))
+
+	/* XXXXXX bugs bugs bugs ? */
+	if (kif->pfik_ifp != NULL)
 		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 {
+	else
 		RB_FOREACH(p, pfi_ifhead, &pfi_ifs)
-			if (p->pfik_flags & PFI_IFLAG_INSTANCE)
+			if (p->pfik_ifp != NULL)
 				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,
@@ -515,7 +523,7 @@ pfi_dynaddr_remove(struct pf_addr_wrap *
 	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);
+	pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE);
 	aw->p.dyn->pfid_kif = NULL;
 	pfr_detach_table(aw->p.dyn->pfid_kt);
 	aw->p.dyn->pfid_kt = NULL;
@@ -539,8 +547,7 @@ pfi_kifaddr_update(void *v)
 	int		 s;
 
 	s = splsoftnet();
-	pfi_update++;
-	pfi_dohooks(v);
+	dohooks(((struct pfi_kif *)v)->pfik_ah_head, 0);
 	splx(s);
 }
 
@@ -550,98 +557,6 @@ pfi_if_compare(struct pfi_kif *p, struct
 	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_second;
-
-	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->pfik_ah_head, PFI_MTYPE);
-	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_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)
 {
@@ -669,76 +584,33 @@ pfi_fill_oldstatus(struct pf_status *pfs
 }
 
 int
-pfi_clr_istats(const char *name, int *nzero, int flags)
+pfi_clr_istats(const char *name)
 {
 	struct pfi_kif	*p;
-	int		 n = 0, s;
-	long		 tzero = time_second;
+	int		 s;
 
-	ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE);
 	s = splsoftnet();
 	RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
-		if (pfi_skip_if(name, p, flags))
+		if (pfi_skip_if(name, p))
 			continue;
 		bzero(p->pfik_packets, sizeof(p->pfik_packets));
 		bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
-		p->pfik_tzero = tzero;
-		n++;
+		p->pfik_tzero = time_second;
 	}
 	splx(s);
-	if (nzero != NULL)
-		*nzero = n;
-	return (0);
-}
 
-int
-pfi_set_flags(const char *name, int flags)
-{
-	struct pfi_kif	*p;
-	int		 s;
-
-	if (flags & ~PFI_IFLAG_SETABLE_MASK)
-		return (EINVAL);
-
-	s = splsoftnet();
-	RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
-		if (pfi_skip_if(name, p, PFI_FLAG_GROUP|PFI_FLAG_INSTANCE))
-			continue;
-		p->pfik_flags |= flags;
-	}
-	splx(s);
-	return (0);
-}
-
-int
-pfi_clear_flags(const char *name, int flags)
-{
-	struct pfi_kif	*p;
-	int		 s;
-
-	if (flags & ~PFI_IFLAG_SETABLE_MASK)
-		return (EINVAL);
-
-	s = splsoftnet();
-	RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
-		if (pfi_skip_if(name, p, PFI_FLAG_GROUP|PFI_FLAG_INSTANCE))
-			continue;
-		p->pfik_flags &= ~flags;
-	}
-	splx(s);
 	return (0);
 }
 
 int
-pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags)
+pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
 {
 	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))
+		if (pfi_skip_if(name, p))
 			continue;
 		if (*size > n++) {
 			if (!p->pfik_tzero)
@@ -754,25 +626,11 @@ pfi_get_ifaces(const char *name, struct 
 	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)
+pfi_skip_if(const char *filter, struct pfi_kif *p)
 {
 	int	n;
 
-	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);
 	if (!strcmp(p->pfik_name, filter))
@@ -787,6 +645,38 @@ pfi_skip_if(const char *filter, struct p
 	return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9');
 }
 
+int
+pfi_set_flags(const char *name, int flags)
+{
+	struct pfi_kif	*p;
+	int		 s;
+
+	s = splsoftnet();
+	RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+		if (pfi_skip_if(name, p))
+			continue;
+		p->pfik_flags |= flags;
+	}
+	splx(s);
+	return (0);
+}
+
+int
+pfi_clear_flags(const char *name, int flags)
+{
+	struct pfi_kif	*p;
+	int		 s;
+
+	s = splsoftnet();
+	RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+		if (pfi_skip_if(name, p))
+			continue;
+		p->pfik_flags &= ~flags;
+	}
+	splx(s);
+	return (0);
+}
+
 /* from pf_print_state.c */
 int
 pfi_unmask(void *addr)
@@ -807,44 +697,3 @@ pfi_unmask(void *addr)
 	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)
-{
-	switch (af) {
-#ifdef INET
-	case AF_INET:
-		switch (dyn->pfid_acnt4) {
-		case 0:
-			return (0);
-		case 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));
-		}
-		break;
-#endif /* INET */
-#ifdef INET6
-	case AF_INET6:
-		switch (dyn->pfid_acnt6) {
-		case 0:
-			return (0);
-		case 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));
-		}
-		break;
-#endif /* INET6 */
-	default:
-		return (0);
-	}
-}
Index: sys/net/pf_ioctl.c
===================================================================
RCS file: /cvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.140
diff -u -p -r1.140 pf_ioctl.c
--- sys/net/pf_ioctl.c	10 May 2005 13:15:15 -0000	1.140
+++ sys/net/pf_ioctl.c	16 May 2005 16:26:34 -0000
@@ -560,7 +560,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);
+		pfi_kif_unref(empty_pool_pa->kif, PFI_KIF_REF_RULE);
 		TAILQ_REMOVE(poola, empty_pool_pa, entries);
 		pool_put(&pf_pooladdr_pl, empty_pool_pa);
 	}
@@ -606,7 +606,7 @@ pf_rm_rule(struct pf_rulequeue *rulequeu
 		if (rule->overload_tbl)
 			pfr_detach_table(rule->overload_tbl);
 	}
-	pfi_detach_rule(rule->kif);
+	pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE);
 	pf_anchor_remove(rule);
 	pf_empty_pool(&rule->rpool.list);
 	pool_put(&pf_rule_pl, rule);
@@ -1039,7 +1039,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 		case DIOCGETSRCNODES:
 		case DIOCCLRSRCNODES:
 		case DIOCIGETIFACES:
-		case DIOCICLRISTATS:
 		case DIOCSETIFFLAG:
 		case DIOCCLRIFFLAG:
 			break;
@@ -1188,12 +1187,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 		else
 			rule->nr = 0;
 		if (rule->ifname[0]) {
-			rule->kif = pfi_attach_rule(rule->ifname);
+			rule->kif = pfi_kif_get(rule->ifname);
 			if (rule->kif == NULL) {
 				pool_put(&pf_rule_pl, rule);
 				error = EINVAL;
 				break;
 			}
+			pfi_kif_ref(rule->kif, PFI_KIF_REF_RULE);
 		}
 
 #ifdef ALTQ
@@ -1408,12 +1408,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 			}
 #endif /* INET6 */
 			if (newrule->ifname[0]) {
-				newrule->kif = pfi_attach_rule(newrule->ifname);
+				newrule->kif = pfi_kif_get(newrule->ifname);
 				if (newrule->kif == NULL) {
 					pool_put(&pf_rule_pl, newrule);
 					error = EINVAL;
 					break;
 				}
+				pfi_kif_ref(newrule->kif, PFI_KIF_REF_RULE);
 			} else
 				newrule->kif = NULL;
 
@@ -1616,7 +1617,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 			error = ENOMEM;
 			break;
 		}
-		kif = pfi_lookup_create(ps->state.u.ifname);
+		kif = pfi_kif_get(ps->state.u.ifname);
 		if (kif == NULL) {
 			pool_put(&pf_state_pl, state);
 			error = ENOENT;
@@ -1634,7 +1635,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 		state->bytes[0] = state->bytes[1] = 0;
 
 		if (pf_insert_state(kif, state)) {
-			pfi_maybe_destroy(kif);
+			pfi_kif_unref(kif, PFI_KIF_REF_NONE);
 			pool_put(&pf_state_pl, state);
 			error = ENOMEM;
 		}
@@ -1745,8 +1746,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 		bzero(pf_status.fcounters, sizeof(pf_status.fcounters));
 		bzero(pf_status.scounters, sizeof(pf_status.scounters));
 		if (*pf_status.ifname)
-			pfi_clr_istats(pf_status.ifname, NULL,
-			    PFI_FLAG_INSTANCE);
+			pfi_clr_istats(pf_status.ifname);
 		break;
 	}
 
@@ -2068,16 +2068,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 		}
 		bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr));
 		if (pa->ifname[0]) {
-			pa->kif = pfi_attach_rule(pa->ifname);
+			pa->kif = pfi_kif_get(pa->ifname);
 			if (pa->kif == NULL) {
 				pool_put(&pf_pooladdr_pl, pa);
 				error = EINVAL;
 				break;
 			}
+			pfi_kif_ref(pa->kif, PFI_KIF_REF_RULE);
 		}
 		if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
 			pfi_dynaddr_remove(&pa->addr);
-			pfi_detach_rule(pa->kif);
+			pfi_kif_unref(pa->kif, PFI_KIF_REF_RULE);
 			pool_put(&pf_pooladdr_pl, pa);
 			error = EINVAL;
 			break;
@@ -2177,18 +2178,19 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 			}
 #endif /* INET6 */
 			if (newpa->ifname[0]) {
-				newpa->kif = pfi_attach_rule(newpa->ifname);
+				newpa->kif = pfi_kif_get(newpa->ifname);
 				if (newpa->kif == NULL) {
 					pool_put(&pf_pooladdr_pl, newpa);
 					error = EINVAL;
 					break;
 				}
+				pfi_kif_ref(newpa->kif, PFI_KIF_REF_RULE);
 			} else
 				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);
+				pfi_kif_unref(newpa->kif, PFI_KIF_REF_RULE);
 				pool_put(&pf_pooladdr_pl, newpa);
 				error = EINVAL;
 				break;
@@ -2217,7 +2219,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 			TAILQ_REMOVE(&pool->list, oldpa, entries);
 			pfi_dynaddr_remove(&oldpa->addr);
 			pf_tbladdr_remove(&oldpa->addr);
-			pfi_detach_rule(oldpa->kif);
+			pfi_kif_unref(oldpa->kif, PFI_KIF_REF_RULE);
 			pool_put(&pf_pooladdr_pl, oldpa);
 		} else {
 			if (oldpa == NULL)
@@ -2771,20 +2773,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
 	case DIOCIGETIFACES: {
 		struct pfioc_iface *io = (struct pfioc_iface *)addr;
 
-		if (io->pfiio_esize != sizeof(struct pfi_if)) {
+		if (io->pfiio_esize != sizeof(struct pfi_kif)) {
 			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);
+		    &io->pfiio_size);
 		break;
 	}
 
Index: sys/net/pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.97
diff -u -p -r1.97 pf_norm.c
--- sys/net/pf_norm.c	21 Sep 2004 16:59:12 -0000	1.97
+++ sys/net/pf_norm.c	16 May 2005 16:26:34 -0000
@@ -831,8 +831,7 @@ pf_normalize_ip(struct mbuf **m0, int di
 	r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
 	while (r != NULL) {
 		r->evaluations++;
-		if (r->kif != NULL &&
-		    (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+		if (pfi_kif_match(r->kif, kif) == !r->ifnot)
 			r = r->skip[PF_SKIP_IFP].ptr;
 		else if (r->direction && r->direction != dir)
 			r = r->skip[PF_SKIP_DIR].ptr;
@@ -1048,8 +1047,7 @@ pf_normalize_ip6(struct mbuf **m0, int d
 	r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
 	while (r != NULL) {
 		r->evaluations++;
-		if (r->kif != NULL &&
-		    (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+		if (pfi_kif_match(r->kif, kif) == !r->ifnot)
 			r = r->skip[PF_SKIP_IFP].ptr;
 		else if (r->direction && r->direction != dir)
 			r = r->skip[PF_SKIP_DIR].ptr;
@@ -1215,8 +1213,7 @@ pf_normalize_tcp(int dir, struct pfi_kif
 	r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
 	while (r != NULL) {
 		r->evaluations++;
-		if (r->kif != NULL &&
-		    (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+		if (pfi_kif_match(r->kif, kif) == !r->ifnot)
 			r = r->skip[PF_SKIP_IFP].ptr;
 		else if (r->direction && r->direction != dir)
 			r = r->skip[PF_SKIP_DIR].ptr;
Index: sys/net/pfvar.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar.h,v
retrieving revision 1.213
diff -u -p -r1.213 pfvar.h
--- sys/net/pfvar.h	3 Mar 2005 07:13:39 -0000	1.213
+++ sys/net/pfvar.h	16 May 2005 16:26:35 -0000
@@ -588,7 +588,6 @@ struct pf_rule {
 
 /* rule flags again */
 #define PFRULE_IFBOUND		0x00010000	/* if-bound */
-#define PFRULE_GRBOUND		0x00020000	/* group-bound */
 
 #define PFSTATE_HIWAT		10000	/* default state table size */
 
@@ -846,53 +845,33 @@ 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;
+	char				 pfik_name[IFNAMSIZ];
+	u_int64_t			 pfik_packets[2][2][2];
+	u_int64_t			 pfik_bytes[2][2][2];
+	u_int32_t			 pfik_tzero;	/* XXX */
+	int				 pfik_flags;
 	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 */
+
+enum pfi_kif_refs {
+	PFI_KIF_REF_NONE,
+	PFI_KIF_REF_STATE,
+	PFI_KIF_REF_RULE
+};
+
 #define PFI_IFLAG_SKIP		0x0100	/* skip filtering on interface */
-#define PFI_IFLAG_SETABLE_MASK	0x0100	/* setable via DIOC{SET,CLR}IFFLAG */
 
 struct pf_pdesc {
 	u_int64_t	 tot_len;	/* Make Mickey money */
@@ -1282,11 +1261,6 @@ struct pfioc_table {
 #define pfrio_setflag	pfrio_size2
 #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;
@@ -1365,7 +1339,6 @@ struct pfioc_iface {
 #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)
 #define DIOCSETIFFLAG	_IOWR('D', 89, struct pfioc_iface)
 #define DIOCCLRIFFLAG	_IOWR('D', 90, struct pfioc_iface)
 
@@ -1387,7 +1360,6 @@ 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 pfi_kif			**pfi_index2kif;
 
 extern u_int32_t		 ticket_altqs_active;
 extern u_int32_t		 ticket_altqs_inactive;
@@ -1513,29 +1485,26 @@ int	pfr_ina_commit(struct pfr_table *, u
 int	pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
 	    int *, u_int32_t, int);
 
+extern struct pfi_statehead	 pfi_statehead;
+extern struct pfi_kif		*pfi_all;
+
 void		 pfi_initialize(void);
-void		 pfi_attach_clone(struct if_clone *);
+struct pfi_kif	*pfi_kif_get(char *);
+void		 pfi_kif_ref(struct pfi_kif *, enum pfi_kif_refs);
+void		 pfi_kif_unref(struct pfi_kif *, enum pfi_kif_refs);
+int		 pfi_kif_match(struct pfi_kif *, struct pfi_kif *);
 void		 pfi_attach_ifnet(struct ifnet *);
 void		 pfi_detach_ifnet(struct ifnet *);
-struct pfi_kif	*pfi_lookup_create(const char *);
-struct pfi_kif	*pfi_lookup_if(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_match_addr(struct pfi_dynaddr *, struct pf_addr *,
+		    sa_family_t);
 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_dynaddr_copyout(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_clr_istats(const char *);
+int		 pfi_get_ifaces(const char *, struct pfi_kif *, int *);
 int		 pfi_set_flags(const char *, int);
 int		 pfi_clear_flags(const char *, 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 *);
Index: sbin/pfctl/parse.y
===================================================================
RCS file: /cvs/src/sbin/pfctl/parse.y,v
retrieving revision 1.483
diff -u -p -r1.483 parse.y
--- sbin/pfctl/parse.y	22 Apr 2005 11:05:36 -0000	1.483
+++ sbin/pfctl/parse.y	16 May 2005 16:26:35 -0000
@@ -410,7 +410,7 @@ typedef struct {
 %token	LOAD
 %token	STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
 %token	MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH
-%token	TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY ROUTE
+%token	TAGGED TAG IFBOUND FLOATING STATEPOLICY ROUTE
 %token	<v.string>		STRING
 %token	<v.i>			PORTBINARY
 %type	<v.interface>		interface if_list if_item_not if_item
@@ -560,10 +560,6 @@ option		: SET OPTIMIZATION STRING		{
 				case PFRULE_IFBOUND:
 					printf("set state-policy if-bound\n");
 					break;
-				case PFRULE_GRBOUND:
-					printf("set state-policy "
-					    "group-bound\n");
-					break;
 				}
 			default_statelock = $3;
 		}
@@ -2836,9 +2832,6 @@ sourcetrack	: SOURCETRACK		{ $$ = PF_SRC
 statelock	: IFBOUND {
 			$$ = PFRULE_IFBOUND;
 		}
-		| GRBOUND {
-			$$ = PFRULE_GRBOUND;
-		}
 		| FLOATING {
 			$$ = 0;
 		}
@@ -4602,7 +4595,6 @@ lookup(char *s)
 		{ "from",		FROM},
 		{ "global",		GLOBAL},
 		{ "group",		GROUP},
-		{ "group-bound",	GRBOUND},
 		{ "hfsc",		HFSC},
 		{ "hostid",		HOSTID},
 		{ "icmp-type",		ICMPTYPE},
Index: sbin/pfctl/pfctl.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl.c,v
retrieving revision 1.235
diff -u -p -r1.235 pfctl.c
--- sbin/pfctl/pfctl.c	5 May 2005 04:00:26 -0000	1.235
+++ sbin/pfctl/pfctl.c	16 May 2005 16:26:36 -0000
@@ -268,7 +268,6 @@ pfctl_clear_interface_flags(int dev, int
 
 	if ((opts & PF_OPT_NOACTION) == 0) {
 		bzero(&pi, sizeof(pi));
-		pi.pfiio_flags = PFI_IFLAG_SETABLE_MASK;
 
 		if (ioctl(dev, DIOCCLRIFFLAG, &pi))
 			err(1, "DIOCCLRIFFLAG");
Index: sbin/pfctl/pfctl.h
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl.h,v
retrieving revision 1.37
diff -u -p -r1.37 pfctl.h
--- sbin/pfctl/pfctl.h	5 Jan 2005 18:23:10 -0000	1.37
+++ sbin/pfctl/pfctl.h	16 May 2005 16:26:36 -0000
@@ -73,7 +73,7 @@ int	 pfr_buf_grow(struct pfr_buffer *, i
 int	 pfr_buf_load(struct pfr_buffer *, char *, int,
 	    int (*)(struct pfr_buffer *, char *, int));
 char	*pfr_strerror(int);
-int	 pfi_get_ifaces(const char *, struct pfi_if *, int *, int);
+int	 pfi_get_ifaces(const char *, struct pfi_kif *, int *);
 int	 pfi_clr_istats(const char *, int *, int);
 
 void	 pfctl_print_title(char *);
Index: sbin/pfctl/pfctl_parser.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_parser.c,v
retrieving revision 1.211
diff -u -p -r1.211 pfctl_parser.c
--- sbin/pfctl/pfctl_parser.c	7 Dec 2004 10:33:41 -0000	1.211
+++ sbin/pfctl/pfctl_parser.c	16 May 2005 16:26:36 -0000
@@ -820,7 +820,7 @@ print_rule(struct pf_rule *r, const char
 		opts = 1;
 	if (r->rule_flag & PFRULE_SRCTRACK)
 		opts = 1;
-	if (r->rule_flag & (PFRULE_IFBOUND | PFRULE_GRBOUND))
+	if (r->rule_flag & PFRULE_IFBOUND)
 		opts = 1;
 	for (i = 0; !opts && i < PFTM_MAX; ++i)
 		if (r->timeout[i])
@@ -886,12 +886,6 @@ print_rule(struct pf_rule *r, const char
 			if (!opts)
 				printf(", ");
 			printf("if-bound");
-			opts = 0;
-		}
-		if (r->rule_flag & PFRULE_GRBOUND) {
-			if (!opts)
-				printf(", ");
-			printf("group-bound");
 			opts = 0;
 		}
 		for (i = 0; i < PFTM_MAX; ++i)
Index: sbin/pfctl/pfctl_radix.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_radix.c,v
retrieving revision 1.26
diff -u -p -r1.26 pfctl_radix.c
--- sbin/pfctl/pfctl_radix.c	14 Jun 2004 20:44:22 -0000	1.26
+++ sbin/pfctl/pfctl_radix.c	16 May 2005 16:26:36 -0000
@@ -421,7 +421,7 @@ pfr_ina_define(struct pfr_table *tbl, st
 /* interface management code */
 
 int
-pfi_get_ifaces(const char *filter, struct pfi_if *buf, int *size, int flags)
+pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
 {
 	struct pfioc_iface io;
 
@@ -430,7 +430,6 @@ pfi_get_ifaces(const char *filter, struc
 		return (-1);
 	}
 	bzero(&io, sizeof io);
-	io.pfiio_flags = flags;
 	if (filter != NULL)
 		if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
 		    sizeof(io.pfiio_name)) {
@@ -451,7 +450,7 @@ pfi_get_ifaces(const char *filter, struc
 size_t buf_esize[PFRB_MAX] = { 0,
 	sizeof(struct pfr_table), sizeof(struct pfr_tstats),
 	sizeof(struct pfr_addr), sizeof(struct pfr_astats),
-	sizeof(struct pfi_if), sizeof(struct pfioc_trans_e)
+	sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
 };
 
 /*
Index: sbin/pfctl/pfctl_table.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_table.c,v
retrieving revision 1.62
diff -u -p -r1.62 pfctl_table.c
--- sbin/pfctl/pfctl_table.c	22 Dec 2004 17:17:55 -0000	1.62
+++ sbin/pfctl/pfctl_table.c	16 May 2005 16:26:36 -0000
@@ -61,8 +61,7 @@ static void	print_addrx(struct pfr_addr 
 static void	print_astats(struct pfr_astats *, int);
 static void	radix_perror(void);
 static void	xprintf(int, const char *, ...);
-static void	print_iface(struct pfi_if *, int);
-static void	oprintf(int, int, const char *, int *, int);
+static void	print_iface(struct pfi_kif *, int);
 
 static const char	*stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = {
 	{ "In/Block:",	"In/Pass:",	"In/XPass:" },
@@ -539,17 +538,15 @@ int
 pfctl_show_ifaces(const char *filter, int opts)
 {
 	struct pfr_buffer	 b;
-	struct pfi_if		*p;
-	int			 i = 0, f = PFI_FLAG_GROUP|PFI_FLAG_INSTANCE;
+	struct pfi_kif		*p;
+	int			 i = 0;
 
-	if (filter != NULL && *filter && !isdigit(filter[strlen(filter)-1]))
-		f &= ~PFI_FLAG_INSTANCE;
 	bzero(&b, sizeof(b));
 	b.pfrb_type = PFRB_IFACES;
 	for (;;) {
 		pfr_buf_grow(&b, b.pfrb_size);
 		b.pfrb_size = b.pfrb_msize;
-		if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size, f)) {
+		if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size)) {
 			radix_perror();
 			return (1);
 		}
@@ -565,46 +562,26 @@ pfctl_show_ifaces(const char *filter, in
 }
 
 void
-print_iface(struct pfi_if *p, int opts)
+print_iface(struct pfi_kif *p, int opts)
 {
-	time_t	tzero = p->pfif_tzero;
-	int	flags = (opts & PF_OPT_VERBOSE) ? p->pfif_flags : 0;
-	int	first = 1;
+	time_t	tzero = p->pfik_tzero;
 	int	i, af, dir, act;
 
-	printf("%s", p->pfif_name);
-	oprintf(flags, PFI_IFLAG_INSTANCE, "instance", &first, 0);
-	oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0);
-	oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0);
-	oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0);
-	oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 0);
-	oprintf(flags, PFI_IFLAG_SKIP, "skipped", &first, 1);
+	printf("%s", p->pfik_name);
 	printf("\n");
 
 	if (!(opts & PF_OPT_VERBOSE2))
 		return;
 	printf("\tCleared:     %s", ctime(&tzero));
 	printf("\tReferences:  [ States:  %-18d Rules: %-18d ]\n",
-	    p->pfif_states, p->pfif_rules);
+	    p->pfik_states, p->pfik_rules);
 	for (i = 0; i < 8; i++) {
 		af = (i>>2) & 1;
 		dir = (i>>1) &1;
 		act = i & 1;
 		printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
 		    istats_text[af][dir][act],
-		    (unsigned long long)p->pfif_packets[af][dir][act],
-		    (unsigned long long)p->pfif_bytes[af][dir][act]);
+		    (unsigned long long)p->pfik_packets[af][dir][act],
+		    (unsigned long long)p->pfik_bytes[af][dir][act]);
 	}
 }
-
-void
-oprintf(int flags, int flag, const char *s, int *first, int last)
-{
-	if (flags & flag) {
-		printf(*first ? "\t(%s" : ", %s", s);
-		*first = 0;
-	}
-	if (last && !*first)
-		printf(")");
-}
-