xref: /freebsd/sys/netpfil/ipfilter/netinet/ip_pool.c (revision cde9ec6a)
13b9b51feSCy Schubert /*
23b9b51feSCy Schubert  * Copyright (C) 2012 by Darren Reed.
33b9b51feSCy Schubert  *
43b9b51feSCy Schubert  * See the IPFILTER.LICENCE file for details on licencing.
53b9b51feSCy Schubert  */
63b9b51feSCy Schubert #if defined(KERNEL) || defined(_KERNEL)
73b9b51feSCy Schubert # undef KERNEL
83b9b51feSCy Schubert # undef _KERNEL
93b9b51feSCy Schubert # define        KERNEL	1
103b9b51feSCy Schubert # define        _KERNEL	1
113b9b51feSCy Schubert #endif
123b9b51feSCy Schubert #include <sys/errno.h>
133b9b51feSCy Schubert #include <sys/types.h>
143b9b51feSCy Schubert #include <sys/param.h>
153b9b51feSCy Schubert #include <sys/file.h>
163b9b51feSCy Schubert #if !defined(_KERNEL) && !defined(__KERNEL__)
173b9b51feSCy Schubert # include <stdio.h>
183b9b51feSCy Schubert # include <stdlib.h>
193b9b51feSCy Schubert # include <string.h>
203b9b51feSCy Schubert # define _KERNEL
213b9b51feSCy Schubert # include <sys/uio.h>
223b9b51feSCy Schubert # undef _KERNEL
233b9b51feSCy Schubert #else
243b9b51feSCy Schubert # include <sys/systm.h>
253b9b51feSCy Schubert # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
263b9b51feSCy Schubert #  include <sys/proc.h>
273b9b51feSCy Schubert # endif
283b9b51feSCy Schubert #endif
293b9b51feSCy Schubert #include <sys/time.h>
303b9b51feSCy Schubert #if defined(_KERNEL) && !defined(SOLARIS2)
313b9b51feSCy Schubert # include <sys/mbuf.h>
323b9b51feSCy Schubert #endif
333b9b51feSCy Schubert #if defined(__SVR4)
343b9b51feSCy Schubert # include <sys/byteorder.h>
353b9b51feSCy Schubert # ifdef _KERNEL
363b9b51feSCy Schubert #  include <sys/dditypes.h>
373b9b51feSCy Schubert # endif
383b9b51feSCy Schubert # include <sys/stream.h>
393b9b51feSCy Schubert # include <sys/kmem.h>
403b9b51feSCy Schubert #endif
413b9b51feSCy Schubert #if defined(__FreeBSD__)
423b9b51feSCy Schubert # include <sys/malloc.h>
433b9b51feSCy Schubert #endif
443b9b51feSCy Schubert 
453b9b51feSCy Schubert #include <sys/socket.h>
463b9b51feSCy Schubert #include <net/if.h>
473b9b51feSCy Schubert #include <netinet/in.h>
483b9b51feSCy Schubert #if !defined(_KERNEL)
493b9b51feSCy Schubert # include "ipf.h"
503b9b51feSCy Schubert #endif
513b9b51feSCy Schubert 
523b9b51feSCy Schubert #include "netinet/ip_compat.h"
533b9b51feSCy Schubert #include "netinet/ip_fil.h"
543b9b51feSCy Schubert #include "netinet/ip_pool.h"
553b9b51feSCy Schubert #include "netinet/radix_ipf.h"
563b9b51feSCy Schubert 
573b9b51feSCy Schubert /* END OF INCLUDES */
583b9b51feSCy Schubert 
593b9b51feSCy Schubert 
603b9b51feSCy Schubert typedef struct ipf_pool_softc_s {
613b9b51feSCy Schubert 	void		*ipf_radix;
623b9b51feSCy Schubert 	ip_pool_t	*ipf_pool_list[LOOKUP_POOL_SZ];
633b9b51feSCy Schubert 	ipf_pool_stat_t	ipf_pool_stats;
643b9b51feSCy Schubert 	ip_pool_node_t	*ipf_node_explist;
653b9b51feSCy Schubert } ipf_pool_softc_t;
663b9b51feSCy Schubert 
673b9b51feSCy Schubert 
683b9b51feSCy Schubert static void ipf_pool_clearnodes(ipf_main_softc_t *, ipf_pool_softc_t *,
693b9b51feSCy Schubert 				     ip_pool_t *);
703b9b51feSCy Schubert static int ipf_pool_create(ipf_main_softc_t *, ipf_pool_softc_t *, iplookupop_t *);
713b9b51feSCy Schubert static int ipf_pool_deref(ipf_main_softc_t *, void *, void *);
723b9b51feSCy Schubert static int ipf_pool_destroy(ipf_main_softc_t *, ipf_pool_softc_t *, int, char *);
733b9b51feSCy Schubert static void *ipf_pool_exists(ipf_pool_softc_t *, int, char *);
743b9b51feSCy Schubert static void *ipf_pool_find(void *, int, char *);
753b9b51feSCy Schubert static ip_pool_node_t *ipf_pool_findeq(ipf_pool_softc_t *, ip_pool_t *,
763b9b51feSCy Schubert 					    addrfamily_t *, addrfamily_t *);
773b9b51feSCy Schubert static void ipf_pool_free(ipf_main_softc_t *, ipf_pool_softc_t *,
783b9b51feSCy Schubert 			       ip_pool_t *);
793b9b51feSCy Schubert static int ipf_pool_insert_node(ipf_main_softc_t *, ipf_pool_softc_t *,
803b9b51feSCy Schubert 				     ip_pool_t *, struct ip_pool_node *);
813b9b51feSCy Schubert static int ipf_pool_iter_deref(ipf_main_softc_t *, void *, int, int, void *);
823b9b51feSCy Schubert static int ipf_pool_iter_next(ipf_main_softc_t *,  void *, ipftoken_t *,
833b9b51feSCy Schubert 				   ipflookupiter_t *);
843b9b51feSCy Schubert static size_t ipf_pool_flush(ipf_main_softc_t *, void *, iplookupflush_t *);
853b9b51feSCy Schubert static int ipf_pool_node_add(ipf_main_softc_t *, void *, iplookupop_t *,
863b9b51feSCy Schubert 				  int);
873b9b51feSCy Schubert static int ipf_pool_node_del(ipf_main_softc_t *, void *, iplookupop_t *,
883b9b51feSCy Schubert 				  int);
893b9b51feSCy Schubert static void ipf_pool_node_deref(ipf_pool_softc_t *, ip_pool_node_t *);
903b9b51feSCy Schubert static int ipf_pool_remove_node(ipf_main_softc_t *, ipf_pool_softc_t *,
913b9b51feSCy Schubert 				     ip_pool_t *, ip_pool_node_t *);
923b9b51feSCy Schubert static int ipf_pool_search(ipf_main_softc_t *, void *, int,
933b9b51feSCy Schubert 				void *, u_int);
943b9b51feSCy Schubert static void *ipf_pool_soft_create(ipf_main_softc_t *);
953b9b51feSCy Schubert static void ipf_pool_soft_destroy(ipf_main_softc_t *, void *);
963b9b51feSCy Schubert static void ipf_pool_soft_fini(ipf_main_softc_t *, void *);
973b9b51feSCy Schubert static int ipf_pool_soft_init(ipf_main_softc_t *, void *);
983b9b51feSCy Schubert static int ipf_pool_stats_get(ipf_main_softc_t *, void *, iplookupop_t *);
993b9b51feSCy Schubert static int ipf_pool_table_add(ipf_main_softc_t *, void *, iplookupop_t *);
1003b9b51feSCy Schubert static int ipf_pool_table_del(ipf_main_softc_t *, void *, iplookupop_t *);
1013b9b51feSCy Schubert static void *ipf_pool_select_add_ref(void *, int, char *);
1023b9b51feSCy Schubert static void ipf_pool_expire(ipf_main_softc_t *, void *);
1033b9b51feSCy Schubert 
1043b9b51feSCy Schubert ipf_lookup_t ipf_pool_backend = {
1053b9b51feSCy Schubert 	IPLT_POOL,
1063b9b51feSCy Schubert 	ipf_pool_soft_create,
1073b9b51feSCy Schubert 	ipf_pool_soft_destroy,
1083b9b51feSCy Schubert 	ipf_pool_soft_init,
1093b9b51feSCy Schubert 	ipf_pool_soft_fini,
1103b9b51feSCy Schubert 	ipf_pool_search,
1113b9b51feSCy Schubert 	ipf_pool_flush,
1123b9b51feSCy Schubert 	ipf_pool_iter_deref,
1133b9b51feSCy Schubert 	ipf_pool_iter_next,
1143b9b51feSCy Schubert 	ipf_pool_node_add,
1153b9b51feSCy Schubert 	ipf_pool_node_del,
1163b9b51feSCy Schubert 	ipf_pool_stats_get,
1173b9b51feSCy Schubert 	ipf_pool_table_add,
1183b9b51feSCy Schubert 	ipf_pool_table_del,
1193b9b51feSCy Schubert 	ipf_pool_deref,
1203b9b51feSCy Schubert 	ipf_pool_find,
1213b9b51feSCy Schubert 	ipf_pool_select_add_ref,
1223b9b51feSCy Schubert 	NULL,
1233b9b51feSCy Schubert 	ipf_pool_expire,
1243b9b51feSCy Schubert 	NULL
1253b9b51feSCy Schubert };
1263b9b51feSCy Schubert 
1273b9b51feSCy Schubert 
1283b9b51feSCy Schubert #ifdef TEST_POOL
1293b9b51feSCy Schubert void treeprint(ip_pool_t *);
1303b9b51feSCy Schubert 
1313b9b51feSCy Schubert int
main(int argc,char * argv[])132064a5a95SCy Schubert main(int argc, char *argv[])
1333b9b51feSCy Schubert {
1343b9b51feSCy Schubert 	ip_pool_node_t node;
1353b9b51feSCy Schubert 	addrfamily_t a, b;
1363b9b51feSCy Schubert 	iplookupop_t op;
1373b9b51feSCy Schubert 	ip_pool_t *ipo;
1383b9b51feSCy Schubert 	i6addr_t ip;
1393b9b51feSCy Schubert 
1403b9b51feSCy Schubert 	RWLOCK_INIT(softc->ipf_poolrw, "poolrw");
1413b9b51feSCy Schubert 	ipf_pool_init();
1423b9b51feSCy Schubert 
1433b9b51feSCy Schubert 	bzero((char *)&ip, sizeof(ip));
1443b9b51feSCy Schubert 	bzero((char *)&op, sizeof(op));
1453b9b51feSCy Schubert 	bzero((char *)&node, sizeof(node));
1463b9b51feSCy Schubert 	strcpy(op.iplo_name, "0");
1473b9b51feSCy Schubert 
1483b9b51feSCy Schubert 	if (ipf_pool_create(&op) == 0)
1493b9b51feSCy Schubert 		ipo = ipf_pool_exists(0, "0");
1503b9b51feSCy Schubert 
1513b9b51feSCy Schubert 	node.ipn_addr.adf_family = AF_INET;
1523b9b51feSCy Schubert 
1533b9b51feSCy Schubert 	node.ipn_addr.adf_addr.in4.s_addr = 0x0a010203;
1543b9b51feSCy Schubert 	node.ipn_mask.adf_addr.in4.s_addr = 0xffffffff;
1553b9b51feSCy Schubert 	node.ipn_info = 1;
1563b9b51feSCy Schubert 	ipf_pool_insert_node(ipo, &node);
1573b9b51feSCy Schubert 
1583b9b51feSCy Schubert 	node.ipn_addr.adf_addr.in4.s_addr = 0x0a000000;
1593b9b51feSCy Schubert 	node.ipn_mask.adf_addr.in4.s_addr = 0xff000000;
1603b9b51feSCy Schubert 	node.ipn_info = 0;
1613b9b51feSCy Schubert 	ipf_pool_insert_node(ipo, &node);
1623b9b51feSCy Schubert 
1633b9b51feSCy Schubert 	node.ipn_addr.adf_addr.in4.s_addr = 0x0a010100;
1643b9b51feSCy Schubert 	node.ipn_mask.adf_addr.in4.s_addr = 0xffffff00;
1653b9b51feSCy Schubert 	node.ipn_info = 1;
1663b9b51feSCy Schubert 	ipf_pool_insert_node(ipo, &node);
1673b9b51feSCy Schubert 
1683b9b51feSCy Schubert 	node.ipn_addr.adf_addr.in4.s_addr = 0x0a010200;
1693b9b51feSCy Schubert 	node.ipn_mask.adf_addr.in4.s_addr = 0xffffff00;
1703b9b51feSCy Schubert 	node.ipn_info = 0;
1713b9b51feSCy Schubert 	ipf_pool_insert_node(ipo, &node);
1723b9b51feSCy Schubert 
1733b9b51feSCy Schubert 	node.ipn_addr.adf_addr.in4.s_addr = 0x0a010000;
1743b9b51feSCy Schubert 	node.ipn_mask.adf_addr.in4.s_addr = 0xffff0000;
1753b9b51feSCy Schubert 	node.ipn_info = 1;
1763b9b51feSCy Schubert 	ipf_pool_insert_node(ipo, &node);
1773b9b51feSCy Schubert 
1783b9b51feSCy Schubert 	node.ipn_addr.adf_addr.in4.s_addr = 0x0a01020f;
1793b9b51feSCy Schubert 	node.ipn_mask.adf_addr.in4.s_addr = 0xffffffff;
1803b9b51feSCy Schubert 	node.ipn_info = 1;
1813b9b51feSCy Schubert 	ipf_pool_insert_node(ipo, &node);
1823b9b51feSCy Schubert #ifdef	DEBUG_POOL
1833b9b51feSCy Schubert 	treeprint(ipo);
1843b9b51feSCy Schubert #endif
1853b9b51feSCy Schubert 	ip.in4.s_addr = 0x0a00aabb;
1863b9b51feSCy Schubert 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
1873b9b51feSCy Schubert 		ipf_pool_search(ipo, 4, &ip, 1));
1883b9b51feSCy Schubert 
1893b9b51feSCy Schubert 	ip.in4.s_addr = 0x0a000001;
1903b9b51feSCy Schubert 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
1913b9b51feSCy Schubert 		ipf_pool_search(ipo, 4, &ip, 1));
1923b9b51feSCy Schubert 
1933b9b51feSCy Schubert 	ip.in4.s_addr = 0x0a000101;
1943b9b51feSCy Schubert 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
1953b9b51feSCy Schubert 		ipf_pool_search(ipo, 4, &ip, 1));
1963b9b51feSCy Schubert 
1973b9b51feSCy Schubert 	ip.in4.s_addr = 0x0a010001;
1983b9b51feSCy Schubert 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
1993b9b51feSCy Schubert 		ipf_pool_search(ipo, 4, &ip, 1));
2003b9b51feSCy Schubert 
2013b9b51feSCy Schubert 	ip.in4.s_addr = 0x0a010101;
2023b9b51feSCy Schubert 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
2033b9b51feSCy Schubert 		ipf_pool_search(ipo, 4, &ip, 1));
2043b9b51feSCy Schubert 
2053b9b51feSCy Schubert 	ip.in4.s_addr = 0x0a010201;
2063b9b51feSCy Schubert 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
2073b9b51feSCy Schubert 		ipf_pool_search(ipo, 4, &ip, 1));
2083b9b51feSCy Schubert 
2093b9b51feSCy Schubert 	ip.in4.s_addr = 0x0a010203;
2103b9b51feSCy Schubert 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
2113b9b51feSCy Schubert 		ipf_pool_search(ipo, 4, &ip, 1));
2123b9b51feSCy Schubert 
2133b9b51feSCy Schubert 	ip.in4.s_addr = 0x0a01020f;
2143b9b51feSCy Schubert 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
2153b9b51feSCy Schubert 		ipf_pool_search(ipo, 4, &ip, 1));
2163b9b51feSCy Schubert 
2173b9b51feSCy Schubert 	ip.in4.s_addr = 0x0b00aabb;
2183b9b51feSCy Schubert 	printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
2193b9b51feSCy Schubert 		ipf_pool_search(ipo, 4, &ip, 1));
2203b9b51feSCy Schubert 
2213b9b51feSCy Schubert #ifdef	DEBUG_POOL
2223b9b51feSCy Schubert 	treeprint(ipo);
2233b9b51feSCy Schubert #endif
2243b9b51feSCy Schubert 
2253b9b51feSCy Schubert 	ipf_pool_fini();
2263b9b51feSCy Schubert 
2278c82b374SCy Schubert 	return (0);
2283b9b51feSCy Schubert }
2293b9b51feSCy Schubert 
2303b9b51feSCy Schubert 
2313b9b51feSCy Schubert void
treeprint(ip_pool_t * ipo)232064a5a95SCy Schubert treeprint(ip_pool_t *ipo)
2333b9b51feSCy Schubert {
2343b9b51feSCy Schubert 	ip_pool_node_t *c;
2353b9b51feSCy Schubert 
2363b9b51feSCy Schubert 	for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
2373b9b51feSCy Schubert 		printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
2383b9b51feSCy Schubert 			c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
2393b9b51feSCy Schubert 			c->ipn_mask.adf_addr.in4.s_addr,
2403b9b51feSCy Schubert 			c->ipn_info, c->ipn_hits);
2413b9b51feSCy Schubert }
2423b9b51feSCy Schubert #endif /* TEST_POOL */
2433b9b51feSCy Schubert 
2443b9b51feSCy Schubert 
2453b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
2463b9b51feSCy Schubert /* Function:    ipf_pool_soft_create                                        */
2473b9b51feSCy Schubert /* Returns:     void *   - NULL = failure, else pointer to local context    */
2483b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
2493b9b51feSCy Schubert /*                                                                          */
2503b9b51feSCy Schubert /* Initialise the routing table data structures where required.             */
2513b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
2523b9b51feSCy Schubert static void *
ipf_pool_soft_create(ipf_main_softc_t * softc)253064a5a95SCy Schubert ipf_pool_soft_create(ipf_main_softc_t *softc)
2543b9b51feSCy Schubert {
2553b9b51feSCy Schubert 	ipf_pool_softc_t *softp;
2563b9b51feSCy Schubert 
2573b9b51feSCy Schubert 	KMALLOC(softp, ipf_pool_softc_t *);
2583b9b51feSCy Schubert 	if (softp == NULL) {
2593b9b51feSCy Schubert 		IPFERROR(70032);
2608c82b374SCy Schubert 		return (NULL);
2613b9b51feSCy Schubert 	}
2623b9b51feSCy Schubert 
2633b9b51feSCy Schubert 	bzero((char *)softp, sizeof(*softp));
2643b9b51feSCy Schubert 
2653b9b51feSCy Schubert 	softp->ipf_radix = ipf_rx_create();
2663b9b51feSCy Schubert 	if (softp->ipf_radix == NULL) {
2673b9b51feSCy Schubert 		IPFERROR(70033);
2683b9b51feSCy Schubert 		KFREE(softp);
2698c82b374SCy Schubert 		return (NULL);
2703b9b51feSCy Schubert 	}
2713b9b51feSCy Schubert 
2728c82b374SCy Schubert 	return (softp);
2733b9b51feSCy Schubert }
2743b9b51feSCy Schubert 
2753b9b51feSCy Schubert 
2763b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
2773b9b51feSCy Schubert /* Function:    ipf_pool_soft_init                                          */
2783b9b51feSCy Schubert /* Returns:     int     - 0 = success, else error                           */
2793b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
2803b9b51feSCy Schubert /*              arg(I)   - pointer to local context to use                  */
2813b9b51feSCy Schubert /*                                                                          */
2823b9b51feSCy Schubert /* Initialise the routing table data structures where required.             */
2833b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
2843b9b51feSCy Schubert static int
ipf_pool_soft_init(ipf_main_softc_t * softc,void * arg)285064a5a95SCy Schubert ipf_pool_soft_init(ipf_main_softc_t *softc, void *arg)
2863b9b51feSCy Schubert {
2873b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
2883b9b51feSCy Schubert 
2893b9b51feSCy Schubert 	ipf_rx_init(softp->ipf_radix);
2903b9b51feSCy Schubert 
2918c82b374SCy Schubert 	return (0);
2923b9b51feSCy Schubert }
2933b9b51feSCy Schubert 
2943b9b51feSCy Schubert 
2953b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
2963b9b51feSCy Schubert /* Function:    ipf_pool_soft_fini                                          */
2973b9b51feSCy Schubert /* Returns:     Nil                                                         */
2983b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
2993b9b51feSCy Schubert /*              arg(I)   - pointer to local context to use                  */
3003b9b51feSCy Schubert /* Locks:       WRITE(ipf_global)                                           */
3013b9b51feSCy Schubert /*                                                                          */
3023b9b51feSCy Schubert /* Clean up all the pool data structures allocated and call the cleanup     */
3033b9b51feSCy Schubert /* function for the radix tree that supports the pools. ipf_pool_destroy is */
3043b9b51feSCy Schubert /* used to delete the pools one by one to ensure they're properly freed up. */
3053b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
3063b9b51feSCy Schubert static void
ipf_pool_soft_fini(ipf_main_softc_t * softc,void * arg)307064a5a95SCy Schubert ipf_pool_soft_fini(ipf_main_softc_t *softc, void *arg)
3083b9b51feSCy Schubert {
3093b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
3103b9b51feSCy Schubert 	ip_pool_t *p, *q;
3113b9b51feSCy Schubert 	int i;
3123b9b51feSCy Schubert 
3133b9b51feSCy Schubert 	softc = arg;
3143b9b51feSCy Schubert 
3153b9b51feSCy Schubert 	for (i = -1; i <= IPL_LOGMAX; i++) {
3163b9b51feSCy Schubert 		for (q = softp->ipf_pool_list[i + 1]; (p = q) != NULL; ) {
3173b9b51feSCy Schubert 			q = p->ipo_next;
3183b9b51feSCy Schubert 			(void) ipf_pool_destroy(softc, arg, i, p->ipo_name);
3193b9b51feSCy Schubert 		}
3203b9b51feSCy Schubert 	}
3213b9b51feSCy Schubert }
3223b9b51feSCy Schubert 
3233b9b51feSCy Schubert 
3243b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
3253b9b51feSCy Schubert /* Function:    ipf_pool_soft_destroy                                       */
3263b9b51feSCy Schubert /* Returns:     Nil                                                         */
3273b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
3283b9b51feSCy Schubert /*              arg(I)   - pointer to local context to use                  */
3293b9b51feSCy Schubert /*                                                                          */
3303b9b51feSCy Schubert /* Clean up the pool by free'ing the radix tree associated with it and free */
3313b9b51feSCy Schubert /* up the pool context too.                                                 */
3323b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
3333b9b51feSCy Schubert static void
ipf_pool_soft_destroy(ipf_main_softc_t * softc,void * arg)334064a5a95SCy Schubert ipf_pool_soft_destroy(ipf_main_softc_t *softc, void *arg)
3353b9b51feSCy Schubert {
3363b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
3373b9b51feSCy Schubert 
3383b9b51feSCy Schubert 	ipf_rx_destroy(softp->ipf_radix);
3393b9b51feSCy Schubert 
3403b9b51feSCy Schubert 	KFREE(softp);
3413b9b51feSCy Schubert }
3423b9b51feSCy Schubert 
3433b9b51feSCy Schubert 
3443b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
3453b9b51feSCy Schubert /* Function:   ipf_pool_node_add                                            */
3463b9b51feSCy Schubert /* Returns:    int - 0 = success, else error                                */
3473b9b51feSCy Schubert /* Parameters: softc(I) - pointer to soft context main structure            */
3483b9b51feSCy Schubert /*             arg(I)   - pointer to local context to use                   */
3493b9b51feSCy Schubert /*             op(I) - pointer to lookup operatin data                      */
3503b9b51feSCy Schubert /*                                                                          */
3513b9b51feSCy Schubert /* When adding a new node, a check is made to ensure that the address/mask  */
3523b9b51feSCy Schubert /* pair supplied has been appropriately prepared by applying the mask to    */
3533b9b51feSCy Schubert /* the address prior to calling for the pair to be added.                   */
3543b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
3553b9b51feSCy Schubert static int
ipf_pool_node_add(ipf_main_softc_t * softc,void * arg,iplookupop_t * op,int uid)356064a5a95SCy Schubert ipf_pool_node_add(ipf_main_softc_t *softc, void *arg, iplookupop_t *op,
357064a5a95SCy Schubert 	int uid)
3583b9b51feSCy Schubert {
3593b9b51feSCy Schubert 	ip_pool_node_t node, *m;
3603b9b51feSCy Schubert 	ip_pool_t *p;
3613b9b51feSCy Schubert 	int err;
3623b9b51feSCy Schubert 
3633b9b51feSCy Schubert 	if (op->iplo_size != sizeof(node)) {
3643b9b51feSCy Schubert 		IPFERROR(70014);
3658c82b374SCy Schubert 		return (EINVAL);
3663b9b51feSCy Schubert 	}
3673b9b51feSCy Schubert 
3683b9b51feSCy Schubert 	err = COPYIN(op->iplo_struct, &node, sizeof(node));
3693b9b51feSCy Schubert 	if (err != 0) {
3703b9b51feSCy Schubert 		IPFERROR(70015);
3718c82b374SCy Schubert 		return (EFAULT);
3723b9b51feSCy Schubert 	}
3733b9b51feSCy Schubert 
3743b9b51feSCy Schubert 	p = ipf_pool_find(arg, op->iplo_unit, op->iplo_name);
3753b9b51feSCy Schubert 	if (p == NULL) {
3763b9b51feSCy Schubert 		IPFERROR(70017);
3778c82b374SCy Schubert 		return (ESRCH);
3783b9b51feSCy Schubert 	}
3793b9b51feSCy Schubert 
3803b9b51feSCy Schubert 	if (node.ipn_addr.adf_family == AF_INET) {
3813b9b51feSCy Schubert 		if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) +
3823b9b51feSCy Schubert 					     sizeof(struct in_addr)) {
3833b9b51feSCy Schubert 			IPFERROR(70028);
3848c82b374SCy Schubert 			return (EINVAL);
3853b9b51feSCy Schubert 		}
3863b9b51feSCy Schubert 	}
3873b9b51feSCy Schubert #ifdef USE_INET6
3883b9b51feSCy Schubert 	else if (node.ipn_addr.adf_family == AF_INET6) {
3893b9b51feSCy Schubert 		if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) +
3903b9b51feSCy Schubert 					     sizeof(struct in6_addr)) {
3913b9b51feSCy Schubert 			IPFERROR(70034);
3928c82b374SCy Schubert 			return (EINVAL);
3933b9b51feSCy Schubert 		}
3943b9b51feSCy Schubert 	}
3953b9b51feSCy Schubert #endif
3963b9b51feSCy Schubert 	if (node.ipn_mask.adf_len != node.ipn_addr.adf_len) {
3973b9b51feSCy Schubert 		IPFERROR(70029);
3988c82b374SCy Schubert 		return (EINVAL);
3993b9b51feSCy Schubert 	}
4003b9b51feSCy Schubert 
4013b9b51feSCy Schubert 	/*
4023b9b51feSCy Schubert 	 * Check that the address/mask pair works.
4033b9b51feSCy Schubert 	 */
4043b9b51feSCy Schubert 	if (node.ipn_addr.adf_family == AF_INET) {
4053b9b51feSCy Schubert 		if ((node.ipn_addr.adf_addr.in4.s_addr &
4063b9b51feSCy Schubert 		     node.ipn_mask.adf_addr.in4.s_addr) !=
4073b9b51feSCy Schubert 		    node.ipn_addr.adf_addr.in4.s_addr) {
4083b9b51feSCy Schubert 			IPFERROR(70035);
4098c82b374SCy Schubert 			return (EINVAL);
4103b9b51feSCy Schubert 		}
4113b9b51feSCy Schubert 	}
4123b9b51feSCy Schubert #ifdef USE_INET6
4133b9b51feSCy Schubert 	else if (node.ipn_addr.adf_family == AF_INET6) {
4143b9b51feSCy Schubert 		if (IP6_MASKNEQ(&node.ipn_addr.adf_addr.in6,
4153b9b51feSCy Schubert 				&node.ipn_mask.adf_addr.in6,
4163b9b51feSCy Schubert 				&node.ipn_addr.adf_addr.in6)) {
4173b9b51feSCy Schubert 			IPFERROR(70036);
4188c82b374SCy Schubert 			return (EINVAL);
4193b9b51feSCy Schubert 		}
4203b9b51feSCy Schubert 	}
4213b9b51feSCy Schubert #endif
4223b9b51feSCy Schubert 
4233b9b51feSCy Schubert 	/*
4243b9b51feSCy Schubert 	* add an entry to a pool - return an error if it already
4253b9b51feSCy Schubert 	 * exists remove an entry from a pool - if it exists
4263b9b51feSCy Schubert 	 * - in both cases, the pool *must* exist!
4273b9b51feSCy Schubert 	 */
4283b9b51feSCy Schubert 	m = ipf_pool_findeq(arg, p, &node.ipn_addr, &node.ipn_mask);
4293b9b51feSCy Schubert 	if (m != NULL) {
4303b9b51feSCy Schubert 		IPFERROR(70018);
4318c82b374SCy Schubert 		return (EEXIST);
4323b9b51feSCy Schubert 	}
4333b9b51feSCy Schubert 	err = ipf_pool_insert_node(softc, arg, p, &node);
4343b9b51feSCy Schubert 
4358c82b374SCy Schubert 	return (err);
4363b9b51feSCy Schubert }
4373b9b51feSCy Schubert 
4383b9b51feSCy Schubert 
4393b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
4403b9b51feSCy Schubert /* Function:   ipf_pool_node_del                                            */
4413b9b51feSCy Schubert /* Returns:    int - 0 = success, else error                                */
4423b9b51feSCy Schubert /* Parameters: softc(I) - pointer to soft context main structure            */
4433b9b51feSCy Schubert /*             arg(I)   - pointer to local context to use                   */
4443b9b51feSCy Schubert /*             op(I)    - pointer to lookup operatin data                   */
4453b9b51feSCy Schubert /*                                                                          */
4463b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
4473b9b51feSCy Schubert static int
ipf_pool_node_del(ipf_main_softc_t * softc,void * arg,iplookupop_t * op,int uid)448064a5a95SCy Schubert ipf_pool_node_del(ipf_main_softc_t *softc, void *arg, iplookupop_t *op,
449064a5a95SCy Schubert 	int uid)
4503b9b51feSCy Schubert {
4513b9b51feSCy Schubert 	ip_pool_node_t node, *m;
4523b9b51feSCy Schubert 	ip_pool_t *p;
4533b9b51feSCy Schubert 	int err;
4543b9b51feSCy Schubert 
4553b9b51feSCy Schubert 
4563b9b51feSCy Schubert 	if (op->iplo_size != sizeof(node)) {
4573b9b51feSCy Schubert 		IPFERROR(70019);
4588c82b374SCy Schubert 		return (EINVAL);
4593b9b51feSCy Schubert 	}
4603b9b51feSCy Schubert 	node.ipn_uid = uid;
4613b9b51feSCy Schubert 
4623b9b51feSCy Schubert 	err = COPYIN(op->iplo_struct, &node, sizeof(node));
4633b9b51feSCy Schubert 	if (err != 0) {
4643b9b51feSCy Schubert 		IPFERROR(70020);
4658c82b374SCy Schubert 		return (EFAULT);
4663b9b51feSCy Schubert 	}
4673b9b51feSCy Schubert 
4683b9b51feSCy Schubert 	if (node.ipn_addr.adf_family == AF_INET) {
4693b9b51feSCy Schubert 		if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) +
4703b9b51feSCy Schubert 					     sizeof(struct in_addr)) {
4713b9b51feSCy Schubert 			IPFERROR(70030);
4728c82b374SCy Schubert 			return (EINVAL);
4733b9b51feSCy Schubert 		}
4743b9b51feSCy Schubert 	}
4753b9b51feSCy Schubert #ifdef USE_INET6
4763b9b51feSCy Schubert 	else if (node.ipn_addr.adf_family == AF_INET6) {
4773b9b51feSCy Schubert 		if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) +
4783b9b51feSCy Schubert 					     sizeof(struct in6_addr)) {
4793b9b51feSCy Schubert 			IPFERROR(70037);
4808c82b374SCy Schubert 			return (EINVAL);
4813b9b51feSCy Schubert 		}
4823b9b51feSCy Schubert 	}
4833b9b51feSCy Schubert #endif
4843b9b51feSCy Schubert 	if (node.ipn_mask.adf_len != node.ipn_addr.adf_len) {
4853b9b51feSCy Schubert 		IPFERROR(70031);
4868c82b374SCy Schubert 		return (EINVAL);
4873b9b51feSCy Schubert 	}
4883b9b51feSCy Schubert 
4893b9b51feSCy Schubert 	p = ipf_pool_find(arg, op->iplo_unit, op->iplo_name);
4903b9b51feSCy Schubert 	if (p == NULL) {
4913b9b51feSCy Schubert 		IPFERROR(70021);
4928c82b374SCy Schubert 		return (ESRCH);
4933b9b51feSCy Schubert 	}
4943b9b51feSCy Schubert 
4953b9b51feSCy Schubert 	m = ipf_pool_findeq(arg, p, &node.ipn_addr, &node.ipn_mask);
4963b9b51feSCy Schubert 	if (m == NULL) {
4973b9b51feSCy Schubert 		IPFERROR(70022);
4988c82b374SCy Schubert 		return (ENOENT);
4993b9b51feSCy Schubert 	}
5003b9b51feSCy Schubert 
5013b9b51feSCy Schubert 	if ((uid != 0) && (uid != m->ipn_uid)) {
5023b9b51feSCy Schubert 		IPFERROR(70024);
5038c82b374SCy Schubert 		return (EACCES);
5043b9b51feSCy Schubert 	}
5053b9b51feSCy Schubert 
5063b9b51feSCy Schubert 	err = ipf_pool_remove_node(softc, arg, p, m);
5073b9b51feSCy Schubert 
5088c82b374SCy Schubert 	return (err);
5093b9b51feSCy Schubert }
5103b9b51feSCy Schubert 
5113b9b51feSCy Schubert 
5123b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
5133b9b51feSCy Schubert /* Function:   ipf_pool_table_add                                           */
5143b9b51feSCy Schubert /* Returns:    int - 0 = success, else error                                */
5153b9b51feSCy Schubert /* Parameters: softc(I) - pointer to soft context main structure            */
5163b9b51feSCy Schubert /*             arg(I)   - pointer to local context to use                   */
5173b9b51feSCy Schubert /*             op(I)    - pointer to lookup operatin data                   */
5183b9b51feSCy Schubert /*                                                                          */
5193b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
5203b9b51feSCy Schubert static int
ipf_pool_table_add(ipf_main_softc_t * softc,void * arg,iplookupop_t * op)521064a5a95SCy Schubert ipf_pool_table_add(ipf_main_softc_t *softc, void *arg, iplookupop_t *op)
5223b9b51feSCy Schubert {
5233b9b51feSCy Schubert 	int err;
5243b9b51feSCy Schubert 
5253b9b51feSCy Schubert 	if (((op->iplo_arg & LOOKUP_ANON) == 0) &&
5263b9b51feSCy Schubert 	    (ipf_pool_find(arg, op->iplo_unit, op->iplo_name) != NULL)) {
5273b9b51feSCy Schubert 		IPFERROR(70023);
5283b9b51feSCy Schubert 		err = EEXIST;
5293b9b51feSCy Schubert 	} else {
5303b9b51feSCy Schubert 		err = ipf_pool_create(softc, arg, op);
5313b9b51feSCy Schubert 	}
5323b9b51feSCy Schubert 
5338c82b374SCy Schubert 	return (err);
5343b9b51feSCy Schubert }
5353b9b51feSCy Schubert 
5363b9b51feSCy Schubert 
5373b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
5383b9b51feSCy Schubert /* Function:   ipf_pool_table_del                                           */
5393b9b51feSCy Schubert /* Returns:    int - 0 = success, else error                                */
5403b9b51feSCy Schubert /* Parameters: softc(I) - pointer to soft context main structure            */
5413b9b51feSCy Schubert /*             arg(I)   - pointer to local context to use                   */
5423b9b51feSCy Schubert /*             op(I)    - pointer to lookup operatin data                   */
5433b9b51feSCy Schubert /*                                                                          */
5443b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
5453b9b51feSCy Schubert static int
ipf_pool_table_del(ipf_main_softc_t * softc,void * arg,iplookupop_t * op)546064a5a95SCy Schubert ipf_pool_table_del(ipf_main_softc_t *softc, void *arg, iplookupop_t *op)
5473b9b51feSCy Schubert {
5488c82b374SCy Schubert 	return (ipf_pool_destroy(softc, arg, op->iplo_unit, op->iplo_name));
5493b9b51feSCy Schubert }
5503b9b51feSCy Schubert 
5513b9b51feSCy Schubert 
5523b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
5533b9b51feSCy Schubert /* Function:    ipf_pool_statistics                                         */
5543b9b51feSCy Schubert /* Returns:     int      - 0 = success, else error                          */
5553b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
5563b9b51feSCy Schubert /*              arg(I)   - pointer to local context to use                  */
5573b9b51feSCy Schubert /*              op(I)    - pointer to lookup operatin data                  */
5583b9b51feSCy Schubert /*                                                                          */
5593b9b51feSCy Schubert /* Copy the current statistics out into user space, collecting pool list    */
5603b9b51feSCy Schubert /* pointers as appropriate for later use.                                   */
5613b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
5623b9b51feSCy Schubert static int
ipf_pool_stats_get(ipf_main_softc_t * softc,void * arg,iplookupop_t * op)563064a5a95SCy Schubert ipf_pool_stats_get(ipf_main_softc_t *softc, void *arg, iplookupop_t *op)
5643b9b51feSCy Schubert {
5653b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
5663b9b51feSCy Schubert 	ipf_pool_stat_t stats;
5673b9b51feSCy Schubert 	int unit, i, err = 0;
5683b9b51feSCy Schubert 
5693b9b51feSCy Schubert 	if (op->iplo_size != sizeof(ipf_pool_stat_t)) {
5703b9b51feSCy Schubert 		IPFERROR(70001);
5718c82b374SCy Schubert 		return (EINVAL);
5723b9b51feSCy Schubert 	}
5733b9b51feSCy Schubert 
5743b9b51feSCy Schubert 	bcopy((char *)&softp->ipf_pool_stats, (char *)&stats, sizeof(stats));
5753b9b51feSCy Schubert 	unit = op->iplo_unit;
5763b9b51feSCy Schubert 	if (unit == IPL_LOGALL) {
5773b9b51feSCy Schubert 		for (i = 0; i <= LOOKUP_POOL_MAX; i++)
5783b9b51feSCy Schubert 			stats.ipls_list[i] = softp->ipf_pool_list[i];
5793b9b51feSCy Schubert 	} else if (unit >= 0 && unit <= IPL_LOGMAX) {
5803b9b51feSCy Schubert 		unit++;						/* -1 => 0 */
5813b9b51feSCy Schubert 		if (op->iplo_name[0] != '\0')
5823b9b51feSCy Schubert 			stats.ipls_list[unit] = ipf_pool_exists(softp, unit - 1,
5833b9b51feSCy Schubert 								op->iplo_name);
5843b9b51feSCy Schubert 		else
5853b9b51feSCy Schubert 			stats.ipls_list[unit] = softp->ipf_pool_list[unit];
5863b9b51feSCy Schubert 	} else {
5873b9b51feSCy Schubert 		IPFERROR(70025);
5883b9b51feSCy Schubert 		err = EINVAL;
5893b9b51feSCy Schubert 	}
5903b9b51feSCy Schubert 	if (err == 0) {
5913b9b51feSCy Schubert 		err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
5923b9b51feSCy Schubert 		if (err != 0) {
5933b9b51feSCy Schubert 			IPFERROR(70026);
5948c82b374SCy Schubert 			return (EFAULT);
5953b9b51feSCy Schubert 		}
5963b9b51feSCy Schubert 	}
5978c82b374SCy Schubert 	return (0);
5983b9b51feSCy Schubert }
5993b9b51feSCy Schubert 
6003b9b51feSCy Schubert 
6013b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
6023b9b51feSCy Schubert /* Function:    ipf_pool_exists                                             */
6033b9b51feSCy Schubert /* Returns:     int      - 0 = success, else error                          */
6043b9b51feSCy Schubert /* Parameters:  softp(I) - pointer to soft context pool information         */
6053b9b51feSCy Schubert /*              unit(I)  - ipfilter device to which we are working on       */
6063b9b51feSCy Schubert /*              name(I)  - name of the pool                                 */
6073b9b51feSCy Schubert /*                                                                          */
6083b9b51feSCy Schubert /* Find a matching pool inside the collection of pools for a particular     */
6093b9b51feSCy Schubert /* device, indicated by the unit number.                                    */
6103b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
6113b9b51feSCy Schubert static void *
ipf_pool_exists(ipf_pool_softc_t * softp,int unit,char * name)612064a5a95SCy Schubert ipf_pool_exists(ipf_pool_softc_t *softp, int unit, char *name)
6133b9b51feSCy Schubert {
6143b9b51feSCy Schubert 	ip_pool_t *p;
6153b9b51feSCy Schubert 	int i;
6163b9b51feSCy Schubert 
6173b9b51feSCy Schubert 	if (unit == IPL_LOGALL) {
6183b9b51feSCy Schubert 		for (i = 0; i <= LOOKUP_POOL_MAX; i++) {
6193b9b51feSCy Schubert 			for (p = softp->ipf_pool_list[i]; p != NULL;
6203b9b51feSCy Schubert 			     p = p->ipo_next) {
6213b9b51feSCy Schubert 				if (strncmp(p->ipo_name, name,
6223b9b51feSCy Schubert 					    sizeof(p->ipo_name)) == 0)
6233b9b51feSCy Schubert 					break;
6243b9b51feSCy Schubert 			}
6253b9b51feSCy Schubert 			if (p != NULL)
6263b9b51feSCy Schubert 				break;
6273b9b51feSCy Schubert 		}
6283b9b51feSCy Schubert 	} else {
6293b9b51feSCy Schubert 		for (p = softp->ipf_pool_list[unit + 1]; p != NULL;
6303b9b51feSCy Schubert 		     p = p->ipo_next)
6313b9b51feSCy Schubert 			if (strncmp(p->ipo_name, name,
6323b9b51feSCy Schubert 				    sizeof(p->ipo_name)) == 0)
6333b9b51feSCy Schubert 				break;
6343b9b51feSCy Schubert 	}
6358c82b374SCy Schubert 	return (p);
6363b9b51feSCy Schubert }
6373b9b51feSCy Schubert 
6383b9b51feSCy Schubert 
6393b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
6403b9b51feSCy Schubert /* Function:    ipf_pool_find                                               */
6413b9b51feSCy Schubert /* Returns:     int    - 0 = success, else error                            */
6423b9b51feSCy Schubert /* Parameters:  arg(I)  - pointer to local context to use                   */
6433b9b51feSCy Schubert /*              unit(I) - ipfilter device to which we are working on        */
6443b9b51feSCy Schubert /*              name(I)  - name of the pool                                 */
6453b9b51feSCy Schubert /*                                                                          */
6463b9b51feSCy Schubert /* Find a matching pool inside the collection of pools for a particular     */
6473b9b51feSCy Schubert /* device, indicated by the unit number.  If it is marked for deletion then */
6483b9b51feSCy Schubert /* pretend it does not exist.                                               */
6493b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
6503b9b51feSCy Schubert static void *
ipf_pool_find(void * arg,int unit,char * name)651064a5a95SCy Schubert ipf_pool_find(void *arg, int unit, char *name)
6523b9b51feSCy Schubert {
6533b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
6543b9b51feSCy Schubert 	ip_pool_t *p;
6553b9b51feSCy Schubert 
6563b9b51feSCy Schubert 	p = ipf_pool_exists(softp, unit, name);
6573b9b51feSCy Schubert 	if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE))
6588c82b374SCy Schubert 		return (NULL);
6593b9b51feSCy Schubert 
6608c82b374SCy Schubert 	return (p);
6613b9b51feSCy Schubert }
6623b9b51feSCy Schubert 
6633b9b51feSCy Schubert 
6643b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
6653b9b51feSCy Schubert /* Function:    ipf_pool_select_add_ref                                     */
6663b9b51feSCy Schubert /* Returns:     int - 0 = success, else error                               */
6673b9b51feSCy Schubert /* Parameters:  arg(I)  - pointer to local context to use                   */
6683b9b51feSCy Schubert /*              unit(I) - ipfilter device to which we are working on        */
6693b9b51feSCy Schubert /*              name(I)  - name of the pool                                 */
6703b9b51feSCy Schubert /*                                                                          */
6713b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
6723b9b51feSCy Schubert static void *
ipf_pool_select_add_ref(void * arg,int unit,char * name)673064a5a95SCy Schubert ipf_pool_select_add_ref(void *arg, int unit, char *name)
6743b9b51feSCy Schubert {
6753b9b51feSCy Schubert 	ip_pool_t *p;
6763b9b51feSCy Schubert 
6773b9b51feSCy Schubert 	p = ipf_pool_find(arg, -1, name);
6783b9b51feSCy Schubert 	if (p == NULL)
6793b9b51feSCy Schubert 		p = ipf_pool_find(arg, unit, name);
6803b9b51feSCy Schubert 	if (p != NULL) {
6813b9b51feSCy Schubert 		ATOMIC_INC32(p->ipo_ref);
6823b9b51feSCy Schubert 	}
6838c82b374SCy Schubert 	return (p);
6843b9b51feSCy Schubert }
6853b9b51feSCy Schubert 
6863b9b51feSCy Schubert 
6873b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
6883b9b51feSCy Schubert /* Function:    ipf_pool_findeq                                             */
6893b9b51feSCy Schubert /* Returns:     int     - 0 = success, else error                           */
6903b9b51feSCy Schubert /* Parameters:  softp(I) - pointer to soft context pool information         */
6913b9b51feSCy Schubert /*              ipo(I)  - pointer to the pool getting the new node.         */
6923b9b51feSCy Schubert /*              addr(I) - pointer to address information to match on        */
6933b9b51feSCy Schubert /*              mask(I) - pointer to the address mask to match              */
6943b9b51feSCy Schubert /*                                                                          */
6953b9b51feSCy Schubert /* Searches for an exact match of an entry in the pool.                     */
6963b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
6973b9b51feSCy Schubert extern void printhostmask(int, u_32_t *, u_32_t *);
6983b9b51feSCy Schubert static ip_pool_node_t *
ipf_pool_findeq(ipf_pool_softc_t * softp,ip_pool_t * ipo,addrfamily_t * addr,addrfamily_t * mask)699064a5a95SCy Schubert ipf_pool_findeq(ipf_pool_softc_t *softp, ip_pool_t *ipo, addrfamily_t *addr,
700064a5a95SCy Schubert 	addrfamily_t *mask)
7013b9b51feSCy Schubert {
7023b9b51feSCy Schubert 	ipf_rdx_node_t *n;
7033b9b51feSCy Schubert 
7043b9b51feSCy Schubert 	n = ipo->ipo_head->lookup(ipo->ipo_head, addr, mask);
7053b9b51feSCy Schubert 	return (ip_pool_node_t *)n;
7063b9b51feSCy Schubert }
7073b9b51feSCy Schubert 
7083b9b51feSCy Schubert 
7093b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
7103b9b51feSCy Schubert /* Function:    ipf_pool_search                                             */
7113b9b51feSCy Schubert /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve/no match    */
7123b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
7133b9b51feSCy Schubert /*              tptr(I)    - pointer to the pool to search                  */
7143b9b51feSCy Schubert /*              version(I) - IP protocol version (4 or 6)                   */
7153b9b51feSCy Schubert /*              dptr(I)    - pointer to address information                 */
7163b9b51feSCy Schubert /*              bytes(I)   - length of packet                               */
7173b9b51feSCy Schubert /*                                                                          */
7183b9b51feSCy Schubert /* Search the pool for a given address and return a search result.          */
7193b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
7203b9b51feSCy Schubert static int
ipf_pool_search(ipf_main_softc_t * softc,void * tptr,int ipversion,void * dptr,u_int bytes)721064a5a95SCy Schubert ipf_pool_search(ipf_main_softc_t *softc, void *tptr, int ipversion, void *dptr,
722064a5a95SCy Schubert 	u_int bytes)
7233b9b51feSCy Schubert {
7243b9b51feSCy Schubert 	ipf_rdx_node_t *rn;
7253b9b51feSCy Schubert 	ip_pool_node_t *m;
7263b9b51feSCy Schubert 	i6addr_t *addr;
7273b9b51feSCy Schubert 	addrfamily_t v;
7283b9b51feSCy Schubert 	ip_pool_t *ipo;
7293b9b51feSCy Schubert 	int rv;
7303b9b51feSCy Schubert 
7313b9b51feSCy Schubert 	ipo = tptr;
7323b9b51feSCy Schubert 	if (ipo == NULL)
7338c82b374SCy Schubert 		return (-1);
7343b9b51feSCy Schubert 
7353b9b51feSCy Schubert 	rv = 1;
7363b9b51feSCy Schubert 	m = NULL;
7373b9b51feSCy Schubert 	addr = (i6addr_t *)dptr;
7383b9b51feSCy Schubert 	bzero(&v, sizeof(v));
7393b9b51feSCy Schubert 
7403b9b51feSCy Schubert 	if (ipversion == 4) {
7413b9b51feSCy Schubert 		v.adf_family = AF_INET;
7423b9b51feSCy Schubert 		v.adf_len = offsetof(addrfamily_t, adf_addr) +
7433b9b51feSCy Schubert 			    sizeof(struct in_addr);
7443b9b51feSCy Schubert 		v.adf_addr.in4 = addr->in4;
7453b9b51feSCy Schubert #ifdef USE_INET6
7463b9b51feSCy Schubert 	} else if (ipversion == 6) {
7473b9b51feSCy Schubert 		v.adf_family = AF_INET6;
7483b9b51feSCy Schubert 		v.adf_len = offsetof(addrfamily_t, adf_addr) +
7493b9b51feSCy Schubert 			    sizeof(struct in6_addr);
7503b9b51feSCy Schubert 		v.adf_addr.in6 = addr->in6;
7513b9b51feSCy Schubert #endif
7523b9b51feSCy Schubert 	} else
7538c82b374SCy Schubert 		return (-1);
7543b9b51feSCy Schubert 
7553b9b51feSCy Schubert 	READ_ENTER(&softc->ipf_poolrw);
7563b9b51feSCy Schubert 
7573b9b51feSCy Schubert 	rn = ipo->ipo_head->matchaddr(ipo->ipo_head, &v);
7583b9b51feSCy Schubert 
7593b9b51feSCy Schubert 	if ((rn != NULL) && (rn->root == 0)) {
7603b9b51feSCy Schubert 		m = (ip_pool_node_t *)rn;
7613b9b51feSCy Schubert 		ipo->ipo_hits++;
7623b9b51feSCy Schubert 		m->ipn_bytes += bytes;
7633b9b51feSCy Schubert 		m->ipn_hits++;
7643b9b51feSCy Schubert 		rv = m->ipn_info;
7653b9b51feSCy Schubert 	}
7663b9b51feSCy Schubert 	RWLOCK_EXIT(&softc->ipf_poolrw);
7678c82b374SCy Schubert 	return (rv);
7683b9b51feSCy Schubert }
7693b9b51feSCy Schubert 
7703b9b51feSCy Schubert 
7713b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
7723b9b51feSCy Schubert /* Function:    ipf_pool_insert_node                                        */
7733b9b51feSCy Schubert /* Returns:     int      - 0 = success, else error                          */
7743b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
7753b9b51feSCy Schubert /*              softp(I) - pointer to soft context pool information         */
7763b9b51feSCy Schubert /*              ipo(I)   - pointer to the pool getting the new node.        */
7773b9b51feSCy Schubert /*              node(I)  - structure with address/mask to add               */
7783b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw)                                           */
7793b9b51feSCy Schubert /*                                                                          */
7803b9b51feSCy Schubert /* Add another node to the pool given by ipo.  The three parameters passed  */
7813b9b51feSCy Schubert /* in (addr, mask, info) shold all be stored in the node.                   */
7823b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
7833b9b51feSCy Schubert static int
ipf_pool_insert_node(ipf_main_softc_t * softc,ipf_pool_softc_t * softp,ip_pool_t * ipo,struct ip_pool_node * node)784064a5a95SCy Schubert ipf_pool_insert_node(ipf_main_softc_t *softc, ipf_pool_softc_t *softp,
785064a5a95SCy Schubert 	ip_pool_t *ipo, struct ip_pool_node *node)
7863b9b51feSCy Schubert {
7873b9b51feSCy Schubert 	ipf_rdx_node_t *rn;
7883b9b51feSCy Schubert 	ip_pool_node_t *x;
7893b9b51feSCy Schubert 
7903b9b51feSCy Schubert 	if ((node->ipn_addr.adf_len > sizeof(*rn)) ||
7913b9b51feSCy Schubert 	    (node->ipn_addr.adf_len < 4)) {
7923b9b51feSCy Schubert 		IPFERROR(70003);
7938c82b374SCy Schubert 		return (EINVAL);
7943b9b51feSCy Schubert 	}
7953b9b51feSCy Schubert 
7963b9b51feSCy Schubert 	if ((node->ipn_mask.adf_len > sizeof(*rn)) ||
7973b9b51feSCy Schubert 	    (node->ipn_mask.adf_len < 4)) {
7983b9b51feSCy Schubert 		IPFERROR(70004);
7998c82b374SCy Schubert 		return (EINVAL);
8003b9b51feSCy Schubert 	}
8013b9b51feSCy Schubert 
8023b9b51feSCy Schubert 	KMALLOC(x, ip_pool_node_t *);
8033b9b51feSCy Schubert 	if (x == NULL) {
8043b9b51feSCy Schubert 		IPFERROR(70002);
8058c82b374SCy Schubert 		return (ENOMEM);
8063b9b51feSCy Schubert 	}
8073b9b51feSCy Schubert 
8083b9b51feSCy Schubert 	*x = *node;
8093b9b51feSCy Schubert 	bzero((char *)x->ipn_nodes, sizeof(x->ipn_nodes));
8103b9b51feSCy Schubert 	x->ipn_owner = ipo;
8113b9b51feSCy Schubert 	x->ipn_hits = 0;
8123b9b51feSCy Schubert 	x->ipn_next = NULL;
8133b9b51feSCy Schubert 	x->ipn_pnext = NULL;
8143b9b51feSCy Schubert 	x->ipn_dnext = NULL;
8153b9b51feSCy Schubert 	x->ipn_pdnext = NULL;
8163b9b51feSCy Schubert 
8173b9b51feSCy Schubert 	if (x->ipn_die != 0) {
8183b9b51feSCy Schubert 		/*
8193b9b51feSCy Schubert 		 * If the new node has a given expiration time, insert it
8203b9b51feSCy Schubert 		 * into the list of expiring nodes with the ones to be
8213b9b51feSCy Schubert 		 * removed first added to the front of the list. The
8223b9b51feSCy Schubert 		 * insertion is O(n) but it is kept sorted for quick scans
8233b9b51feSCy Schubert 		 * at expiration interval checks.
8243b9b51feSCy Schubert 		 */
8253b9b51feSCy Schubert 		ip_pool_node_t *n;
8263b9b51feSCy Schubert 
8273b9b51feSCy Schubert 		x->ipn_die = softc->ipf_ticks + IPF_TTLVAL(x->ipn_die);
8283b9b51feSCy Schubert 		for (n = softp->ipf_node_explist; n != NULL; n = n->ipn_dnext) {
8293b9b51feSCy Schubert 			if (x->ipn_die < n->ipn_die)
8303b9b51feSCy Schubert 				break;
8313b9b51feSCy Schubert 			if (n->ipn_dnext == NULL) {
8323b9b51feSCy Schubert 				/*
8333b9b51feSCy Schubert 				 * We've got to the last node and everything
8343b9b51feSCy Schubert 				 * wanted to be expired before this new node,
8353b9b51feSCy Schubert 				 * so we have to tack it on the end...
8363b9b51feSCy Schubert 				 */
8373b9b51feSCy Schubert 				n->ipn_dnext = x;
8383b9b51feSCy Schubert 				x->ipn_pdnext = &n->ipn_dnext;
8393b9b51feSCy Schubert 				n = NULL;
8403b9b51feSCy Schubert 				break;
8413b9b51feSCy Schubert 			}
8423b9b51feSCy Schubert 		}
8433b9b51feSCy Schubert 
8443b9b51feSCy Schubert 		if (softp->ipf_node_explist == NULL) {
8453b9b51feSCy Schubert 			softp->ipf_node_explist = x;
8463b9b51feSCy Schubert 			x->ipn_pdnext = &softp->ipf_node_explist;
8473b9b51feSCy Schubert 		} else if (n != NULL) {
8483b9b51feSCy Schubert 			x->ipn_dnext = n;
8493b9b51feSCy Schubert 			x->ipn_pdnext = n->ipn_pdnext;
8503b9b51feSCy Schubert 			n->ipn_pdnext = &x->ipn_dnext;
8513b9b51feSCy Schubert 		}
8523b9b51feSCy Schubert 	}
8533b9b51feSCy Schubert 
8543b9b51feSCy Schubert 	rn = ipo->ipo_head->addaddr(ipo->ipo_head, &x->ipn_addr, &x->ipn_mask,
8553b9b51feSCy Schubert 				    x->ipn_nodes);
8563b9b51feSCy Schubert #ifdef	DEBUG_POOL
8573b9b51feSCy Schubert 	printf("Added %p at %p\n", x, rn);
8583b9b51feSCy Schubert #endif
8593b9b51feSCy Schubert 
8603b9b51feSCy Schubert 	if (rn == NULL) {
8613b9b51feSCy Schubert 		KFREE(x);
8623b9b51feSCy Schubert 		IPFERROR(70005);
8638c82b374SCy Schubert 		return (ENOMEM);
8643b9b51feSCy Schubert 	}
8653b9b51feSCy Schubert 
8663b9b51feSCy Schubert 	x->ipn_ref = 1;
8673b9b51feSCy Schubert 	x->ipn_pnext = ipo->ipo_tail;
8683b9b51feSCy Schubert 	*ipo->ipo_tail = x;
8693b9b51feSCy Schubert 	ipo->ipo_tail = &x->ipn_next;
8703b9b51feSCy Schubert 
8713b9b51feSCy Schubert 	softp->ipf_pool_stats.ipls_nodes++;
8723b9b51feSCy Schubert 
8738c82b374SCy Schubert 	return (0);
8743b9b51feSCy Schubert }
8753b9b51feSCy Schubert 
8763b9b51feSCy Schubert 
8773b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
8783b9b51feSCy Schubert /* Function:    ipf_pool_create                                             */
8793b9b51feSCy Schubert /* Returns:     int      - 0 = success, else error                          */
8803b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
8813b9b51feSCy Schubert /*              softp(I) - pointer to soft context pool information         */
8823b9b51feSCy Schubert /*              op(I)    - pointer to iplookup struct with call details     */
8833b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw)                                           */
8843b9b51feSCy Schubert /*                                                                          */
885d53555d6SGordon Bergling /* Creates a new group according to the parameters passed in via the        */
8863b9b51feSCy Schubert /* iplookupop structure.  Does not check to see if the group already exists */
8873b9b51feSCy Schubert /* when being inserted - assume this has already been done.  If the pool is */
8883b9b51feSCy Schubert /* marked as being anonymous, give it a new, unique, identifier.  Call any  */
8893b9b51feSCy Schubert /* other functions required to initialise the structure.                    */
8903b9b51feSCy Schubert /*                                                                          */
8913b9b51feSCy Schubert /* If the structure is flagged for deletion then reset the flag and return, */
8923b9b51feSCy Schubert /* as this likely means we've tried to free a pool that is in use (flush)   */
8933b9b51feSCy Schubert /* and now want to repopulate it with "new" data.                           */
8943b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
8953b9b51feSCy Schubert static int
ipf_pool_create(ipf_main_softc_t * softc,ipf_pool_softc_t * softp,iplookupop_t * op)896064a5a95SCy Schubert ipf_pool_create(ipf_main_softc_t *softc, ipf_pool_softc_t *softp,
897064a5a95SCy Schubert 	iplookupop_t *op)
8983b9b51feSCy Schubert {
8993b9b51feSCy Schubert 	char name[FR_GROUPLEN];
9003b9b51feSCy Schubert 	int poolnum, unit;
9013b9b51feSCy Schubert 	ip_pool_t *h;
9023b9b51feSCy Schubert 
9033b9b51feSCy Schubert 	unit = op->iplo_unit;
9043b9b51feSCy Schubert 
9053b9b51feSCy Schubert 	if ((op->iplo_arg & LOOKUP_ANON) == 0) {
9063b9b51feSCy Schubert 		h = ipf_pool_exists(softp, unit, op->iplo_name);
9073b9b51feSCy Schubert 		if (h != NULL) {
9083b9b51feSCy Schubert 			if ((h->ipo_flags & IPOOL_DELETE) == 0) {
9093b9b51feSCy Schubert 				IPFERROR(70006);
9108c82b374SCy Schubert 				return (EEXIST);
9113b9b51feSCy Schubert 			}
9123b9b51feSCy Schubert 			h->ipo_flags &= ~IPOOL_DELETE;
9138c82b374SCy Schubert 			return (0);
9143b9b51feSCy Schubert 		}
9153b9b51feSCy Schubert 	}
9163b9b51feSCy Schubert 
9173b9b51feSCy Schubert 	KMALLOC(h, ip_pool_t *);
9183b9b51feSCy Schubert 	if (h == NULL) {
9193b9b51feSCy Schubert 		IPFERROR(70007);
9208c82b374SCy Schubert 		return (ENOMEM);
9213b9b51feSCy Schubert 	}
9223b9b51feSCy Schubert 	bzero(h, sizeof(*h));
9233b9b51feSCy Schubert 
9243b9b51feSCy Schubert 	if (ipf_rx_inithead(softp->ipf_radix, &h->ipo_head) != 0) {
9253b9b51feSCy Schubert 		KFREE(h);
9263b9b51feSCy Schubert 		IPFERROR(70008);
9278c82b374SCy Schubert 		return (ENOMEM);
9283b9b51feSCy Schubert 	}
9293b9b51feSCy Schubert 
9303b9b51feSCy Schubert 	if ((op->iplo_arg & LOOKUP_ANON) != 0) {
9313b9b51feSCy Schubert 		ip_pool_t *p;
9323b9b51feSCy Schubert 
9333b9b51feSCy Schubert 		h->ipo_flags |= IPOOL_ANON;
9343b9b51feSCy Schubert 		poolnum = LOOKUP_ANON;
9353b9b51feSCy Schubert 
9363b9b51feSCy Schubert 		(void)snprintf(name, sizeof(name), "%x", poolnum);
9373b9b51feSCy Schubert 
9383b9b51feSCy Schubert 		for (p = softp->ipf_pool_list[unit + 1]; p != NULL; ) {
9393b9b51feSCy Schubert 			if (strncmp(name, p->ipo_name,
9403b9b51feSCy Schubert 				    sizeof(p->ipo_name)) == 0) {
9413b9b51feSCy Schubert 				poolnum++;
9423b9b51feSCy Schubert 				(void)snprintf(name, sizeof(name), "%x", poolnum);
9433b9b51feSCy Schubert 				p = softp->ipf_pool_list[unit + 1];
9443b9b51feSCy Schubert 			} else
9453b9b51feSCy Schubert 				p = p->ipo_next;
9463b9b51feSCy Schubert 		}
9473b9b51feSCy Schubert 
9483b9b51feSCy Schubert 		(void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
9493b9b51feSCy Schubert 		(void)strncpy(op->iplo_name, name, sizeof(op->iplo_name));
9503b9b51feSCy Schubert 	} else {
9513b9b51feSCy Schubert 		(void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
9523b9b51feSCy Schubert 	}
9533b9b51feSCy Schubert 
9543b9b51feSCy Schubert 	h->ipo_radix = softp->ipf_radix;
9553b9b51feSCy Schubert 	h->ipo_ref = 1;
9563b9b51feSCy Schubert 	h->ipo_list = NULL;
9573b9b51feSCy Schubert 	h->ipo_tail = &h->ipo_list;
9583b9b51feSCy Schubert 	h->ipo_unit = unit;
9593b9b51feSCy Schubert 	h->ipo_next = softp->ipf_pool_list[unit + 1];
9603b9b51feSCy Schubert 	if (softp->ipf_pool_list[unit + 1] != NULL)
9613b9b51feSCy Schubert 		softp->ipf_pool_list[unit + 1]->ipo_pnext = &h->ipo_next;
9623b9b51feSCy Schubert 	h->ipo_pnext = &softp->ipf_pool_list[unit + 1];
9633b9b51feSCy Schubert 	softp->ipf_pool_list[unit + 1] = h;
9643b9b51feSCy Schubert 
9653b9b51feSCy Schubert 	softp->ipf_pool_stats.ipls_pools++;
9663b9b51feSCy Schubert 
9678c82b374SCy Schubert 	return (0);
9683b9b51feSCy Schubert }
9693b9b51feSCy Schubert 
9703b9b51feSCy Schubert 
9713b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
9723b9b51feSCy Schubert /* Function:    ipf_pool_remove_node                                        */
9733b9b51feSCy Schubert /* Returns:     int      - 0 = success, else error                          */
9743b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
9753b9b51feSCy Schubert /*              ipo(I)   - pointer to the pool to remove the node from.     */
9763b9b51feSCy Schubert /*              ipe(I)   - address being deleted as a node                  */
9773b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw)                                           */
9783b9b51feSCy Schubert /*                                                                          */
9793b9b51feSCy Schubert /* Remove a node from the pool given by ipo.                                */
9803b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
9813b9b51feSCy Schubert static int
ipf_pool_remove_node(ipf_main_softc_t * softc,ipf_pool_softc_t * softp,ip_pool_t * ipo,ip_pool_node_t * ipe)982064a5a95SCy Schubert ipf_pool_remove_node(ipf_main_softc_t *softc, ipf_pool_softc_t *softp,
983064a5a95SCy Schubert 	ip_pool_t *ipo, ip_pool_node_t *ipe)
9843b9b51feSCy Schubert {
9853b9b51feSCy Schubert 	void *ptr;
9863b9b51feSCy Schubert 
9873b9b51feSCy Schubert 	if (ipo->ipo_tail == &ipe->ipn_next)
9883b9b51feSCy Schubert 		ipo->ipo_tail = ipe->ipn_pnext;
9893b9b51feSCy Schubert 
9903b9b51feSCy Schubert 	if (ipe->ipn_pnext != NULL)
9913b9b51feSCy Schubert 		*ipe->ipn_pnext = ipe->ipn_next;
9923b9b51feSCy Schubert 	if (ipe->ipn_next != NULL)
9933b9b51feSCy Schubert 		ipe->ipn_next->ipn_pnext = ipe->ipn_pnext;
9943b9b51feSCy Schubert 
9953b9b51feSCy Schubert 	if (ipe->ipn_pdnext != NULL)
9963b9b51feSCy Schubert 		*ipe->ipn_pdnext = ipe->ipn_dnext;
9973b9b51feSCy Schubert 	if (ipe->ipn_dnext != NULL)
9983b9b51feSCy Schubert 		ipe->ipn_dnext->ipn_pdnext = ipe->ipn_pdnext;
9993b9b51feSCy Schubert 
10003b9b51feSCy Schubert 	ptr = ipo->ipo_head->deladdr(ipo->ipo_head, &ipe->ipn_addr,
10013b9b51feSCy Schubert 				     &ipe->ipn_mask);
10023b9b51feSCy Schubert 
10033b9b51feSCy Schubert 	if (ptr != NULL) {
10043b9b51feSCy Schubert 		ipf_pool_node_deref(softp, ipe);
10058c82b374SCy Schubert 		return (0);
10063b9b51feSCy Schubert 	}
10073b9b51feSCy Schubert 	IPFERROR(70027);
10088c82b374SCy Schubert 	return (ESRCH);
10093b9b51feSCy Schubert }
10103b9b51feSCy Schubert 
10113b9b51feSCy Schubert 
10123b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
10133b9b51feSCy Schubert /* Function:    ipf_pool_destroy                                            */
10143b9b51feSCy Schubert /* Returns:     int    - 0 = success, else error                            */
10153b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
10163b9b51feSCy Schubert /*              softp(I) - pointer to soft context pool information         */
10173b9b51feSCy Schubert /*              unit(I)  - ipfilter device to which we are working on       */
10183b9b51feSCy Schubert /*              name(I)  - name of the pool                                 */
10193b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw) or WRITE(ipf_global)                      */
10203b9b51feSCy Schubert /*                                                                          */
1021d53555d6SGordon Bergling /* Search for a pool using parameters passed in and if it's not otherwise   */
10223b9b51feSCy Schubert /* busy, free it.  If it is busy, clear all of its nodes, mark it for being */
10233b9b51feSCy Schubert /* deleted and return an error saying it is busy.                           */
10243b9b51feSCy Schubert /*                                                                          */
10253b9b51feSCy Schubert /* NOTE: Because this function is called out of ipfdetach() where ipf_poolrw*/
10263b9b51feSCy Schubert /* may not be initialised, we can't use an ASSERT to enforce the locking    */
10273b9b51feSCy Schubert /* assertion that one of the two (ipf_poolrw,ipf_global) is held.           */
10283b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
10293b9b51feSCy Schubert static int
ipf_pool_destroy(ipf_main_softc_t * softc,ipf_pool_softc_t * softp,int unit,char * name)1030064a5a95SCy Schubert ipf_pool_destroy(ipf_main_softc_t *softc, ipf_pool_softc_t *softp,
1031064a5a95SCy Schubert 	int unit, char *name)
10323b9b51feSCy Schubert {
10333b9b51feSCy Schubert 	ip_pool_t *ipo;
10343b9b51feSCy Schubert 
10353b9b51feSCy Schubert 	ipo = ipf_pool_exists(softp, unit, name);
10363b9b51feSCy Schubert 	if (ipo == NULL) {
10373b9b51feSCy Schubert 		IPFERROR(70009);
10388c82b374SCy Schubert 		return (ESRCH);
10393b9b51feSCy Schubert 	}
10403b9b51feSCy Schubert 
10413b9b51feSCy Schubert 	if (ipo->ipo_ref != 1) {
10423b9b51feSCy Schubert 		ipf_pool_clearnodes(softc, softp, ipo);
10433b9b51feSCy Schubert 		ipo->ipo_flags |= IPOOL_DELETE;
10448c82b374SCy Schubert 		return (0);
10453b9b51feSCy Schubert 	}
10463b9b51feSCy Schubert 
10473b9b51feSCy Schubert 	ipf_pool_free(softc, softp, ipo);
10488c82b374SCy Schubert 	return (0);
10493b9b51feSCy Schubert }
10503b9b51feSCy Schubert 
10513b9b51feSCy Schubert 
10523b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
10533b9b51feSCy Schubert /* Function:    ipf_pool_flush                                              */
10543b9b51feSCy Schubert /* Returns:     int    - number of pools deleted                            */
10553b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
10563b9b51feSCy Schubert /*              arg(I)   - pointer to local context to use                  */
10573b9b51feSCy Schubert /*              fp(I)    - which pool(s) to flush                           */
10583b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw) or WRITE(ipf_global)                      */
10593b9b51feSCy Schubert /*                                                                          */
10603b9b51feSCy Schubert /* Free all pools associated with the device that matches the unit number   */
10613b9b51feSCy Schubert /* passed in with operation.                                                */
10623b9b51feSCy Schubert /*                                                                          */
10633b9b51feSCy Schubert /* NOTE: Because this function is called out of ipfdetach() where ipf_poolrw*/
10643b9b51feSCy Schubert /* may not be initialised, we can't use an ASSERT to enforce the locking    */
10653b9b51feSCy Schubert /* assertion that one of the two (ipf_poolrw,ipf_global) is held.           */
10663b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
10673b9b51feSCy Schubert static size_t
ipf_pool_flush(ipf_main_softc_t * softc,void * arg,iplookupflush_t * fp)1068064a5a95SCy Schubert ipf_pool_flush(ipf_main_softc_t *softc, void *arg, iplookupflush_t *fp)
10693b9b51feSCy Schubert {
10703b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
10713b9b51feSCy Schubert 	int i, num = 0, unit, err;
10723b9b51feSCy Schubert 	ip_pool_t *p, *q;
10733b9b51feSCy Schubert 
10743b9b51feSCy Schubert 	unit = fp->iplf_unit;
10753b9b51feSCy Schubert 	for (i = -1; i <= IPL_LOGMAX; i++) {
10763b9b51feSCy Schubert 		if (unit != IPLT_ALL && i != unit)
10773b9b51feSCy Schubert 			continue;
10783b9b51feSCy Schubert 		for (q = softp->ipf_pool_list[i + 1]; (p = q) != NULL; ) {
10793b9b51feSCy Schubert 			q = p->ipo_next;
10803b9b51feSCy Schubert 			err = ipf_pool_destroy(softc, softp, i, p->ipo_name);
10813b9b51feSCy Schubert 			if (err == 0)
10823b9b51feSCy Schubert 				num++;
10833b9b51feSCy Schubert 		}
10843b9b51feSCy Schubert 	}
10858c82b374SCy Schubert 	return (num);
10863b9b51feSCy Schubert }
10873b9b51feSCy Schubert 
10883b9b51feSCy Schubert 
10893b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
10903b9b51feSCy Schubert /* Function:    ipf_pool_free                                               */
10913b9b51feSCy Schubert /* Returns:     void                                                        */
10923b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
10933b9b51feSCy Schubert /*              softp(I) - pointer to soft context pool information         */
10943b9b51feSCy Schubert /*              ipo(I) - pointer to pool structure                          */
10953b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw) or WRITE(ipf_global)                      */
10963b9b51feSCy Schubert /*                                                                          */
1097cde9ec6aSGordon Bergling /* Deletes the pool structure passed in from the list of pools and deletes  */
10983b9b51feSCy Schubert /* all of the address information stored in it, including any tree data     */
10993b9b51feSCy Schubert /* structures also allocated.                                               */
11003b9b51feSCy Schubert /*                                                                          */
11013b9b51feSCy Schubert /* NOTE: Because this function is called out of ipfdetach() where ipf_poolrw*/
11023b9b51feSCy Schubert /* may not be initialised, we can't use an ASSERT to enforce the locking    */
11033b9b51feSCy Schubert /* assertion that one of the two (ipf_poolrw,ipf_global) is held.           */
11043b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
11053b9b51feSCy Schubert static void
ipf_pool_free(ipf_main_softc_t * softc,ipf_pool_softc_t * softp,ip_pool_t * ipo)1106064a5a95SCy Schubert ipf_pool_free(ipf_main_softc_t *softc, ipf_pool_softc_t *softp, ip_pool_t *ipo)
11073b9b51feSCy Schubert {
11083b9b51feSCy Schubert 
11093b9b51feSCy Schubert 	ipf_pool_clearnodes(softc, softp, ipo);
11103b9b51feSCy Schubert 
11113b9b51feSCy Schubert 	if (ipo->ipo_next != NULL)
11123b9b51feSCy Schubert 		ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
11133b9b51feSCy Schubert 	*ipo->ipo_pnext = ipo->ipo_next;
11143b9b51feSCy Schubert 	ipf_rx_freehead(ipo->ipo_head);
11153b9b51feSCy Schubert 	KFREE(ipo);
11163b9b51feSCy Schubert 
11173b9b51feSCy Schubert 	softp->ipf_pool_stats.ipls_pools--;
11183b9b51feSCy Schubert }
11193b9b51feSCy Schubert 
11203b9b51feSCy Schubert 
11213b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
11223b9b51feSCy Schubert /* Function:    ipf_pool_clearnodes                                         */
11233b9b51feSCy Schubert /* Returns:     void                                                        */
11243b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
11253b9b51feSCy Schubert /*              softp(I) - pointer to soft context pool information         */
11263b9b51feSCy Schubert /*              ipo(I)   - pointer to pool structure                        */
11273b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw) or WRITE(ipf_global)                      */
11283b9b51feSCy Schubert /*                                                                          */
11293b9b51feSCy Schubert /* Deletes all nodes stored in a pool structure.                            */
11303b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
11313b9b51feSCy Schubert static void
ipf_pool_clearnodes(ipf_main_softc_t * softc,ipf_pool_softc_t * softp,ip_pool_t * ipo)1132064a5a95SCy Schubert ipf_pool_clearnodes(ipf_main_softc_t *softc, ipf_pool_softc_t *softp,
1133064a5a95SCy Schubert 	ip_pool_t *ipo)
11343b9b51feSCy Schubert {
11353b9b51feSCy Schubert 	ip_pool_node_t *n, **next;
11363b9b51feSCy Schubert 
11373b9b51feSCy Schubert 	for (next = &ipo->ipo_list; (n = *next) != NULL; )
11383b9b51feSCy Schubert 		ipf_pool_remove_node(softc, softp, ipo, n);
11393b9b51feSCy Schubert 
11403b9b51feSCy Schubert 	ipo->ipo_list = NULL;
11413b9b51feSCy Schubert }
11423b9b51feSCy Schubert 
11433b9b51feSCy Schubert 
11443b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
11453b9b51feSCy Schubert /* Function:    ipf_pool_deref                                              */
11463b9b51feSCy Schubert /* Returns:     void                                                        */
11473b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
11483b9b51feSCy Schubert /*              arg(I)   - pointer to local context to use                  */
11493b9b51feSCy Schubert /*              pool(I)  - pointer to pool structure                        */
11503b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw)                                           */
11513b9b51feSCy Schubert /*                                                                          */
11523b9b51feSCy Schubert /* Drop the number of known references to this pool structure by one and if */
11533b9b51feSCy Schubert /* we arrive at zero known references, free it.                             */
11543b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
11553b9b51feSCy Schubert static int
ipf_pool_deref(ipf_main_softc_t * softc,void * arg,void * pool)1156064a5a95SCy Schubert ipf_pool_deref(ipf_main_softc_t *softc, void *arg, void *pool)
11573b9b51feSCy Schubert {
11583b9b51feSCy Schubert 	ip_pool_t *ipo = pool;
11593b9b51feSCy Schubert 
11603b9b51feSCy Schubert 	ipo->ipo_ref--;
11613b9b51feSCy Schubert 
11623b9b51feSCy Schubert 	if (ipo->ipo_ref == 0)
11633b9b51feSCy Schubert 		ipf_pool_free(softc, arg, ipo);
11643b9b51feSCy Schubert 
11653b9b51feSCy Schubert 	else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE))
11663b9b51feSCy Schubert 		ipf_pool_destroy(softc, arg, ipo->ipo_unit, ipo->ipo_name);
11673b9b51feSCy Schubert 
11688c82b374SCy Schubert 	return (0);
11693b9b51feSCy Schubert }
11703b9b51feSCy Schubert 
11713b9b51feSCy Schubert 
11723b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
11733b9b51feSCy Schubert /* Function:    ipf_pool_node_deref                                         */
11743b9b51feSCy Schubert /* Returns:     void                                                        */
11753b9b51feSCy Schubert /* Parameters:  softp(I) - pointer to soft context pool information         */
11763b9b51feSCy Schubert /*              ipn(I)   - pointer to pool structure                        */
11773b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw)                                           */
11783b9b51feSCy Schubert /*                                                                          */
11793b9b51feSCy Schubert /* Drop a reference to the pool node passed in and if we're the last, free  */
11803b9b51feSCy Schubert /* it all up and adjust the stats accordingly.                              */
11813b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
11823b9b51feSCy Schubert static void
ipf_pool_node_deref(ipf_pool_softc_t * softp,ip_pool_node_t * ipn)1183064a5a95SCy Schubert ipf_pool_node_deref(ipf_pool_softc_t *softp, ip_pool_node_t *ipn)
11843b9b51feSCy Schubert {
11853b9b51feSCy Schubert 
11863b9b51feSCy Schubert 	ipn->ipn_ref--;
11873b9b51feSCy Schubert 
11883b9b51feSCy Schubert 	if (ipn->ipn_ref == 0) {
11893b9b51feSCy Schubert 		KFREE(ipn);
11903b9b51feSCy Schubert 		softp->ipf_pool_stats.ipls_nodes--;
11913b9b51feSCy Schubert 	}
11923b9b51feSCy Schubert }
11933b9b51feSCy Schubert 
11943b9b51feSCy Schubert 
11953b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
11963b9b51feSCy Schubert /* Function:    ipf_pool_iter_next                                          */
11973b9b51feSCy Schubert /* Returns:     void                                                        */
11983b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
11993b9b51feSCy Schubert /*              arg(I)   - pointer to local context to use                  */
12003b9b51feSCy Schubert /*              token(I) - pointer to pool structure                        */
12013b9b51feSCy Schubert /*              ilp(IO)  - pointer to pool iterating structure              */
12023b9b51feSCy Schubert /*                                                                          */
12033b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
12043b9b51feSCy Schubert static int
ipf_pool_iter_next(ipf_main_softc_t * softc,void * arg,ipftoken_t * token,ipflookupiter_t * ilp)1205064a5a95SCy Schubert ipf_pool_iter_next(ipf_main_softc_t *softc, void *arg, ipftoken_t *token,
1206064a5a95SCy Schubert 	ipflookupiter_t *ilp)
12073b9b51feSCy Schubert {
12083b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
12093b9b51feSCy Schubert 	ip_pool_node_t *node, zn, *nextnode;
12103b9b51feSCy Schubert 	ip_pool_t *ipo, zp, *nextipo;
12113b9b51feSCy Schubert 	void *pnext;
12123b9b51feSCy Schubert 	int err;
12133b9b51feSCy Schubert 
12143b9b51feSCy Schubert 	err = 0;
12153b9b51feSCy Schubert 	node = NULL;
12163b9b51feSCy Schubert 	nextnode = NULL;
12173b9b51feSCy Schubert 	ipo = NULL;
12183b9b51feSCy Schubert 	nextipo = NULL;
12193b9b51feSCy Schubert 
12203b9b51feSCy Schubert 	READ_ENTER(&softc->ipf_poolrw);
12213b9b51feSCy Schubert 
12223b9b51feSCy Schubert 	switch (ilp->ili_otype)
12233b9b51feSCy Schubert 	{
12243b9b51feSCy Schubert 	case IPFLOOKUPITER_LIST :
12253b9b51feSCy Schubert 		ipo = token->ipt_data;
12263b9b51feSCy Schubert 		if (ipo == NULL) {
12273b9b51feSCy Schubert 			nextipo = softp->ipf_pool_list[(int)ilp->ili_unit + 1];
12283b9b51feSCy Schubert 		} else {
12293b9b51feSCy Schubert 			nextipo = ipo->ipo_next;
12303b9b51feSCy Schubert 		}
12313b9b51feSCy Schubert 
12323b9b51feSCy Schubert 		if (nextipo != NULL) {
12333b9b51feSCy Schubert 			ATOMIC_INC32(nextipo->ipo_ref);
12343b9b51feSCy Schubert 			token->ipt_data = nextipo;
12353b9b51feSCy Schubert 		} else {
12363b9b51feSCy Schubert 			bzero((char *)&zp, sizeof(zp));
12373b9b51feSCy Schubert 			nextipo = &zp;
12383b9b51feSCy Schubert 			token->ipt_data = NULL;
12393b9b51feSCy Schubert 		}
12403b9b51feSCy Schubert 		pnext = nextipo->ipo_next;
12413b9b51feSCy Schubert 		break;
12423b9b51feSCy Schubert 
12433b9b51feSCy Schubert 	case IPFLOOKUPITER_NODE :
12443b9b51feSCy Schubert 		node = token->ipt_data;
12453b9b51feSCy Schubert 		if (node == NULL) {
12463b9b51feSCy Schubert 			ipo = ipf_pool_exists(arg, ilp->ili_unit,
12473b9b51feSCy Schubert 					      ilp->ili_name);
12483b9b51feSCy Schubert 			if (ipo == NULL) {
12493b9b51feSCy Schubert 				IPFERROR(70010);
12503b9b51feSCy Schubert 				err = ESRCH;
12513b9b51feSCy Schubert 			} else {
12523b9b51feSCy Schubert 				nextnode = ipo->ipo_list;
12533b9b51feSCy Schubert 				ipo = NULL;
12543b9b51feSCy Schubert 			}
12553b9b51feSCy Schubert 		} else {
12563b9b51feSCy Schubert 			nextnode = node->ipn_next;
12573b9b51feSCy Schubert 		}
12583b9b51feSCy Schubert 
12593b9b51feSCy Schubert 		if (nextnode != NULL) {
12603b9b51feSCy Schubert 			ATOMIC_INC32(nextnode->ipn_ref);
12613b9b51feSCy Schubert 			token->ipt_data = nextnode;
12623b9b51feSCy Schubert 		} else {
12633b9b51feSCy Schubert 			bzero((char *)&zn, sizeof(zn));
12643b9b51feSCy Schubert 			nextnode = &zn;
12653b9b51feSCy Schubert 			token->ipt_data = NULL;
12663b9b51feSCy Schubert 		}
12673b9b51feSCy Schubert 		pnext = nextnode->ipn_next;
12683b9b51feSCy Schubert 		break;
12693b9b51feSCy Schubert 
12703b9b51feSCy Schubert 	default :
12713b9b51feSCy Schubert 		IPFERROR(70011);
12723b9b51feSCy Schubert 		pnext = NULL;
12733b9b51feSCy Schubert 		err = EINVAL;
12743b9b51feSCy Schubert 		break;
12753b9b51feSCy Schubert 	}
12763b9b51feSCy Schubert 
12773b9b51feSCy Schubert 	RWLOCK_EXIT(&softc->ipf_poolrw);
12783b9b51feSCy Schubert 	if (err != 0)
12798c82b374SCy Schubert 		return (err);
12803b9b51feSCy Schubert 
12813b9b51feSCy Schubert 	switch (ilp->ili_otype)
12823b9b51feSCy Schubert 	{
12833b9b51feSCy Schubert 	case IPFLOOKUPITER_LIST :
12843b9b51feSCy Schubert 		err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo));
12853b9b51feSCy Schubert 		if (err != 0)  {
12863b9b51feSCy Schubert 			IPFERROR(70012);
12873b9b51feSCy Schubert 			err = EFAULT;
12883b9b51feSCy Schubert 		}
12893b9b51feSCy Schubert 		if (ipo != NULL) {
12903b9b51feSCy Schubert 			WRITE_ENTER(&softc->ipf_poolrw);
12913b9b51feSCy Schubert 			ipf_pool_deref(softc, softp, ipo);
12923b9b51feSCy Schubert 			RWLOCK_EXIT(&softc->ipf_poolrw);
12933b9b51feSCy Schubert 		}
12943b9b51feSCy Schubert 		break;
12953b9b51feSCy Schubert 
12963b9b51feSCy Schubert 	case IPFLOOKUPITER_NODE :
12973b9b51feSCy Schubert 		err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
12983b9b51feSCy Schubert 		if (err != 0) {
12993b9b51feSCy Schubert 			IPFERROR(70013);
13003b9b51feSCy Schubert 			err = EFAULT;
13013b9b51feSCy Schubert 		}
13023b9b51feSCy Schubert 		if (node != NULL) {
13033b9b51feSCy Schubert 			WRITE_ENTER(&softc->ipf_poolrw);
13043b9b51feSCy Schubert 			ipf_pool_node_deref(softp, node);
13053b9b51feSCy Schubert 			RWLOCK_EXIT(&softc->ipf_poolrw);
13063b9b51feSCy Schubert 		}
13073b9b51feSCy Schubert 		break;
13083b9b51feSCy Schubert 	}
13093b9b51feSCy Schubert 	if (pnext == NULL)
13103b9b51feSCy Schubert 		ipf_token_mark_complete(token);
13113b9b51feSCy Schubert 
13128c82b374SCy Schubert 	return (err);
13133b9b51feSCy Schubert }
13143b9b51feSCy Schubert 
13153b9b51feSCy Schubert 
13163b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
13173b9b51feSCy Schubert /* Function:    ipf_pool_iterderef                                          */
13183b9b51feSCy Schubert /* Returns:     void                                                        */
13193b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
13203b9b51feSCy Schubert /*              arg(I)   - pointer to local context to use                  */
13213b9b51feSCy Schubert /*              unit(I)  - ipfilter device to which we are working on       */
13223b9b51feSCy Schubert /* Locks:       WRITE(ipf_poolrw)                                           */
13233b9b51feSCy Schubert /*                                                                          */
13243b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
13253b9b51feSCy Schubert static int
ipf_pool_iter_deref(ipf_main_softc_t * softc,void * arg,int otype,int unit,void * data)1326064a5a95SCy Schubert ipf_pool_iter_deref(ipf_main_softc_t *softc, void *arg, int otype, int unit,
1327064a5a95SCy Schubert 	void *data)
13283b9b51feSCy Schubert {
13293b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
13303b9b51feSCy Schubert 
13313b9b51feSCy Schubert 	if (data == NULL)
13328c82b374SCy Schubert 		return (EINVAL);
13333b9b51feSCy Schubert 
13343b9b51feSCy Schubert 	if (unit < 0 || unit > IPL_LOGMAX)
13358c82b374SCy Schubert 		return (EINVAL);
13363b9b51feSCy Schubert 
13373b9b51feSCy Schubert 	switch (otype)
13383b9b51feSCy Schubert 	{
13393b9b51feSCy Schubert 	case IPFLOOKUPITER_LIST :
13403b9b51feSCy Schubert 		ipf_pool_deref(softc, softp, (ip_pool_t *)data);
13413b9b51feSCy Schubert 		break;
13423b9b51feSCy Schubert 
13433b9b51feSCy Schubert 	case IPFLOOKUPITER_NODE :
13443b9b51feSCy Schubert 		ipf_pool_node_deref(softp, (ip_pool_node_t *)data);
13453b9b51feSCy Schubert 		break;
13463b9b51feSCy Schubert 	default :
13473b9b51feSCy Schubert 		break;
13483b9b51feSCy Schubert 	}
13493b9b51feSCy Schubert 
13508c82b374SCy Schubert 	return (0);
13513b9b51feSCy Schubert }
13523b9b51feSCy Schubert 
13533b9b51feSCy Schubert 
13543b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
13553b9b51feSCy Schubert /* Function:    ipf_pool_expire                                             */
13563b9b51feSCy Schubert /* Returns:     Nil                                                         */
13573b9b51feSCy Schubert /* Parameters:  softc(I) - pointer to soft context main structure           */
13583b9b51feSCy Schubert /*              arg(I)   - pointer to local context to use                  */
13593b9b51feSCy Schubert /*                                                                          */
13603b9b51feSCy Schubert /* At present this function exists just to support temporary addition of    */
13613b9b51feSCy Schubert /* nodes to the address pool.                                               */
13623b9b51feSCy Schubert /* ------------------------------------------------------------------------ */
13633b9b51feSCy Schubert static void
ipf_pool_expire(ipf_main_softc_t * softc,void * arg)1364064a5a95SCy Schubert ipf_pool_expire(ipf_main_softc_t *softc, void *arg)
13653b9b51feSCy Schubert {
13663b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
13673b9b51feSCy Schubert 	ip_pool_node_t *n;
13683b9b51feSCy Schubert 
13693b9b51feSCy Schubert 	while ((n = softp->ipf_node_explist) != NULL) {
13703b9b51feSCy Schubert 		/*
13713b9b51feSCy Schubert 		 * Because the list is kept sorted on insertion, the fist
13723b9b51feSCy Schubert 		 * one that dies in the future means no more work to do.
13733b9b51feSCy Schubert 		 */
13743b9b51feSCy Schubert 		if (n->ipn_die > softc->ipf_ticks)
13753b9b51feSCy Schubert 			break;
13763b9b51feSCy Schubert 		ipf_pool_remove_node(softc, softp, n->ipn_owner, n);
13773b9b51feSCy Schubert 	}
13783b9b51feSCy Schubert }
13793b9b51feSCy Schubert 
13803b9b51feSCy Schubert 
13813b9b51feSCy Schubert 
13823b9b51feSCy Schubert 
13833b9b51feSCy Schubert #ifndef _KERNEL
13843b9b51feSCy Schubert void
ipf_pool_dump(softc,arg)13853b9b51feSCy Schubert ipf_pool_dump(softc, arg)
13863b9b51feSCy Schubert 	ipf_main_softc_t *softc;
13873b9b51feSCy Schubert 	void *arg;
13883b9b51feSCy Schubert {
13893b9b51feSCy Schubert 	ipf_pool_softc_t *softp = arg;
13903b9b51feSCy Schubert 	ip_pool_t *ipl;
13913b9b51feSCy Schubert 	int i;
13923b9b51feSCy Schubert 
13933b9b51feSCy Schubert 	printf("List of configured pools\n");
13943b9b51feSCy Schubert 	for (i = 0; i <= LOOKUP_POOL_MAX; i++)
13953b9b51feSCy Schubert 		for (ipl = softp->ipf_pool_list[i]; ipl != NULL;
13963b9b51feSCy Schubert 		     ipl = ipl->ipo_next)
13973b9b51feSCy Schubert 			printpool(ipl, bcopywrap, NULL, opts, NULL);
13983b9b51feSCy Schubert }
13993b9b51feSCy Schubert #endif
1400