xref: /illumos-gate/usr/src/uts/common/inet/ipf/ip_pool.c (revision ab25eeb5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (C) 1993-2001, 2003 by Darren Reed.
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
57c478bd9Sstevel@tonic-gate  *
6*ab25eeb5Syz  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
77c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
87c478bd9Sstevel@tonic-gate  */
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
117c478bd9Sstevel@tonic-gate 
127c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL)
137c478bd9Sstevel@tonic-gate # undef KERNEL
147c478bd9Sstevel@tonic-gate # undef _KERNEL
157c478bd9Sstevel@tonic-gate # define        KERNEL	1
167c478bd9Sstevel@tonic-gate # define        _KERNEL	1
177c478bd9Sstevel@tonic-gate #endif
18*ab25eeb5Syz #if defined(__osf__)
19*ab25eeb5Syz # define _PROTO_NET_H_
20*ab25eeb5Syz #endif
217c478bd9Sstevel@tonic-gate #include <sys/errno.h>
227c478bd9Sstevel@tonic-gate #include <sys/types.h>
237c478bd9Sstevel@tonic-gate #include <sys/param.h>
247c478bd9Sstevel@tonic-gate #include <sys/file.h>
257c478bd9Sstevel@tonic-gate #if !defined(_KERNEL) && !defined(__KERNEL__)
267c478bd9Sstevel@tonic-gate # include <stdio.h>
277c478bd9Sstevel@tonic-gate # include <stdlib.h>
287c478bd9Sstevel@tonic-gate # include <string.h>
297c478bd9Sstevel@tonic-gate # define _KERNEL
307c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__
317c478bd9Sstevel@tonic-gate struct file;
327c478bd9Sstevel@tonic-gate # endif
337c478bd9Sstevel@tonic-gate # include <sys/uio.h>
347c478bd9Sstevel@tonic-gate # undef _KERNEL
357c478bd9Sstevel@tonic-gate #else
367c478bd9Sstevel@tonic-gate # include <sys/systm.h>
377c478bd9Sstevel@tonic-gate # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
387c478bd9Sstevel@tonic-gate #  include <sys/proc.h>
397c478bd9Sstevel@tonic-gate # endif
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate #include <sys/time.h>
427c478bd9Sstevel@tonic-gate #if !defined(linux)
437c478bd9Sstevel@tonic-gate # include <sys/protosw.h>
447c478bd9Sstevel@tonic-gate #endif
457c478bd9Sstevel@tonic-gate #include <sys/socket.h>
467c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
477c478bd9Sstevel@tonic-gate # include <sys/mbuf.h>
487c478bd9Sstevel@tonic-gate #endif
497c478bd9Sstevel@tonic-gate #if defined(__SVR4) || defined(__svr4__)
507c478bd9Sstevel@tonic-gate # include <sys/filio.h>
517c478bd9Sstevel@tonic-gate # include <sys/byteorder.h>
527c478bd9Sstevel@tonic-gate # ifdef _KERNEL
537c478bd9Sstevel@tonic-gate #  include <sys/dditypes.h>
547c478bd9Sstevel@tonic-gate # endif
557c478bd9Sstevel@tonic-gate # include <sys/stream.h>
567c478bd9Sstevel@tonic-gate # include <sys/kmem.h>
577c478bd9Sstevel@tonic-gate #endif
587c478bd9Sstevel@tonic-gate #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
597c478bd9Sstevel@tonic-gate # include <sys/malloc.h>
607c478bd9Sstevel@tonic-gate #endif
617c478bd9Sstevel@tonic-gate 
62*ab25eeb5Syz #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
63*ab25eeb5Syz      defined(__hpux) || defined(__sgi))
64*ab25eeb5Syz # ifdef __osf__
65*ab25eeb5Syz #  include <net/radix.h>
66*ab25eeb5Syz # endif
67*ab25eeb5Syz # include "radix_ipf_local.h"
68*ab25eeb5Syz # define _RADIX_H_
69*ab25eeb5Syz #endif
707c478bd9Sstevel@tonic-gate #include <net/if.h>
717c478bd9Sstevel@tonic-gate #include <netinet/in.h>
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h"
747c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h"
757c478bd9Sstevel@tonic-gate #include "netinet/ip_pool.h"
76*ab25eeb5Syz 
77*ab25eeb5Syz #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
78*ab25eeb5Syz       ((BSD >= 198911) && !defined(__osf__) && \
79*ab25eeb5Syz       !defined(__hpux) && !defined(__sgi))
80*ab25eeb5Syz static int rn_freenode __P((struct radix_node *, void *));
817c478bd9Sstevel@tonic-gate #endif
82*ab25eeb5Syz 
837c478bd9Sstevel@tonic-gate /* END OF INCLUDES */
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate #if !defined(lint)
867c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
87*ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $";
887c478bd9Sstevel@tonic-gate #endif
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP
917c478bd9Sstevel@tonic-gate 
92*ab25eeb5Syz # ifndef RADIX_NODE_HEAD_LOCK
93*ab25eeb5Syz #  define RADIX_NODE_HEAD_LOCK(x)	;
94*ab25eeb5Syz # endif
95*ab25eeb5Syz # ifndef RADIX_NODE_HEAD_UNLOCK
96*ab25eeb5Syz #  define RADIX_NODE_HEAD_UNLOCK(x)	;
97*ab25eeb5Syz # endif
98*ab25eeb5Syz 
997c478bd9Sstevel@tonic-gate ip_pool_stat_t ipoolstat;
100*ab25eeb5Syz ipfrwlock_t ip_poolrw;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate  * Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
1047c478bd9Sstevel@tonic-gate  * NOTE: Insertion *MUST* be from greatest range to least for it to work!
1057c478bd9Sstevel@tonic-gate  * These should be replaced, eventually, by something else - most notably a
1067c478bd9Sstevel@tonic-gate  * interval searching method.  The important feature is to be able to find
1077c478bd9Sstevel@tonic-gate  * the best match.
1087c478bd9Sstevel@tonic-gate  *
1097c478bd9Sstevel@tonic-gate  * So why not use a radix tree for this?  As the first line implies, it
1107c478bd9Sstevel@tonic-gate  * has been written to work with a _range_ of addresses.  A range is not
1117c478bd9Sstevel@tonic-gate  * necessarily a match with any given netmask so what we end up dealing
1127c478bd9Sstevel@tonic-gate  * with is an interval tree.  Implementations of these are hard to find
1137c478bd9Sstevel@tonic-gate  * and the one herein is far from bug free.
1147c478bd9Sstevel@tonic-gate  *
1157c478bd9Sstevel@tonic-gate  * Sigh, in the end I became convinced that the bugs the code contained did
1167c478bd9Sstevel@tonic-gate  * not make it worthwhile not using radix trees.  For now the radix tree from
1177c478bd9Sstevel@tonic-gate  * 4.4 BSD is used, but this is not viewed as a long term solution.
1187c478bd9Sstevel@tonic-gate  */
1197c478bd9Sstevel@tonic-gate ip_pool_t *ip_pool_list[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL,
1207c478bd9Sstevel@tonic-gate 					 NULL, NULL, NULL, NULL };
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate #ifdef TEST_POOL
1247c478bd9Sstevel@tonic-gate void treeprint __P((ip_pool_t *));
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate int
1277c478bd9Sstevel@tonic-gate main(argc, argv)
1287c478bd9Sstevel@tonic-gate 	int argc;
1297c478bd9Sstevel@tonic-gate 	char *argv[];
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	addrfamily_t a, b;
1327c478bd9Sstevel@tonic-gate 	iplookupop_t op;
1337c478bd9Sstevel@tonic-gate 	ip_pool_t *ipo;
1347c478bd9Sstevel@tonic-gate 	i6addr_t ip;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	RWLOCK_INIT(&ip_poolrw, "poolrw");
1377c478bd9Sstevel@tonic-gate 	ip_pool_init();
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	bzero((char *)&a, sizeof(a));
1407c478bd9Sstevel@tonic-gate 	bzero((char *)&b, sizeof(b));
1417c478bd9Sstevel@tonic-gate 	bzero((char *)&ip, sizeof(ip));
1427c478bd9Sstevel@tonic-gate 	bzero((char *)&op, sizeof(op));
1437c478bd9Sstevel@tonic-gate 	strcpy(op.iplo_name, "0");
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	if (ip_pool_create(&op) == 0)
1467c478bd9Sstevel@tonic-gate 		ipo = ip_pool_find(0, "0");
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a010203;
1497c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffffffff;
1507663b816Sml 	ip_pool_insert(ipo, &a, &b, 1);
1517663b816Sml 	ip_pool_insert(ipo, &a, &b, 1);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a000000;
1547c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xff000000;
1557663b816Sml 	ip_pool_insert(ipo, &a, &b, 0);
1567663b816Sml 	ip_pool_insert(ipo, &a, &b, 0);
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a010100;
1597c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffffff00;
1607663b816Sml 	ip_pool_insert(ipo, &a, &b, 1);
1617663b816Sml 	ip_pool_insert(ipo, &a, &b, 1);
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a010200;
1647c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffffff00;
1657663b816Sml 	ip_pool_insert(ipo, &a, &b, 0);
1667663b816Sml 	ip_pool_insert(ipo, &a, &b, 0);
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a010000;
1697c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffff0000;
1707663b816Sml 	ip_pool_insert(ipo, &a, &b, 1);
1717663b816Sml 	ip_pool_insert(ipo, &a, &b, 1);
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a01020f;
1747c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffffffff;
1757663b816Sml 	ip_pool_insert(ipo, &a, &b, 1);
1767663b816Sml 	ip_pool_insert(ipo, &a, &b, 1);
1777c478bd9Sstevel@tonic-gate #ifdef	DEBUG_POOL
1787c478bd9Sstevel@tonic-gate treeprint(ipo);
1797c478bd9Sstevel@tonic-gate #endif
1807c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a00aabb;
1817c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
1827c478bd9Sstevel@tonic-gate 		ip_pool_search(ipo, 4, &ip));
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a000001;
1857c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
1867c478bd9Sstevel@tonic-gate 		ip_pool_search(ipo, 4, &ip));
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a000101;
1897c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
1907c478bd9Sstevel@tonic-gate 		ip_pool_search(ipo, 4, &ip));
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a010001;
1937c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
1947c478bd9Sstevel@tonic-gate 		ip_pool_search(ipo, 4, &ip));
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a010101;
1977c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
1987c478bd9Sstevel@tonic-gate 		ip_pool_search(ipo, 4, &ip));
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a010201;
2017c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
2027c478bd9Sstevel@tonic-gate 		ip_pool_search(ipo, 4, &ip));
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a010203;
2057c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
2067c478bd9Sstevel@tonic-gate 		ip_pool_search(ipo, 4, &ip));
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a01020f;
2097c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
2107c478bd9Sstevel@tonic-gate 		ip_pool_search(ipo, 4, &ip));
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0b00aabb;
2137c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
2147c478bd9Sstevel@tonic-gate 		ip_pool_search(ipo, 4, &ip));
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate #ifdef	DEBUG_POOL
2177c478bd9Sstevel@tonic-gate treeprint(ipo);
2187c478bd9Sstevel@tonic-gate #endif
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	ip_pool_fini();
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	return 0;
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate void
2277c478bd9Sstevel@tonic-gate treeprint(ipo)
2287c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
2297c478bd9Sstevel@tonic-gate {
2307c478bd9Sstevel@tonic-gate 	ip_pool_node_t *c;
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
2337c478bd9Sstevel@tonic-gate 		printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
2347c478bd9Sstevel@tonic-gate 			c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
2357c478bd9Sstevel@tonic-gate 			c->ipn_mask.adf_addr.in4.s_addr,
2367c478bd9Sstevel@tonic-gate 			c->ipn_info, c->ipn_hits);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate #endif /* TEST_POOL */
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
2427c478bd9Sstevel@tonic-gate /* Function:    ip_pool_init                                                */
2437c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
2447c478bd9Sstevel@tonic-gate /*                                                                          */
2457c478bd9Sstevel@tonic-gate /* Initialise the routing table data structures where required.             */
2467c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
2477c478bd9Sstevel@tonic-gate int ip_pool_init()
2487c478bd9Sstevel@tonic-gate {
249*ab25eeb5Syz 
25008254dd3Syz 	bzero((char *)&ipoolstat, sizeof(ipoolstat));
2517c478bd9Sstevel@tonic-gate 
252*ab25eeb5Syz #if (!defined(_KERNEL) || (BSD < 199306))
2537c478bd9Sstevel@tonic-gate 	rn_init();
2547c478bd9Sstevel@tonic-gate #endif
2557c478bd9Sstevel@tonic-gate 	return 0;
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
2607c478bd9Sstevel@tonic-gate /* Function:    ip_pool_fini                                                */
2617c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
2627c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ipf_global)                                           */
2637c478bd9Sstevel@tonic-gate /*                                                                          */
2647c478bd9Sstevel@tonic-gate /* Clean up all the pool data structures allocated and call the cleanup     */
2657c478bd9Sstevel@tonic-gate /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
2667c478bd9Sstevel@tonic-gate /* used to delete the pools one by one to ensure they're properly freed up. */
2677c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
2687c478bd9Sstevel@tonic-gate void ip_pool_fini()
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate 	ip_pool_t *p, *q;
2717c478bd9Sstevel@tonic-gate 	iplookupop_t op;
2727c478bd9Sstevel@tonic-gate 	int i;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	ASSERT(rw_read_locked(&ipf_global.ipf_lk) == 0);
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	for (i = 0; i <= IPL_LOGMAX; i++) {
2777c478bd9Sstevel@tonic-gate 		for (q = ip_pool_list[i]; (p = q) != NULL; ) {
2787c478bd9Sstevel@tonic-gate 			op.iplo_unit = i;
2797c478bd9Sstevel@tonic-gate 			(void)strncpy(op.iplo_name, p->ipo_name,
2807c478bd9Sstevel@tonic-gate 				sizeof(op.iplo_name));
2817c478bd9Sstevel@tonic-gate 			q = p->ipo_next;
2827c478bd9Sstevel@tonic-gate 			(void) ip_pool_destroy(&op);
2837c478bd9Sstevel@tonic-gate 		}
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 
286*ab25eeb5Syz #if (!defined(_KERNEL) || (BSD < 199306))
2877c478bd9Sstevel@tonic-gate 	rn_fini();
2887c478bd9Sstevel@tonic-gate #endif
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate 
291*ab25eeb5Syz 
2927663b816Sml /* ------------------------------------------------------------------------ */
2937663b816Sml /* Function:    ip_pool_statistics                                          */
2947663b816Sml /* Returns:     int     - 0 = success, else error                           */
2957663b816Sml /* Parameters:  op(I)   - pointer to lookup operation arguments             */
2967663b816Sml /*                                                                          */
2977663b816Sml /* Copy the current statistics out into user space, collecting pool list    */
2987663b816Sml /* pointers as appropriate for later use.                                   */
2997663b816Sml /* ------------------------------------------------------------------------ */
3007663b816Sml int ip_pool_statistics(op)
3017663b816Sml iplookupop_t *op;
3027663b816Sml {
3037663b816Sml 	ip_pool_stat_t stats;
3047663b816Sml 	int unit, i, err = 0;
3057663b816Sml 
3067663b816Sml 	if (op->iplo_size != sizeof(ipoolstat))
3077663b816Sml 		return EINVAL;
3087663b816Sml 
3097663b816Sml 	bcopy((char *)&ipoolstat, (char *)&stats, sizeof(stats));
3107663b816Sml 	unit = op->iplo_unit;
3117663b816Sml 	if (unit == IPL_LOGALL) {
3127663b816Sml 		for (i = 0; i < IPL_LOGSIZE; i++)
3137663b816Sml 			stats.ipls_list[i] = ip_pool_list[i];
3147663b816Sml 	} else if (unit >= 0 && unit < IPL_LOGSIZE) {
315*ab25eeb5Syz 		if (op->iplo_name[0] != '\0')
316*ab25eeb5Syz 			stats.ipls_list[unit] = ip_pool_find(unit,
317*ab25eeb5Syz 							     op->iplo_name);
318*ab25eeb5Syz 		else
319*ab25eeb5Syz 			stats.ipls_list[unit] = ip_pool_list[unit];
3207663b816Sml 	} else
3217663b816Sml 		err = EINVAL;
3227663b816Sml 	if (err == 0)
3237663b816Sml 		err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
3247663b816Sml 	return err;
3257663b816Sml }
3267663b816Sml 
3277c478bd9Sstevel@tonic-gate 
328*ab25eeb5Syz 
3297c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3307c478bd9Sstevel@tonic-gate /* Function:    ip_pool_find                                                */
3317c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
3327c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
3337c478bd9Sstevel@tonic-gate /*                                                                          */
3347c478bd9Sstevel@tonic-gate /* Find a matching pool inside the collection of pools for a particular     */
3357c478bd9Sstevel@tonic-gate /* device, indicated by the unit number.                                    */
3367c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3377c478bd9Sstevel@tonic-gate void *ip_pool_find(unit, name)
3387c478bd9Sstevel@tonic-gate int unit;
3397c478bd9Sstevel@tonic-gate char *name;
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	ip_pool_t *p;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next)
344*ab25eeb5Syz 		if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
3457c478bd9Sstevel@tonic-gate 			break;
3467c478bd9Sstevel@tonic-gate 	return p;
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3517c478bd9Sstevel@tonic-gate /* Function:    ip_pool_findeq                                              */
3527c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
3537c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
354*ab25eeb5Syz /*              addr(I) - pointer to address information to delete          */
3557c478bd9Sstevel@tonic-gate /*              mask(I) -                                                   */
3567c478bd9Sstevel@tonic-gate /*                                                                          */
3577c478bd9Sstevel@tonic-gate /* Searches for an exact match of an entry in the pool.                     */
3587c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3597c478bd9Sstevel@tonic-gate ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
3607c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
3617663b816Sml addrfamily_t *addr, *mask;
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate 	struct radix_node *n;
364*ab25eeb5Syz 	SPL_INT(s);
3657c478bd9Sstevel@tonic-gate 
366*ab25eeb5Syz 	SPL_NET(s);
367*ab25eeb5Syz 	RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
3687c478bd9Sstevel@tonic-gate 	n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
369*ab25eeb5Syz 	RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
370*ab25eeb5Syz 	SPL_X(s);
3717c478bd9Sstevel@tonic-gate 	return (ip_pool_node_t *)n;
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3767c478bd9Sstevel@tonic-gate /* Function:    ip_pool_search                                              */
377*ab25eeb5Syz /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve/no match    */
3787c478bd9Sstevel@tonic-gate /* Parameters:  tptr(I)    - pointer to the pool to search                  */
3797c478bd9Sstevel@tonic-gate /*              version(I) - IP protocol version (4 or 6)                   */
3807c478bd9Sstevel@tonic-gate /*              dptr(I)    - pointer to address information                 */
3817c478bd9Sstevel@tonic-gate /*                                                                          */
3827c478bd9Sstevel@tonic-gate /* Search the pool for a given address and return a search result.          */
3837c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3847c478bd9Sstevel@tonic-gate int ip_pool_search(tptr, version, dptr)
3857c478bd9Sstevel@tonic-gate void *tptr;
3867c478bd9Sstevel@tonic-gate int version;
3877c478bd9Sstevel@tonic-gate void *dptr;
3887c478bd9Sstevel@tonic-gate {
3897c478bd9Sstevel@tonic-gate 	struct radix_node *rn;
3907c478bd9Sstevel@tonic-gate 	ip_pool_node_t *m;
3917c478bd9Sstevel@tonic-gate 	i6addr_t *addr;
3927c478bd9Sstevel@tonic-gate 	addrfamily_t v;
3937c478bd9Sstevel@tonic-gate 	ip_pool_t *ipo;
3947c478bd9Sstevel@tonic-gate 	int rv;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	ipo = tptr;
3977c478bd9Sstevel@tonic-gate 	if (ipo == NULL)
3987c478bd9Sstevel@tonic-gate 		return -1;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	rv = 1;
4017c478bd9Sstevel@tonic-gate 	m = NULL;
4027c478bd9Sstevel@tonic-gate 	addr = (i6addr_t *)dptr;
4037c478bd9Sstevel@tonic-gate 	bzero(&v, sizeof(v));
4047c478bd9Sstevel@tonic-gate 	v.adf_len = offsetof(addrfamily_t, adf_addr);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	if (version == 4) {
4077c478bd9Sstevel@tonic-gate 		v.adf_len += sizeof(addr->in4);
4087c478bd9Sstevel@tonic-gate 		v.adf_addr.in4 = addr->in4;
4097c478bd9Sstevel@tonic-gate #ifdef USE_INET6
4107c478bd9Sstevel@tonic-gate 	} else if (version == 6) {
4117c478bd9Sstevel@tonic-gate 		v.adf_len += sizeof(addr->in6);
4127c478bd9Sstevel@tonic-gate 		v.adf_addr.in6 = addr->in6;
4137c478bd9Sstevel@tonic-gate #endif
4147c478bd9Sstevel@tonic-gate 	} else
4157c478bd9Sstevel@tonic-gate 		return -1;
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	READ_ENTER(&ip_poolrw);
4187c478bd9Sstevel@tonic-gate 
419*ab25eeb5Syz 	RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
4207c478bd9Sstevel@tonic-gate 	rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
421*ab25eeb5Syz 	RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
4247c478bd9Sstevel@tonic-gate 		m = (ip_pool_node_t *)rn;
4257c478bd9Sstevel@tonic-gate 		ipo->ipo_hits++;
4267c478bd9Sstevel@tonic-gate 		m->ipn_hits++;
4277c478bd9Sstevel@tonic-gate 		rv = m->ipn_info;
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 	RWLOCK_EXIT(&ip_poolrw);
4307c478bd9Sstevel@tonic-gate 	return rv;
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4357c478bd9Sstevel@tonic-gate /* Function:    ip_pool_insert                                              */
4367c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
4377c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
4387663b816Sml /*              addr(I) - IPv4/6 address being added as a node              */
4397663b816Sml /*              mask(I) - IPv4/6 netmask to with the node being added       */
4407c478bd9Sstevel@tonic-gate /*              info(I) - extra information to store in this node.          */
4417c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw)                                            */
4427c478bd9Sstevel@tonic-gate /*                                                                          */
4437c478bd9Sstevel@tonic-gate /* Add another node to the pool given by ipo.  The three parameters passed  */
4447c478bd9Sstevel@tonic-gate /* in (addr, mask, info) shold all be stored in the node.                   */
4457c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4467c478bd9Sstevel@tonic-gate int ip_pool_insert(ipo, addr, mask, info)
4477c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
4487663b816Sml addrfamily_t *addr, *mask;
4497c478bd9Sstevel@tonic-gate int info;
4507c478bd9Sstevel@tonic-gate {
4517c478bd9Sstevel@tonic-gate 	struct radix_node *rn;
4527c478bd9Sstevel@tonic-gate 	ip_pool_node_t *x;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	KMALLOC(x, ip_pool_node_t *);
4577c478bd9Sstevel@tonic-gate 	if (x == NULL) {
4587c478bd9Sstevel@tonic-gate 		return ENOMEM;
4597c478bd9Sstevel@tonic-gate 	}
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	bzero(x, sizeof(*x));
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	x->ipn_info = info;
4647c478bd9Sstevel@tonic-gate 	(void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
4657c478bd9Sstevel@tonic-gate 
4667663b816Sml 	bcopy(addr, &x->ipn_addr, sizeof(*addr));
4677c478bd9Sstevel@tonic-gate 	x->ipn_addr.adf_len = sizeof(x->ipn_addr);
4687663b816Sml 	bcopy(mask, &x->ipn_mask, sizeof(*mask));
4697c478bd9Sstevel@tonic-gate 	x->ipn_mask.adf_len = sizeof(x->ipn_mask);
4707c478bd9Sstevel@tonic-gate 
471*ab25eeb5Syz 	RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
4727c478bd9Sstevel@tonic-gate 	rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
4737c478bd9Sstevel@tonic-gate 					ipo->ipo_head, x->ipn_nodes);
474*ab25eeb5Syz 	RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
4757c478bd9Sstevel@tonic-gate #ifdef	DEBUG_POOL
4767c478bd9Sstevel@tonic-gate 	printf("Added %p at %p\n", x, rn);
4777c478bd9Sstevel@tonic-gate #endif
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	if (rn == NULL) {
4807c478bd9Sstevel@tonic-gate 		KFREE(x);
4817c478bd9Sstevel@tonic-gate 		return ENOMEM;
4827c478bd9Sstevel@tonic-gate 	}
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	x->ipn_next = ipo->ipo_list;
4857c478bd9Sstevel@tonic-gate 	x->ipn_pnext = &ipo->ipo_list;
4867c478bd9Sstevel@tonic-gate 	if (ipo->ipo_list != NULL)
4877c478bd9Sstevel@tonic-gate 		ipo->ipo_list->ipn_pnext = &x->ipn_next;
4887c478bd9Sstevel@tonic-gate 	ipo->ipo_list = x;
4897c478bd9Sstevel@tonic-gate 
49008254dd3Syz 	ipoolstat.ipls_nodes++;
49108254dd3Syz 
4927c478bd9Sstevel@tonic-gate 	return 0;
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4977c478bd9Sstevel@tonic-gate /* Function:    ip_pool_create                                              */
4987c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
4997c478bd9Sstevel@tonic-gate /* Parameters:  op(I) - pointer to iplookup struct with call details        */
5007c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw)                                            */
5017c478bd9Sstevel@tonic-gate /*                                                                          */
5027c478bd9Sstevel@tonic-gate /* Creates a new group according to the paramters passed in via the         */
5037c478bd9Sstevel@tonic-gate /* iplookupop structure.  Does not check to see if the group already exists */
5047c478bd9Sstevel@tonic-gate /* when being inserted - assume this has already been done.  If the pool is */
5057c478bd9Sstevel@tonic-gate /* marked as being anonymous, give it a new, unique, identifier.  Call any  */
5067c478bd9Sstevel@tonic-gate /* other functions required to initialise the structure.                    */
5077c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
5087c478bd9Sstevel@tonic-gate int ip_pool_create(op)
5097c478bd9Sstevel@tonic-gate iplookupop_t *op;
5107c478bd9Sstevel@tonic-gate {
5117c478bd9Sstevel@tonic-gate 	char name[FR_GROUPLEN];
5127c478bd9Sstevel@tonic-gate 	int poolnum, unit;
5137c478bd9Sstevel@tonic-gate 	ip_pool_t *h;
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	KMALLOC(h, ip_pool_t *);
5187c478bd9Sstevel@tonic-gate 	if (h == NULL)
5197c478bd9Sstevel@tonic-gate 		return ENOMEM;
5207c478bd9Sstevel@tonic-gate 	bzero(h, sizeof(*h));
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	if (rn_inithead((void **)&h->ipo_head,
5237c478bd9Sstevel@tonic-gate 			offsetof(addrfamily_t, adf_addr) << 3) == 0) {
5247c478bd9Sstevel@tonic-gate 		KFREE(h);
5257c478bd9Sstevel@tonic-gate 		return ENOMEM;
5267c478bd9Sstevel@tonic-gate 	}
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	unit = op->iplo_unit;
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	if ((op->iplo_arg & IPOOL_ANON) != 0) {
5317c478bd9Sstevel@tonic-gate 		ip_pool_t *p;
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 		poolnum = IPOOL_ANON;
534*ab25eeb5Syz 
535*ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL)
536*ab25eeb5Syz 		(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
537*ab25eeb5Syz #else
5387c478bd9Sstevel@tonic-gate 		(void)sprintf(name, "%x", poolnum);
539*ab25eeb5Syz #endif
540*ab25eeb5Syz 
5417c478bd9Sstevel@tonic-gate 		for (p = ip_pool_list[unit]; p != NULL; ) {
542*ab25eeb5Syz 			if (strncmp(name, p->ipo_name,
543*ab25eeb5Syz 				    sizeof(p->ipo_name)) == 0) {
5447c478bd9Sstevel@tonic-gate 				poolnum++;
545*ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL)
546*ab25eeb5Syz 				(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
547*ab25eeb5Syz #else
5487c478bd9Sstevel@tonic-gate 				(void)sprintf(name, "%x", poolnum);
549*ab25eeb5Syz #endif
5507c478bd9Sstevel@tonic-gate 				p = ip_pool_list[unit];
5517c478bd9Sstevel@tonic-gate 			} else
5527c478bd9Sstevel@tonic-gate 				p = p->ipo_next;
5537c478bd9Sstevel@tonic-gate 		}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 		(void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
5567c478bd9Sstevel@tonic-gate 	} else {
5577c478bd9Sstevel@tonic-gate 		(void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	h->ipo_ref = 1;
5617c478bd9Sstevel@tonic-gate 	h->ipo_list = NULL;
5627c478bd9Sstevel@tonic-gate 	h->ipo_unit = unit;
5637c478bd9Sstevel@tonic-gate 	h->ipo_next = ip_pool_list[unit];
5647c478bd9Sstevel@tonic-gate 	if (ip_pool_list[unit] != NULL)
5657c478bd9Sstevel@tonic-gate 		ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
5667c478bd9Sstevel@tonic-gate 	h->ipo_pnext = &ip_pool_list[unit];
5677c478bd9Sstevel@tonic-gate 	ip_pool_list[unit] = h;
56808254dd3Syz 
5697c478bd9Sstevel@tonic-gate 	ipoolstat.ipls_pools++;
57008254dd3Syz 
5717c478bd9Sstevel@tonic-gate 	return 0;
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
5767c478bd9Sstevel@tonic-gate /* Function:    ip_pool_remove                                              */
5777c478bd9Sstevel@tonic-gate /* Returns:     int    - 0 = success, else error                            */
5787c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I) - pointer to the pool to remove the node from.       */
5797c478bd9Sstevel@tonic-gate /*              ipe(I) - address being deleted as a node                    */
5807c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw)                                            */
5817c478bd9Sstevel@tonic-gate /*                                                                          */
5827c478bd9Sstevel@tonic-gate /* Add another node to the pool given by ipo.  The three parameters passed  */
5837c478bd9Sstevel@tonic-gate /* in (addr, mask, info) shold all be stored in the node.                   */
5847c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
5857c478bd9Sstevel@tonic-gate int ip_pool_remove(ipo, ipe)
5867c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
5877c478bd9Sstevel@tonic-gate ip_pool_node_t *ipe;
5887c478bd9Sstevel@tonic-gate {
5897c478bd9Sstevel@tonic-gate 	ip_pool_node_t **ipp, *n;
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) {
5947c478bd9Sstevel@tonic-gate 		if (ipe == n) {
5957c478bd9Sstevel@tonic-gate 			*n->ipn_pnext = n->ipn_next;
5967c478bd9Sstevel@tonic-gate 			if (n->ipn_next)
5977c478bd9Sstevel@tonic-gate 				n->ipn_next->ipn_pnext = n->ipn_pnext;
5987c478bd9Sstevel@tonic-gate 			break;
5997c478bd9Sstevel@tonic-gate 		}
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	if (n == NULL)
6037c478bd9Sstevel@tonic-gate 		return ENOENT;
6047c478bd9Sstevel@tonic-gate 
605*ab25eeb5Syz 	RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
6067c478bd9Sstevel@tonic-gate 	ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
6077c478bd9Sstevel@tonic-gate 				   ipo->ipo_head);
608*ab25eeb5Syz 	RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
6097c478bd9Sstevel@tonic-gate 	KFREE(n);
61008254dd3Syz 
611*ab25eeb5Syz 	ipoolstat.ipls_nodes--;
61208254dd3Syz 
6137c478bd9Sstevel@tonic-gate 	return 0;
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
6187c478bd9Sstevel@tonic-gate /* Function:    ip_pool_destroy                                             */
6197c478bd9Sstevel@tonic-gate /* Returns:     int    - 0 = success, else error                            */
6207c478bd9Sstevel@tonic-gate /* Parameters:  op(I)  -  information about the pool to remove              */
6217c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
6227c478bd9Sstevel@tonic-gate /*                                                                          */
6237c478bd9Sstevel@tonic-gate /* Search for a pool using paramters passed in and if it's not otherwise    */
6247c478bd9Sstevel@tonic-gate /* busy, free it.                                                           */
6257c478bd9Sstevel@tonic-gate /*                                                                          */
6267c478bd9Sstevel@tonic-gate /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6277c478bd9Sstevel@tonic-gate /* may not be initialised, we can't use an ASSERT to enforce the locking    */
6287c478bd9Sstevel@tonic-gate /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
6297c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
6307c478bd9Sstevel@tonic-gate int ip_pool_destroy(op)
6317c478bd9Sstevel@tonic-gate iplookupop_t *op;
6327c478bd9Sstevel@tonic-gate {
6337c478bd9Sstevel@tonic-gate 	ip_pool_t *ipo;
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 	ipo = ip_pool_find(op->iplo_unit, op->iplo_name);
6367c478bd9Sstevel@tonic-gate 	if (ipo == NULL)
6377c478bd9Sstevel@tonic-gate 		return ESRCH;
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	if (ipo->ipo_ref != 1)
6407c478bd9Sstevel@tonic-gate 		return EBUSY;
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	ip_pool_free(ipo);
6437c478bd9Sstevel@tonic-gate 	return 0;
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 
647*ab25eeb5Syz /* ------------------------------------------------------------------------ */
648*ab25eeb5Syz /* Function:    ip_pool_flush                                               */
649*ab25eeb5Syz /* Returns:     int    - number of pools deleted                            */
650*ab25eeb5Syz /* Parameters:  fp(I)  - which pool(s) to flush                             */
651*ab25eeb5Syz /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
652*ab25eeb5Syz /*                                                                          */
653*ab25eeb5Syz /* Free all pools associated with the device that matches the unit number   */
654*ab25eeb5Syz /* passed in with operation.                                                */
655*ab25eeb5Syz /*                                                                          */
656*ab25eeb5Syz /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
657*ab25eeb5Syz /* may not be initialised, we can't use an ASSERT to enforce the locking    */
658*ab25eeb5Syz /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
659*ab25eeb5Syz /* ------------------------------------------------------------------------ */
660*ab25eeb5Syz int ip_pool_flush(fp)
661*ab25eeb5Syz iplookupflush_t *fp;
662*ab25eeb5Syz {
663*ab25eeb5Syz 	int i, num = 0, unit, err;
664*ab25eeb5Syz 	ip_pool_t *p, *q;
665*ab25eeb5Syz 	iplookupop_t op;
666*ab25eeb5Syz 
667*ab25eeb5Syz 	unit = fp->iplf_unit;
668*ab25eeb5Syz 
669*ab25eeb5Syz 	for (i = 0; i <= IPL_LOGMAX; i++) {
670*ab25eeb5Syz 		if (unit != IPLT_ALL && i != unit)
671*ab25eeb5Syz 			continue;
672*ab25eeb5Syz 		for (q = ip_pool_list[i]; (p = q) != NULL; ) {
673*ab25eeb5Syz 			op.iplo_unit = i;
674*ab25eeb5Syz 			(void)strncpy(op.iplo_name, p->ipo_name,
675*ab25eeb5Syz 				sizeof(op.iplo_name));
676*ab25eeb5Syz 			q = p->ipo_next;
677*ab25eeb5Syz 			err = ip_pool_destroy(&op);
678*ab25eeb5Syz 			if (err == 0)
679*ab25eeb5Syz 				num++;
680*ab25eeb5Syz 			else
681*ab25eeb5Syz 				break;
682*ab25eeb5Syz 		}
683*ab25eeb5Syz 	}
684*ab25eeb5Syz 	return num;
685*ab25eeb5Syz }
686*ab25eeb5Syz 
687*ab25eeb5Syz 
6887c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
6897c478bd9Sstevel@tonic-gate /* Function:    ip_pool_free                                                */
6907c478bd9Sstevel@tonic-gate /* Returns:     void                                                        */
6917c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I) -  pointer to pool structure                         */
6927c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
6937c478bd9Sstevel@tonic-gate /*                                                                          */
6947c478bd9Sstevel@tonic-gate /* Deletes the pool strucutre passed in from the list of pools and deletes  */
6957c478bd9Sstevel@tonic-gate /* all of the address information stored in it, including any tree data     */
6967c478bd9Sstevel@tonic-gate /* structures also allocated.                                               */
6977c478bd9Sstevel@tonic-gate /*                                                                          */
6987c478bd9Sstevel@tonic-gate /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6997c478bd9Sstevel@tonic-gate /* may not be initialised, we can't use an ASSERT to enforce the locking    */
7007c478bd9Sstevel@tonic-gate /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
7017c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
7027c478bd9Sstevel@tonic-gate void ip_pool_free(ipo)
7037c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
7047c478bd9Sstevel@tonic-gate {
7057c478bd9Sstevel@tonic-gate 	ip_pool_node_t *n;
7067c478bd9Sstevel@tonic-gate 
707*ab25eeb5Syz 	RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
7087c478bd9Sstevel@tonic-gate 	while ((n = ipo->ipo_list) != NULL) {
7097c478bd9Sstevel@tonic-gate 		ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
7107c478bd9Sstevel@tonic-gate 					   ipo->ipo_head);
711*ab25eeb5Syz 
7127c478bd9Sstevel@tonic-gate 		*n->ipn_pnext = n->ipn_next;
7137c478bd9Sstevel@tonic-gate 		if (n->ipn_next)
7147c478bd9Sstevel@tonic-gate 			n->ipn_next->ipn_pnext = n->ipn_pnext;
715*ab25eeb5Syz 
7167c478bd9Sstevel@tonic-gate 		KFREE(n);
71708254dd3Syz 
71808254dd3Syz 		ipoolstat.ipls_nodes--;
7197c478bd9Sstevel@tonic-gate 	}
720*ab25eeb5Syz 	RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	ipo->ipo_list = NULL;
7237c478bd9Sstevel@tonic-gate 	if (ipo->ipo_next != NULL)
7247c478bd9Sstevel@tonic-gate 		ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
7257c478bd9Sstevel@tonic-gate 	*ipo->ipo_pnext = ipo->ipo_next;
7267c478bd9Sstevel@tonic-gate 	rn_freehead(ipo->ipo_head);
7277c478bd9Sstevel@tonic-gate 	KFREE(ipo);
72808254dd3Syz 
72908254dd3Syz 	ipoolstat.ipls_pools--;
7307c478bd9Sstevel@tonic-gate }
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
7347c478bd9Sstevel@tonic-gate /* Function:    ip_pool_deref                                               */
7357c478bd9Sstevel@tonic-gate /* Returns:     void                                                        */
7367c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I) -  pointer to pool structure                         */
7377c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw)                                            */
7387c478bd9Sstevel@tonic-gate /*                                                                          */
7397c478bd9Sstevel@tonic-gate /* Drop the number of known references to this pool structure by one and if */
7407c478bd9Sstevel@tonic-gate /* we arrive at zero known references, free it.                             */
7417c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
7427c478bd9Sstevel@tonic-gate void ip_pool_deref(ipo)
7437c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
7447c478bd9Sstevel@tonic-gate {
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 	ipo->ipo_ref--;
7497c478bd9Sstevel@tonic-gate 	if (ipo->ipo_ref == 0)
7507c478bd9Sstevel@tonic-gate 		ip_pool_free(ipo);
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 
754*ab25eeb5Syz # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
755*ab25eeb5Syz       !defined(__hpux) && !defined(__sgi))
7567c478bd9Sstevel@tonic-gate static int
7577c478bd9Sstevel@tonic-gate rn_freenode(struct radix_node *n, void *p)
7587c478bd9Sstevel@tonic-gate {
7597c478bd9Sstevel@tonic-gate 	struct radix_node_head *rnh = p;
7607c478bd9Sstevel@tonic-gate 	struct radix_node *d;
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 	d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
7637c478bd9Sstevel@tonic-gate 	if (d != NULL) {
7647c478bd9Sstevel@tonic-gate 		FreeS(d, max_keylen + 2 * sizeof (*d));
7657c478bd9Sstevel@tonic-gate 	}
7667c478bd9Sstevel@tonic-gate 	return 0;
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate void
7717c478bd9Sstevel@tonic-gate rn_freehead(rnh)
7727c478bd9Sstevel@tonic-gate       struct radix_node_head *rnh;
7737c478bd9Sstevel@tonic-gate {
7747c478bd9Sstevel@tonic-gate 
775*ab25eeb5Syz 	RADIX_NODE_HEAD_LOCK(rnh);
776*ab25eeb5Syz 	(*rnh->rnh_walktree)(rnh, rn_freenode, rnh);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	rnh->rnh_addaddr = NULL;
7797c478bd9Sstevel@tonic-gate 	rnh->rnh_deladdr = NULL;
7807c478bd9Sstevel@tonic-gate 	rnh->rnh_matchaddr = NULL;
7817c478bd9Sstevel@tonic-gate 	rnh->rnh_lookup = NULL;
7827c478bd9Sstevel@tonic-gate 	rnh->rnh_walktree = NULL;
783*ab25eeb5Syz 	RADIX_NODE_HEAD_UNLOCK(rnh);
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	Free(rnh);
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate # endif
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOOKUP */
790