xref: /illumos-gate/usr/src/uts/common/inet/ipf/ip_pool.c (revision de22af4e)
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*de22af4eSJohn Ojemann  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
77c478bd9Sstevel@tonic-gate  */
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL)
107c478bd9Sstevel@tonic-gate # undef KERNEL
117c478bd9Sstevel@tonic-gate # undef _KERNEL
127c478bd9Sstevel@tonic-gate # define        KERNEL	1
137c478bd9Sstevel@tonic-gate # define        _KERNEL	1
147c478bd9Sstevel@tonic-gate #endif
15ab25eeb5Syz #if defined(__osf__)
16ab25eeb5Syz # define _PROTO_NET_H_
17ab25eeb5Syz #endif
187c478bd9Sstevel@tonic-gate #include <sys/errno.h>
197c478bd9Sstevel@tonic-gate #include <sys/types.h>
207c478bd9Sstevel@tonic-gate #include <sys/param.h>
217c478bd9Sstevel@tonic-gate #include <sys/file.h>
227c478bd9Sstevel@tonic-gate #if !defined(_KERNEL) && !defined(__KERNEL__)
237c478bd9Sstevel@tonic-gate # include <stdio.h>
247c478bd9Sstevel@tonic-gate # include <stdlib.h>
257c478bd9Sstevel@tonic-gate # include <string.h>
267c478bd9Sstevel@tonic-gate # define _KERNEL
277c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__
287c478bd9Sstevel@tonic-gate struct file;
297c478bd9Sstevel@tonic-gate # endif
307c478bd9Sstevel@tonic-gate # include <sys/uio.h>
317c478bd9Sstevel@tonic-gate # undef _KERNEL
327c478bd9Sstevel@tonic-gate #else
337c478bd9Sstevel@tonic-gate # include <sys/systm.h>
347c478bd9Sstevel@tonic-gate # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
357c478bd9Sstevel@tonic-gate #  include <sys/proc.h>
367c478bd9Sstevel@tonic-gate # endif
377c478bd9Sstevel@tonic-gate #endif
387c478bd9Sstevel@tonic-gate #include <sys/time.h>
397c478bd9Sstevel@tonic-gate #if !defined(linux)
407c478bd9Sstevel@tonic-gate # include <sys/protosw.h>
417c478bd9Sstevel@tonic-gate #endif
427c478bd9Sstevel@tonic-gate #include <sys/socket.h>
437c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
447c478bd9Sstevel@tonic-gate # include <sys/mbuf.h>
457c478bd9Sstevel@tonic-gate #endif
467c478bd9Sstevel@tonic-gate #if defined(__SVR4) || defined(__svr4__)
477c478bd9Sstevel@tonic-gate # include <sys/filio.h>
487c478bd9Sstevel@tonic-gate # include <sys/byteorder.h>
497c478bd9Sstevel@tonic-gate # ifdef _KERNEL
507c478bd9Sstevel@tonic-gate #  include <sys/dditypes.h>
517c478bd9Sstevel@tonic-gate # endif
527c478bd9Sstevel@tonic-gate # include <sys/stream.h>
537c478bd9Sstevel@tonic-gate # include <sys/kmem.h>
547c478bd9Sstevel@tonic-gate #endif
557c478bd9Sstevel@tonic-gate #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
567c478bd9Sstevel@tonic-gate # include <sys/malloc.h>
577c478bd9Sstevel@tonic-gate #endif
587c478bd9Sstevel@tonic-gate 
59ab25eeb5Syz #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
60ab25eeb5Syz      defined(__hpux) || defined(__sgi))
61ab25eeb5Syz # ifdef __osf__
62ab25eeb5Syz #  include <net/radix.h>
63ab25eeb5Syz # endif
64ab25eeb5Syz # include "radix_ipf_local.h"
65ab25eeb5Syz # define _RADIX_H_
66ab25eeb5Syz #endif
677c478bd9Sstevel@tonic-gate #include <net/if.h>
687c478bd9Sstevel@tonic-gate #include <netinet/in.h>
697c478bd9Sstevel@tonic-gate 
70f4b3ec61Sdh #include "netinet/ipf_stack.h"
717c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h"
727c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h"
737c478bd9Sstevel@tonic-gate #include "netinet/ip_pool.h"
74ab25eeb5Syz 
75ab25eeb5Syz #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
76ab25eeb5Syz       ((BSD >= 198911) && !defined(__osf__) && \
77ab25eeb5Syz       !defined(__hpux) && !defined(__sgi))
78ab25eeb5Syz static int rn_freenode __P((struct radix_node *, void *));
797c478bd9Sstevel@tonic-gate #endif
80ab25eeb5Syz 
817c478bd9Sstevel@tonic-gate /* END OF INCLUDES */
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate #if !defined(lint)
847c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
85ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $";
867c478bd9Sstevel@tonic-gate #endif
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /*
917c478bd9Sstevel@tonic-gate  * Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
927c478bd9Sstevel@tonic-gate  * NOTE: Insertion *MUST* be from greatest range to least for it to work!
937c478bd9Sstevel@tonic-gate  * These should be replaced, eventually, by something else - most notably a
947c478bd9Sstevel@tonic-gate  * interval searching method.  The important feature is to be able to find
957c478bd9Sstevel@tonic-gate  * the best match.
967c478bd9Sstevel@tonic-gate  *
977c478bd9Sstevel@tonic-gate  * So why not use a radix tree for this?  As the first line implies, it
987c478bd9Sstevel@tonic-gate  * has been written to work with a _range_ of addresses.  A range is not
997c478bd9Sstevel@tonic-gate  * necessarily a match with any given netmask so what we end up dealing
1007c478bd9Sstevel@tonic-gate  * with is an interval tree.  Implementations of these are hard to find
1017c478bd9Sstevel@tonic-gate  * and the one herein is far from bug free.
1027c478bd9Sstevel@tonic-gate  *
1037c478bd9Sstevel@tonic-gate  * Sigh, in the end I became convinced that the bugs the code contained did
1047c478bd9Sstevel@tonic-gate  * not make it worthwhile not using radix trees.  For now the radix tree from
1057c478bd9Sstevel@tonic-gate  * 4.4 BSD is used, but this is not viewed as a long term solution.
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate #ifdef TEST_POOL
1097c478bd9Sstevel@tonic-gate void treeprint __P((ip_pool_t *));
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate int
main(argc,argv)1127c478bd9Sstevel@tonic-gate main(argc, argv)
1137c478bd9Sstevel@tonic-gate 	int argc;
1147c478bd9Sstevel@tonic-gate 	char *argv[];
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 	addrfamily_t a, b;
1177c478bd9Sstevel@tonic-gate 	iplookupop_t op;
1187c478bd9Sstevel@tonic-gate 	ip_pool_t *ipo;
1197c478bd9Sstevel@tonic-gate 	i6addr_t ip;
120*de22af4eSJohn Ojemann 	fr_info_t fin;
1217c478bd9Sstevel@tonic-gate 
122f4b3ec61Sdh 	RWLOCK_INIT(&ifs->ifs_ip_poolrw, "poolrw");
123f4b3ec61Sdh 	ip_pool_init(ifs);
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	bzero((char *)&a, sizeof(a));
1267c478bd9Sstevel@tonic-gate 	bzero((char *)&b, sizeof(b));
1277c478bd9Sstevel@tonic-gate 	bzero((char *)&ip, sizeof(ip));
1287c478bd9Sstevel@tonic-gate 	bzero((char *)&op, sizeof(op));
1297c478bd9Sstevel@tonic-gate 	strcpy(op.iplo_name, "0");
1307c478bd9Sstevel@tonic-gate 
131f4b3ec61Sdh 	if (ip_pool_create(&op, ifs) == 0)
132f4b3ec61Sdh 		ipo = ip_pool_find(0, "0", ifs);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a010203;
1357c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffffffff;
136f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 1, ifs);
137f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a000000;
1407c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xff000000;
141f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 0, ifs);
142f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 0, ifs);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a010100;
1457c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffffff00;
146f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 1, ifs);
147f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a010200;
1507c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffffff00;
151f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 0, ifs);
152f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 0, ifs);
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a010000;
1557c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffff0000;
156f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 1, ifs);
157f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	a.adf_addr.in4.s_addr = 0x0a01020f;
1607c478bd9Sstevel@tonic-gate 	b.adf_addr.in4.s_addr = 0xffffffff;
161f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 1, ifs);
162f4b3ec61Sdh 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1637c478bd9Sstevel@tonic-gate #ifdef	DEBUG_POOL
1647c478bd9Sstevel@tonic-gate treeprint(ipo);
1657c478bd9Sstevel@tonic-gate #endif
166*de22af4eSJohn Ojemann 	fin.fin_plen = 20;
1677c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a00aabb;
1687c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
169*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a000001;
1727c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
173*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a000101;
1767c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
177*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a010001;
1807c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
181*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a010101;
1847c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
185*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a010201;
1887c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
189*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a010203;
1927c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
193*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0a01020f;
1967c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
197*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	ip.in4.s_addr = 0x0b00aabb;
2007c478bd9Sstevel@tonic-gate 	printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
201*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate #ifdef	DEBUG_POOL
2047c478bd9Sstevel@tonic-gate treeprint(ipo);
2057c478bd9Sstevel@tonic-gate #endif
2067c478bd9Sstevel@tonic-gate 
207f4b3ec61Sdh 	ip_pool_fini(ifs);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	return 0;
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate void
treeprint(ipo)2147c478bd9Sstevel@tonic-gate treeprint(ipo)
2157c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
2167c478bd9Sstevel@tonic-gate {
2177c478bd9Sstevel@tonic-gate 	ip_pool_node_t *c;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
2207c478bd9Sstevel@tonic-gate 		printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
2217c478bd9Sstevel@tonic-gate 			c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
2227c478bd9Sstevel@tonic-gate 			c->ipn_mask.adf_addr.in4.s_addr,
2237c478bd9Sstevel@tonic-gate 			c->ipn_info, c->ipn_hits);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate #endif /* TEST_POOL */
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
2297c478bd9Sstevel@tonic-gate /* Function:    ip_pool_init                                                */
2307c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
2317c478bd9Sstevel@tonic-gate /*                                                                          */
2327c478bd9Sstevel@tonic-gate /* Initialise the routing table data structures where required.             */
2337c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ip_pool_init(ifs)234f4b3ec61Sdh int ip_pool_init(ifs)
235f4b3ec61Sdh ipf_stack_t *ifs;
2367c478bd9Sstevel@tonic-gate {
237ab25eeb5Syz 
238f4b3ec61Sdh 	bzero(&ifs->ifs_ipoolstat, sizeof (ip_pool_stat_t));
2397c478bd9Sstevel@tonic-gate 
240c793af95Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
2417c478bd9Sstevel@tonic-gate 	rn_init();
2427c478bd9Sstevel@tonic-gate #endif
2437c478bd9Sstevel@tonic-gate 	return 0;
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
2487c478bd9Sstevel@tonic-gate /* Function:    ip_pool_fini                                                */
2497c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
2507c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ipf_global)                                           */
2517c478bd9Sstevel@tonic-gate /*                                                                          */
2527c478bd9Sstevel@tonic-gate /* Clean up all the pool data structures allocated and call the cleanup     */
2537c478bd9Sstevel@tonic-gate /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
2547c478bd9Sstevel@tonic-gate /* used to delete the pools one by one to ensure they're properly freed up. */
2557c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ip_pool_fini(ifs)256f4b3ec61Sdh void ip_pool_fini(ifs)
257f4b3ec61Sdh ipf_stack_t *ifs;
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate 	ip_pool_t *p, *q;
2607c478bd9Sstevel@tonic-gate 	iplookupop_t op;
2617c478bd9Sstevel@tonic-gate 	int i;
2627c478bd9Sstevel@tonic-gate 
263f4b3ec61Sdh 	ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	for (i = 0; i <= IPL_LOGMAX; i++) {
266f4b3ec61Sdh 		for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) {
2677c478bd9Sstevel@tonic-gate 			op.iplo_unit = i;
2687c478bd9Sstevel@tonic-gate 			(void)strncpy(op.iplo_name, p->ipo_name,
2697c478bd9Sstevel@tonic-gate 				sizeof(op.iplo_name));
2707c478bd9Sstevel@tonic-gate 			q = p->ipo_next;
271f4b3ec61Sdh 			(void) ip_pool_destroy(&op, ifs);
2727c478bd9Sstevel@tonic-gate 		}
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 
275c793af95Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
2767c478bd9Sstevel@tonic-gate 	rn_fini();
2777c478bd9Sstevel@tonic-gate #endif
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate 
280ab25eeb5Syz 
2817663b816Sml /* ------------------------------------------------------------------------ */
2827663b816Sml /* Function:    ip_pool_statistics                                          */
2837663b816Sml /* Returns:     int     - 0 = success, else error                           */
2847663b816Sml /* Parameters:  op(I)   - pointer to lookup operation arguments             */
2857663b816Sml /*                                                                          */
2867663b816Sml /* Copy the current statistics out into user space, collecting pool list    */
2877663b816Sml /* pointers as appropriate for later use.                                   */
2887663b816Sml /* ------------------------------------------------------------------------ */
ip_pool_statistics(op,ifs)289f4b3ec61Sdh int ip_pool_statistics(op, ifs)
2907663b816Sml iplookupop_t *op;
291f4b3ec61Sdh ipf_stack_t *ifs;
2927663b816Sml {
2937663b816Sml 	ip_pool_stat_t stats;
2947663b816Sml 	int unit, i, err = 0;
2957663b816Sml 
296f4b3ec61Sdh 	if (op->iplo_size != sizeof(ip_pool_stat_t))
2977663b816Sml 		return EINVAL;
2987663b816Sml 
299f4b3ec61Sdh 	bcopy((char *)&ifs->ifs_ipoolstat, (char *)&stats, sizeof(stats));
3007663b816Sml 	unit = op->iplo_unit;
3017663b816Sml 	if (unit == IPL_LOGALL) {
3027663b816Sml 		for (i = 0; i < IPL_LOGSIZE; i++)
303f4b3ec61Sdh 			stats.ipls_list[i] = ifs->ifs_ip_pool_list[i];
3047663b816Sml 	} else if (unit >= 0 && unit < IPL_LOGSIZE) {
305ab25eeb5Syz 		if (op->iplo_name[0] != '\0')
306ab25eeb5Syz 			stats.ipls_list[unit] = ip_pool_find(unit,
307f4b3ec61Sdh 							     op->iplo_name, ifs);
308ab25eeb5Syz 		else
309f4b3ec61Sdh 			stats.ipls_list[unit] = ifs->ifs_ip_pool_list[unit];
3107663b816Sml 	} else
3117663b816Sml 		err = EINVAL;
3127663b816Sml 	if (err == 0)
3137663b816Sml 		err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
3147663b816Sml 	return err;
3157663b816Sml }
3167663b816Sml 
3177c478bd9Sstevel@tonic-gate 
318ab25eeb5Syz 
3197c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3207c478bd9Sstevel@tonic-gate /* Function:    ip_pool_find                                                */
3217c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
3227c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
3237c478bd9Sstevel@tonic-gate /*                                                                          */
3247c478bd9Sstevel@tonic-gate /* Find a matching pool inside the collection of pools for a particular     */
3257c478bd9Sstevel@tonic-gate /* device, indicated by the unit number.                                    */
3267c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ip_pool_find(unit,name,ifs)327f4b3ec61Sdh void *ip_pool_find(unit, name, ifs)
3287c478bd9Sstevel@tonic-gate int unit;
3297c478bd9Sstevel@tonic-gate char *name;
330f4b3ec61Sdh ipf_stack_t *ifs;
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate 	ip_pool_t *p;
3337c478bd9Sstevel@tonic-gate 
334f4b3ec61Sdh 	for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; p = p->ipo_next)
335ab25eeb5Syz 		if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
3367c478bd9Sstevel@tonic-gate 			break;
3377c478bd9Sstevel@tonic-gate 	return p;
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3427c478bd9Sstevel@tonic-gate /* Function:    ip_pool_findeq                                              */
3437c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
3447c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
345ab25eeb5Syz /*              addr(I) - pointer to address information to delete          */
3467c478bd9Sstevel@tonic-gate /*              mask(I) -                                                   */
3477c478bd9Sstevel@tonic-gate /*                                                                          */
3487c478bd9Sstevel@tonic-gate /* Searches for an exact match of an entry in the pool.                     */
3497c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ip_pool_findeq(ipo,addr,mask)3507c478bd9Sstevel@tonic-gate ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
3517c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
3527663b816Sml addrfamily_t *addr, *mask;
3537c478bd9Sstevel@tonic-gate {
3547c478bd9Sstevel@tonic-gate 	struct radix_node *n;
355ab25eeb5Syz 	SPL_INT(s);
3567c478bd9Sstevel@tonic-gate 
357ab25eeb5Syz 	SPL_NET(s);
3587c478bd9Sstevel@tonic-gate 	n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
359ab25eeb5Syz 	SPL_X(s);
3607c478bd9Sstevel@tonic-gate 	return (ip_pool_node_t *)n;
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3657c478bd9Sstevel@tonic-gate /* Function:    ip_pool_search                                              */
366ab25eeb5Syz /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve/no match    */
3677c478bd9Sstevel@tonic-gate /* Parameters:  tptr(I)    - pointer to the pool to search                  */
3687c478bd9Sstevel@tonic-gate /*              version(I) - IP protocol version (4 or 6)                   */
3697c478bd9Sstevel@tonic-gate /*              dptr(I)    - pointer to address information                 */
370*de22af4eSJohn Ojemann /*		fin	   - pointer to packet information		    */
371*de22af4eSJohn Ojemann /*		ifs	   - ipf stack instance				    */
3727c478bd9Sstevel@tonic-gate /*                                                                          */
3737c478bd9Sstevel@tonic-gate /* Search the pool for a given address and return a search result.          */
3747c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ip_pool_search(tptr,version,dptr,fin,ifs)375*de22af4eSJohn Ojemann int ip_pool_search(tptr, version, dptr, fin, ifs)
3767c478bd9Sstevel@tonic-gate void *tptr;
3777c478bd9Sstevel@tonic-gate int version;
3787c478bd9Sstevel@tonic-gate void *dptr;
379*de22af4eSJohn Ojemann fr_info_t *fin;
380f4b3ec61Sdh ipf_stack_t *ifs;
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate 	struct radix_node *rn;
3837c478bd9Sstevel@tonic-gate 	ip_pool_node_t *m;
3847c478bd9Sstevel@tonic-gate 	i6addr_t *addr;
3857c478bd9Sstevel@tonic-gate 	addrfamily_t v;
3867c478bd9Sstevel@tonic-gate 	ip_pool_t *ipo;
3877c478bd9Sstevel@tonic-gate 	int rv;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	ipo = tptr;
3907c478bd9Sstevel@tonic-gate 	if (ipo == NULL)
3917c478bd9Sstevel@tonic-gate 		return -1;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	rv = 1;
3947c478bd9Sstevel@tonic-gate 	m = NULL;
3957c478bd9Sstevel@tonic-gate 	addr = (i6addr_t *)dptr;
3967c478bd9Sstevel@tonic-gate 	bzero(&v, sizeof(v));
3977c478bd9Sstevel@tonic-gate 	v.adf_len = offsetof(addrfamily_t, adf_addr);
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	if (version == 4) {
4007c478bd9Sstevel@tonic-gate 		v.adf_len += sizeof(addr->in4);
4017c478bd9Sstevel@tonic-gate 		v.adf_addr.in4 = addr->in4;
4027c478bd9Sstevel@tonic-gate #ifdef USE_INET6
4037c478bd9Sstevel@tonic-gate 	} else if (version == 6) {
4047c478bd9Sstevel@tonic-gate 		v.adf_len += sizeof(addr->in6);
4057c478bd9Sstevel@tonic-gate 		v.adf_addr.in6 = addr->in6;
4067c478bd9Sstevel@tonic-gate #endif
4077c478bd9Sstevel@tonic-gate 	} else
4087c478bd9Sstevel@tonic-gate 		return -1;
4097c478bd9Sstevel@tonic-gate 
410f4b3ec61Sdh 	READ_ENTER(&ifs->ifs_ip_poolrw);
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
4157c478bd9Sstevel@tonic-gate 		m = (ip_pool_node_t *)rn;
4167c478bd9Sstevel@tonic-gate 		ipo->ipo_hits++;
4177c478bd9Sstevel@tonic-gate 		m->ipn_hits++;
418*de22af4eSJohn Ojemann 		m->ipn_bytes += fin->fin_plen;
4197c478bd9Sstevel@tonic-gate 		rv = m->ipn_info;
4207c478bd9Sstevel@tonic-gate 	}
421f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
4227c478bd9Sstevel@tonic-gate 	return rv;
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4277c478bd9Sstevel@tonic-gate /* Function:    ip_pool_insert                                              */
4287c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
4297c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
4307663b816Sml /*              addr(I) - IPv4/6 address being added as a node              */
4317663b816Sml /*              mask(I) - IPv4/6 netmask to with the node being added       */
4327c478bd9Sstevel@tonic-gate /*              info(I) - extra information to store in this node.          */
4337c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw)                                            */
4347c478bd9Sstevel@tonic-gate /*                                                                          */
4357c478bd9Sstevel@tonic-gate /* Add another node to the pool given by ipo.  The three parameters passed  */
4367c478bd9Sstevel@tonic-gate /* in (addr, mask, info) shold all be stored in the node.                   */
4377c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ip_pool_insert(ipo,addr,mask,info,ifs)438f4b3ec61Sdh int ip_pool_insert(ipo, addr, mask, info, ifs)
4397c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
4407663b816Sml addrfamily_t *addr, *mask;
4417c478bd9Sstevel@tonic-gate int info;
442f4b3ec61Sdh ipf_stack_t *ifs;
4437c478bd9Sstevel@tonic-gate {
4447c478bd9Sstevel@tonic-gate 	struct radix_node *rn;
4457c478bd9Sstevel@tonic-gate 	ip_pool_node_t *x;
4467c478bd9Sstevel@tonic-gate 
447f4b3ec61Sdh 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	KMALLOC(x, ip_pool_node_t *);
4507c478bd9Sstevel@tonic-gate 	if (x == NULL) {
4517c478bd9Sstevel@tonic-gate 		return ENOMEM;
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	bzero(x, sizeof(*x));
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	x->ipn_info = info;
4577c478bd9Sstevel@tonic-gate 	(void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
4587c478bd9Sstevel@tonic-gate 
4597663b816Sml 	bcopy(addr, &x->ipn_addr, sizeof(*addr));
4607c478bd9Sstevel@tonic-gate 	x->ipn_addr.adf_len = sizeof(x->ipn_addr);
4617663b816Sml 	bcopy(mask, &x->ipn_mask, sizeof(*mask));
4627c478bd9Sstevel@tonic-gate 	x->ipn_mask.adf_len = sizeof(x->ipn_mask);
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
4657c478bd9Sstevel@tonic-gate 					ipo->ipo_head, x->ipn_nodes);
4667c478bd9Sstevel@tonic-gate #ifdef	DEBUG_POOL
4677c478bd9Sstevel@tonic-gate 	printf("Added %p at %p\n", x, rn);
4687c478bd9Sstevel@tonic-gate #endif
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	if (rn == NULL) {
4717c478bd9Sstevel@tonic-gate 		KFREE(x);
4727c478bd9Sstevel@tonic-gate 		return ENOMEM;
4737c478bd9Sstevel@tonic-gate 	}
4747c478bd9Sstevel@tonic-gate 
475f4b3ec61Sdh 	x->ipn_ref = 1;
4767c478bd9Sstevel@tonic-gate 	x->ipn_next = ipo->ipo_list;
4777c478bd9Sstevel@tonic-gate 	x->ipn_pnext = &ipo->ipo_list;
4787c478bd9Sstevel@tonic-gate 	if (ipo->ipo_list != NULL)
4797c478bd9Sstevel@tonic-gate 		ipo->ipo_list->ipn_pnext = &x->ipn_next;
4807c478bd9Sstevel@tonic-gate 	ipo->ipo_list = x;
4817c478bd9Sstevel@tonic-gate 
482f4b3ec61Sdh 	ifs->ifs_ipoolstat.ipls_nodes++;
48308254dd3Syz 
4847c478bd9Sstevel@tonic-gate 	return 0;
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4897c478bd9Sstevel@tonic-gate /* Function:    ip_pool_create                                              */
4907c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
4917c478bd9Sstevel@tonic-gate /* Parameters:  op(I) - pointer to iplookup struct with call details        */
4927c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw)                                            */
4937c478bd9Sstevel@tonic-gate /*                                                                          */
4947c478bd9Sstevel@tonic-gate /* Creates a new group according to the paramters passed in via the         */
4957c478bd9Sstevel@tonic-gate /* iplookupop structure.  Does not check to see if the group already exists */
4967c478bd9Sstevel@tonic-gate /* when being inserted - assume this has already been done.  If the pool is */
4977c478bd9Sstevel@tonic-gate /* marked as being anonymous, give it a new, unique, identifier.  Call any  */
4987c478bd9Sstevel@tonic-gate /* other functions required to initialise the structure.                    */
4997c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ip_pool_create(op,ifs)500f4b3ec61Sdh int ip_pool_create(op, ifs)
5017c478bd9Sstevel@tonic-gate iplookupop_t *op;
502f4b3ec61Sdh ipf_stack_t *ifs;
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate 	char name[FR_GROUPLEN];
5057c478bd9Sstevel@tonic-gate 	int poolnum, unit;
5067c478bd9Sstevel@tonic-gate 	ip_pool_t *h;
5077c478bd9Sstevel@tonic-gate 
508f4b3ec61Sdh 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	KMALLOC(h, ip_pool_t *);
5117c478bd9Sstevel@tonic-gate 	if (h == NULL)
5127c478bd9Sstevel@tonic-gate 		return ENOMEM;
5137c478bd9Sstevel@tonic-gate 	bzero(h, sizeof(*h));
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	if (rn_inithead((void **)&h->ipo_head,
5167c478bd9Sstevel@tonic-gate 			offsetof(addrfamily_t, adf_addr) << 3) == 0) {
5177c478bd9Sstevel@tonic-gate 		KFREE(h);
5187c478bd9Sstevel@tonic-gate 		return ENOMEM;
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	unit = op->iplo_unit;
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	if ((op->iplo_arg & IPOOL_ANON) != 0) {
5247c478bd9Sstevel@tonic-gate 		ip_pool_t *p;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		poolnum = IPOOL_ANON;
527ab25eeb5Syz 
528ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL)
529ab25eeb5Syz 		(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
530ab25eeb5Syz #else
5317c478bd9Sstevel@tonic-gate 		(void)sprintf(name, "%x", poolnum);
532ab25eeb5Syz #endif
533ab25eeb5Syz 
534f4b3ec61Sdh 		for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; ) {
535ab25eeb5Syz 			if (strncmp(name, p->ipo_name,
536ab25eeb5Syz 				    sizeof(p->ipo_name)) == 0) {
5377c478bd9Sstevel@tonic-gate 				poolnum++;
538ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL)
539ab25eeb5Syz 				(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
540ab25eeb5Syz #else
5417c478bd9Sstevel@tonic-gate 				(void)sprintf(name, "%x", poolnum);
542ab25eeb5Syz #endif
543f4b3ec61Sdh 				p = ifs->ifs_ip_pool_list[unit];
5447c478bd9Sstevel@tonic-gate 			} else
5457c478bd9Sstevel@tonic-gate 				p = p->ipo_next;
5467c478bd9Sstevel@tonic-gate 		}
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 		(void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
5497c478bd9Sstevel@tonic-gate 	} else {
5507c478bd9Sstevel@tonic-gate 		(void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
5517c478bd9Sstevel@tonic-gate 	}
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	h->ipo_ref = 1;
5547c478bd9Sstevel@tonic-gate 	h->ipo_list = NULL;
5557c478bd9Sstevel@tonic-gate 	h->ipo_unit = unit;
556f4b3ec61Sdh 	h->ipo_next = ifs->ifs_ip_pool_list[unit];
557f4b3ec61Sdh 	if (ifs->ifs_ip_pool_list[unit] != NULL)
558f4b3ec61Sdh 		ifs->ifs_ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
559f4b3ec61Sdh 	h->ipo_pnext = &ifs->ifs_ip_pool_list[unit];
560f4b3ec61Sdh 	ifs->ifs_ip_pool_list[unit] = h;
56108254dd3Syz 
562f4b3ec61Sdh 	ifs->ifs_ipoolstat.ipls_pools++;
56308254dd3Syz 
5647c478bd9Sstevel@tonic-gate 	return 0;
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
5697c478bd9Sstevel@tonic-gate /* Function:    ip_pool_remove                                              */
5707c478bd9Sstevel@tonic-gate /* Returns:     int    - 0 = success, else error                            */
5717c478bd9Sstevel@tonic-gate /* Parameters:  ipo(I) - pointer to the pool to remove the node from.       */
5727c478bd9Sstevel@tonic-gate /*              ipe(I) - address being deleted as a node                    */
5737c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw)                                            */
5747c478bd9Sstevel@tonic-gate /*                                                                          */
5757c478bd9Sstevel@tonic-gate /* Add another node to the pool given by ipo.  The three parameters passed  */
5767c478bd9Sstevel@tonic-gate /* in (addr, mask, info) shold all be stored in the node.                   */
5777c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ip_pool_remove(ipo,ipe,ifs)578f4b3ec61Sdh int ip_pool_remove(ipo, ipe, ifs)
5797c478bd9Sstevel@tonic-gate ip_pool_t *ipo;
5807c478bd9Sstevel@tonic-gate ip_pool_node_t *ipe;
581f4b3ec61Sdh ipf_stack_t *ifs;
5827c478bd9Sstevel@tonic-gate {
5837c478bd9Sstevel@tonic-gate 	ip_pool_node_t **ipp, *n;
5847c478bd9Sstevel@tonic-gate 
585f4b3ec61Sdh 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) {
5887c478bd9Sstevel@tonic-gate 		if (ipe == n) {
5897c478bd9Sstevel@tonic-gate 			*n->ipn_pnext = n->ipn_next;
5907c478bd9Sstevel@tonic-gate 			if (n->ipn_next)
5917c478bd9Sstevel@tonic-gate 				n->ipn_next->ipn_pnext = n->ipn_pnext;
5927c478bd9Sstevel@tonic-gate 			break;
5937c478bd9Sstevel@tonic-gate 		}
5947c478bd9Sstevel@tonic-gate 	}
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	if (n == NULL)
5977c478bd9Sstevel@tonic-gate 		return ENOENT;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
6007c478bd9Sstevel@tonic-gate 				   ipo->ipo_head);
6017c478bd9Sstevel@tonic-gate 	KFREE(n);
60208254dd3Syz 
603f4b3ec61Sdh 	ifs->ifs_ipoolstat.ipls_nodes--;
60408254dd3Syz 
6057c478bd9Sstevel@tonic-gate 	return 0;
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
6107c478bd9Sstevel@tonic-gate /* Function:    ip_pool_destroy                                             */
6117c478bd9Sstevel@tonic-gate /* Returns:     int    - 0 = success, else error                            */
6127c478bd9Sstevel@tonic-gate /* Parameters:  op(I)  -  information about the pool to remove              */
6137c478bd9Sstevel@tonic-gate /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
6147c478bd9Sstevel@tonic-gate /*                                                                          */
6157c478bd9Sstevel@tonic-gate /* Search for a pool using paramters passed in and if it's not otherwise    */
6167c478bd9Sstevel@tonic-gate /* busy, free it.                                                           */
6177c478bd9Sstevel@tonic-gate /*                                                                          */
6187c478bd9Sstevel@tonic-gate /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6197c478bd9Sstevel@tonic-gate /* may not be initialised, we can't use an ASSERT to enforce the locking    */
6207c478bd9Sstevel@tonic-gate /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
6217c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ip_pool_destroy(op,ifs)622f4b3ec61Sdh int ip_pool_destroy(op, ifs)
6237c478bd9Sstevel@tonic-gate iplookupop_t *op;
624f4b3ec61Sdh ipf_stack_t *ifs;
6257c478bd9Sstevel@tonic-gate {
6267c478bd9Sstevel@tonic-gate 	ip_pool_t *ipo;
6277c478bd9Sstevel@tonic-gate 
628f4b3ec61Sdh 	ipo = ip_pool_find(op->iplo_unit, op->iplo_name, ifs);
6297c478bd9Sstevel@tonic-gate 	if (ipo == NULL)
6307c478bd9Sstevel@tonic-gate 		return ESRCH;
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	if (ipo->ipo_ref != 1)
6337c478bd9Sstevel@tonic-gate 		return EBUSY;
6347c478bd9Sstevel@tonic-gate 
635f4b3ec61Sdh 	ip_pool_free(ipo, ifs);
6367c478bd9Sstevel@tonic-gate 	return 0;
6377c478bd9Sstevel@tonic-gate }
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 
640ab25eeb5Syz /* ------------------------------------------------------------------------ */
641