xref: /onnv-gate/usr/src/uts/common/inet/ipf/ip_pool.c (revision 3448:aaf16568054b)
12393Syz155240 /*
22393Syz155240  * Copyright (C) 1993-2001, 2003 by Darren Reed.
32393Syz155240  *
42393Syz155240  * See the IPFILTER.LICENCE file for details on licencing.
52393Syz155240  *
6*3448Sdh155122  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
72393Syz155240  * Use is subject to license terms.
82393Syz155240  */
92393Syz155240 
102393Syz155240 #pragma ident	"%Z%%M%	%I%	%E% SMI"
112393Syz155240 
122393Syz155240 #if defined(KERNEL) || defined(_KERNEL)
132393Syz155240 # undef KERNEL
142393Syz155240 # undef _KERNEL
152393Syz155240 # define        KERNEL	1
162393Syz155240 # define        _KERNEL	1
172393Syz155240 #endif
182393Syz155240 #if defined(__osf__)
192393Syz155240 # define _PROTO_NET_H_
202393Syz155240 #endif
212393Syz155240 #include <sys/errno.h>
222393Syz155240 #include <sys/types.h>
232393Syz155240 #include <sys/param.h>
242393Syz155240 #include <sys/file.h>
252393Syz155240 #if !defined(_KERNEL) && !defined(__KERNEL__)
262393Syz155240 # include <stdio.h>
272393Syz155240 # include <stdlib.h>
282393Syz155240 # include <string.h>
292393Syz155240 # define _KERNEL
302393Syz155240 # ifdef __OpenBSD__
312393Syz155240 struct file;
322393Syz155240 # endif
332393Syz155240 # include <sys/uio.h>
342393Syz155240 # undef _KERNEL
352393Syz155240 #else
362393Syz155240 # include <sys/systm.h>
372393Syz155240 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
382393Syz155240 #  include <sys/proc.h>
392393Syz155240 # endif
402393Syz155240 #endif
412393Syz155240 #include <sys/time.h>
422393Syz155240 #if !defined(linux)
432393Syz155240 # include <sys/protosw.h>
442393Syz155240 #endif
452393Syz155240 #include <sys/socket.h>
462393Syz155240 #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
472393Syz155240 # include <sys/mbuf.h>
482393Syz155240 #endif
492393Syz155240 #if defined(__SVR4) || defined(__svr4__)
502393Syz155240 # include <sys/filio.h>
512393Syz155240 # include <sys/byteorder.h>
522393Syz155240 # ifdef _KERNEL
532393Syz155240 #  include <sys/dditypes.h>
542393Syz155240 # endif
552393Syz155240 # include <sys/stream.h>
562393Syz155240 # include <sys/kmem.h>
572393Syz155240 #endif
582393Syz155240 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
592393Syz155240 # include <sys/malloc.h>
602393Syz155240 #endif
612393Syz155240 
622393Syz155240 #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
632393Syz155240      defined(__hpux) || defined(__sgi))
642393Syz155240 # ifdef __osf__
652393Syz155240 #  include <net/radix.h>
662393Syz155240 # endif
672393Syz155240 # include "radix_ipf_local.h"
682393Syz155240 # define _RADIX_H_
692393Syz155240 #endif
702393Syz155240 #include <net/if.h>
712393Syz155240 #include <netinet/in.h>
722393Syz155240 
73*3448Sdh155122 #include "netinet/ipf_stack.h"
742393Syz155240 #include "netinet/ip_compat.h"
752393Syz155240 #include "netinet/ip_fil.h"
762393Syz155240 #include "netinet/ip_pool.h"
772393Syz155240 
782393Syz155240 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
792393Syz155240       ((BSD >= 198911) && !defined(__osf__) && \
802393Syz155240       !defined(__hpux) && !defined(__sgi))
812393Syz155240 static int rn_freenode __P((struct radix_node *, void *));
822393Syz155240 #endif
832393Syz155240 
842393Syz155240 /* END OF INCLUDES */
852393Syz155240 
862393Syz155240 #if !defined(lint)
872393Syz155240 static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
882393Syz155240 static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $";
892393Syz155240 #endif
902393Syz155240 
912393Syz155240 #ifdef IPFILTER_LOOKUP
922393Syz155240 
932393Syz155240 /*
942393Syz155240  * Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
952393Syz155240  * NOTE: Insertion *MUST* be from greatest range to least for it to work!
962393Syz155240  * These should be replaced, eventually, by something else - most notably a
972393Syz155240  * interval searching method.  The important feature is to be able to find
982393Syz155240  * the best match.
992393Syz155240  *
1002393Syz155240  * So why not use a radix tree for this?  As the first line implies, it
1012393Syz155240  * has been written to work with a _range_ of addresses.  A range is not
1022393Syz155240  * necessarily a match with any given netmask so what we end up dealing
1032393Syz155240  * with is an interval tree.  Implementations of these are hard to find
1042393Syz155240  * and the one herein is far from bug free.
1052393Syz155240  *
1062393Syz155240  * Sigh, in the end I became convinced that the bugs the code contained did
1072393Syz155240  * not make it worthwhile not using radix trees.  For now the radix tree from
1082393Syz155240  * 4.4 BSD is used, but this is not viewed as a long term solution.
1092393Syz155240  */
1102393Syz155240 
1112393Syz155240 #ifdef TEST_POOL
1122393Syz155240 void treeprint __P((ip_pool_t *));
1132393Syz155240 
1142393Syz155240 int
1152393Syz155240 main(argc, argv)
1162393Syz155240 	int argc;
1172393Syz155240 	char *argv[];
1182393Syz155240 {
1192393Syz155240 	addrfamily_t a, b;
1202393Syz155240 	iplookupop_t op;
1212393Syz155240 	ip_pool_t *ipo;
1222393Syz155240 	i6addr_t ip;
1232393Syz155240 
124*3448Sdh155122 	RWLOCK_INIT(&ifs->ifs_ip_poolrw, "poolrw");
125*3448Sdh155122 	ip_pool_init(ifs);
1262393Syz155240 
1272393Syz155240 	bzero((char *)&a, sizeof(a));
1282393Syz155240 	bzero((char *)&b, sizeof(b));
1292393Syz155240 	bzero((char *)&ip, sizeof(ip));
1302393Syz155240 	bzero((char *)&op, sizeof(op));
1312393Syz155240 	strcpy(op.iplo_name, "0");
1322393Syz155240 
133*3448Sdh155122 	if (ip_pool_create(&op, ifs) == 0)
134*3448Sdh155122 		ipo = ip_pool_find(0, "0", ifs);
1352393Syz155240 
1362393Syz155240 	a.adf_addr.in4.s_addr = 0x0a010203;
1372393Syz155240 	b.adf_addr.in4.s_addr = 0xffffffff;
138*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
139*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1402393Syz155240 
1412393Syz155240 	a.adf_addr.in4.s_addr = 0x0a000000;
1422393Syz155240 	b.adf_addr.in4.s_addr = 0xff000000;
143*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
144*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
1452393Syz155240 
1462393Syz155240 	a.adf_addr.in4.s_addr = 0x0a010100;
1472393Syz155240 	b.adf_addr.in4.s_addr = 0xffffff00;
148*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
149*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1502393Syz155240 
1512393Syz155240 	a.adf_addr.in4.s_addr = 0x0a010200;
1522393Syz155240 	b.adf_addr.in4.s_addr = 0xffffff00;
153*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
154*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
1552393Syz155240 
1562393Syz155240 	a.adf_addr.in4.s_addr = 0x0a010000;
1572393Syz155240 	b.adf_addr.in4.s_addr = 0xffff0000;
158*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
159*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1602393Syz155240 
1612393Syz155240 	a.adf_addr.in4.s_addr = 0x0a01020f;
1622393Syz155240 	b.adf_addr.in4.s_addr = 0xffffffff;
163*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
164*3448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1652393Syz155240 #ifdef	DEBUG_POOL
1662393Syz155240 treeprint(ipo);
1672393Syz155240 #endif
1682393Syz155240 	ip.in4.s_addr = 0x0a00aabb;
1692393Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
170*3448Sdh155122 		ip_pool_search(ipo, 4, &ip, ifs));
1712393Syz155240 
1722393Syz155240 	ip.in4.s_addr = 0x0a000001;
1732393Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
174*3448Sdh155122 		ip_pool_search(ipo, 4, &ip, ifs));
1752393Syz155240 
1762393Syz155240 	ip.in4.s_addr = 0x0a000101;
1772393Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
178*3448Sdh155122 		ip_pool_search(ipo, 4, &ip, ifs));
1792393Syz155240 
1802393Syz155240 	ip.in4.s_addr = 0x0a010001;
1812393Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
182*3448Sdh155122 		ip_pool_search(ipo, 4, &ip, ifs));
1832393Syz155240 
1842393Syz155240 	ip.in4.s_addr = 0x0a010101;
1852393Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
186*3448Sdh155122 		ip_pool_search(ipo, 4, &ip, ifs));
1872393Syz155240 
1882393Syz155240 	ip.in4.s_addr = 0x0a010201;
1892393Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
190*3448Sdh155122 		ip_pool_search(ipo, 4, &ip, ifs));
1912393Syz155240 
1922393Syz155240 	ip.in4.s_addr = 0x0a010203;
1932393Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
194*3448Sdh155122 		ip_pool_search(ipo, 4, &ip, ifs));
1952393Syz155240 
1962393Syz155240 	ip.in4.s_addr = 0x0a01020f;
1972393Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
198*3448Sdh155122 		ip_pool_search(ipo, 4, &ip, ifs));
1992393Syz155240 
2002393Syz155240 	ip.in4.s_addr = 0x0b00aabb;
2012393Syz155240 	printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
202*3448Sdh155122 		ip_pool_search(ipo, 4, &ip, ifs));
2032393Syz155240 
2042393Syz155240 #ifdef	DEBUG_POOL
2052393Syz155240 treeprint(ipo);
2062393Syz155240 #endif
2072393Syz155240 
208*3448Sdh155122 	ip_pool_fini(ifs);
2092393Syz155240 
2102393Syz155240 	return 0;
2112393Syz155240 }
2122393Syz155240 
2132393Syz155240 
2142393Syz155240 void
2152393Syz155240 treeprint(ipo)
2162393Syz155240 ip_pool_t *ipo;
2172393Syz155240 {
2182393Syz155240 	ip_pool_node_t *c;
2192393Syz155240 
2202393Syz155240 	for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
2212393Syz155240 		printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
2222393Syz155240 			c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
2232393Syz155240 			c->ipn_mask.adf_addr.in4.s_addr,
2242393Syz155240 			c->ipn_info, c->ipn_hits);
2252393Syz155240 }
2262393Syz155240 #endif /* TEST_POOL */
2272393Syz155240 
2282393Syz155240 
2292393Syz155240 /* ------------------------------------------------------------------------ */
2302393Syz155240 /* Function:    ip_pool_init                                                */
2312393Syz155240 /* Returns:     int     - 0 = success, else error                           */
2322393Syz155240 /*                                                                          */
2332393Syz155240 /* Initialise the routing table data structures where required.             */
2342393Syz155240 /* ------------------------------------------------------------------------ */
235*3448Sdh155122 int ip_pool_init(ifs)
236*3448Sdh155122 ipf_stack_t *ifs;
2372393Syz155240 {
2382393Syz155240 
239*3448Sdh155122 	bzero(&ifs->ifs_ipoolstat, sizeof (ip_pool_stat_t));
2402393Syz155240 
2412535Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
2422393Syz155240 	rn_init();
2432393Syz155240 #endif
2442393Syz155240 	return 0;
2452393Syz155240 }
2462393Syz155240 
2472393Syz155240 
2482393Syz155240 /* ------------------------------------------------------------------------ */
2492393Syz155240 /* Function:    ip_pool_fini                                                */
2502393Syz155240 /* Returns:     int     - 0 = success, else error                           */
2512393Syz155240 /* Locks:       WRITE(ipf_global)                                           */
2522393Syz155240 /*                                                                          */
2532393Syz155240 /* Clean up all the pool data structures allocated and call the cleanup     */
2542393Syz155240 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
2552393Syz155240 /* used to delete the pools one by one to ensure they're properly freed up. */
2562393Syz155240 /* ------------------------------------------------------------------------ */
257*3448Sdh155122 void ip_pool_fini(ifs)
258*3448Sdh155122 ipf_stack_t *ifs;
2592393Syz155240 {
2602393Syz155240 	ip_pool_t *p, *q;
2612393Syz155240 	iplookupop_t op;
2622393Syz155240 	int i;
2632393Syz155240 
264*3448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0);
2652393Syz155240 
2662393Syz155240 	for (i = 0; i <= IPL_LOGMAX; i++) {
267*3448Sdh155122 		for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) {
2682393Syz155240 			op.iplo_unit = i;
2692393Syz155240 			(void)strncpy(op.iplo_name, p->ipo_name,
2702393Syz155240 				sizeof(op.iplo_name));
2712393Syz155240 			q = p->ipo_next;
272*3448Sdh155122 			(void) ip_pool_destroy(&op, ifs);
2732393Syz155240 		}
2742393Syz155240 	}
2752393Syz155240 
2762535Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
2772393Syz155240 	rn_fini();
2782393Syz155240 #endif
2792393Syz155240 }
2802393Syz155240 
2812393Syz155240 
2822393Syz155240 /* ------------------------------------------------------------------------ */
2832393Syz155240 /* Function:    ip_pool_statistics                                          */
2842393Syz155240 /* Returns:     int     - 0 = success, else error                           */
2852393Syz155240 /* Parameters:  op(I)   - pointer to lookup operation arguments             */
2862393Syz155240 /*                                                                          */
2872393Syz155240 /* Copy the current statistics out into user space, collecting pool list    */
2882393Syz155240 /* pointers as appropriate for later use.                                   */
2892393Syz155240 /* ------------------------------------------------------------------------ */
290*3448Sdh155122 int ip_pool_statistics(op, ifs)
2912393Syz155240 iplookupop_t *op;
292*3448Sdh155122 ipf_stack_t *ifs;
2932393Syz155240 {
2942393Syz155240 	ip_pool_stat_t stats;
2952393Syz155240 	int unit, i, err = 0;
2962393Syz155240 
297*3448Sdh155122 	if (op->iplo_size != sizeof(ip_pool_stat_t))
2982393Syz155240 		return EINVAL;
2992393Syz155240 
300*3448Sdh155122 	bcopy((char *)&ifs->ifs_ipoolstat, (char *)&stats, sizeof(stats));
3012393Syz155240 	unit = op->iplo_unit;
3022393Syz155240 	if (unit == IPL_LOGALL) {
3032393Syz155240 		for (i = 0; i < IPL_LOGSIZE; i++)
304*3448Sdh155122 			stats.ipls_list[i] = ifs->ifs_ip_pool_list[i];
3052393Syz155240 	} else if (unit >= 0 && unit < IPL_LOGSIZE) {
3062393Syz155240 		if (op->iplo_name[0] != '\0')
3072393Syz155240 			stats.ipls_list[unit] = ip_pool_find(unit,
308*3448Sdh155122 							     op->iplo_name, ifs);
3092393Syz155240 		else
310*3448Sdh155122 			stats.ipls_list[unit] = ifs->ifs_ip_pool_list[unit];
3112393Syz155240 	} else
3122393Syz155240 		err = EINVAL;
3132393Syz155240 	if (err == 0)
3142393Syz155240 		err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
3152393Syz155240 	return err;
3162393Syz155240 }
3172393Syz155240 
3182393Syz155240 
3192393Syz155240 
3202393Syz155240 /* ------------------------------------------------------------------------ */
3212393Syz155240 /* Function:    ip_pool_find                                                */
3222393Syz155240 /* Returns:     int     - 0 = success, else error                           */
3232393Syz155240 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
3242393Syz155240 /*                                                                          */
3252393Syz155240 /* Find a matching pool inside the collection of pools for a particular     */
3262393Syz155240 /* device, indicated by the unit number.                                    */
3272393Syz155240 /* ------------------------------------------------------------------------ */
328*3448Sdh155122 void *ip_pool_find(unit, name, ifs)
3292393Syz155240 int unit;
3302393Syz155240 char *name;
331*3448Sdh155122 ipf_stack_t *ifs;
3322393Syz155240 {
3332393Syz155240 	ip_pool_t *p;
3342393Syz155240 
335*3448Sdh155122 	for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; p = p->ipo_next)
3362393Syz155240 		if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
3372393Syz155240 			break;
3382393Syz155240 	return p;
3392393Syz155240 }
3402393Syz155240 
3412393Syz155240 
3422393Syz155240 /* ------------------------------------------------------------------------ */
3432393Syz155240 /* Function:    ip_pool_findeq                                              */
3442393Syz155240 /* Returns:     int     - 0 = success, else error                           */
3452393Syz155240 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
3462393Syz155240 /*              addr(I) - pointer to address information to delete          */
3472393Syz155240 /*              mask(I) -                                                   */
3482393Syz155240 /*                                                                          */
3492393Syz155240 /* Searches for an exact match of an entry in the pool.                     */
3502393Syz155240 /* ------------------------------------------------------------------------ */
3512393Syz155240 ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
3522393Syz155240 ip_pool_t *ipo;
3532393Syz155240 addrfamily_t *addr, *mask;
3542393Syz155240 {
3552393Syz155240 	struct radix_node *n;
3562393Syz155240 	SPL_INT(s);
3572393Syz155240 
3582393Syz155240 	SPL_NET(s);
3592393Syz155240 	n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
3602393Syz155240 	SPL_X(s);
3612393Syz155240 	return (ip_pool_node_t *)n;
3622393Syz155240 }
3632393Syz155240 
3642393Syz155240 
3652393Syz155240 /* ------------------------------------------------------------------------ */
3662393Syz155240 /* Function:    ip_pool_search                                              */
3672393Syz155240 /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve/no match    */
3682393Syz155240 /* Parameters:  tptr(I)    - pointer to the pool to search                  */
3692393Syz155240 /*              version(I) - IP protocol version (4 or 6)                   */
3702393Syz155240 /*              dptr(I)    - pointer to address information                 */
3712393Syz155240 /*                                                                          */
3722393Syz155240 /* Search the pool for a given address and return a search result.          */
3732393Syz155240 /* ------------------------------------------------------------------------ */
374*3448Sdh155122 int ip_pool_search(tptr, version, dptr, ifs)
3752393Syz155240 void *tptr;
3762393Syz155240 int version;
3772393Syz155240 void *dptr;
378*3448Sdh155122 ipf_stack_t *ifs;
3792393Syz155240 {
3802393Syz155240 	struct radix_node *rn;
3812393Syz155240 	ip_pool_node_t *m;
3822393Syz155240 	i6addr_t *addr;
3832393Syz155240 	addrfamily_t v;
3842393Syz155240 	ip_pool_t *ipo;
3852393Syz155240 	int rv;
3862393Syz155240 
3872393Syz155240 	ipo = tptr;
3882393Syz155240 	if (ipo == NULL)
3892393Syz155240 		return -1;
3902393Syz155240 
3912393Syz155240 	rv = 1;
3922393Syz155240 	m = NULL;
3932393Syz155240 	addr = (i6addr_t *)dptr;
3942393Syz155240 	bzero(&v, sizeof(v));
3952393Syz155240 	v.adf_len = offsetof(addrfamily_t, adf_addr);
3962393Syz155240 
3972393Syz155240 	if (version == 4) {
3982393Syz155240 		v.adf_len += sizeof(addr->in4);
3992393Syz155240 		v.adf_addr.in4 = addr->in4;
4002393Syz155240 #ifdef USE_INET6
4012393Syz155240 	} else if (version == 6) {
4022393Syz155240 		v.adf_len += sizeof(addr->in6);
4032393Syz155240 		v.adf_addr.in6 = addr->in6;
4042393Syz155240 #endif
4052393Syz155240 	} else
4062393Syz155240 		return -1;
4072393Syz155240 
408*3448Sdh155122 	READ_ENTER(&ifs->ifs_ip_poolrw);
4092393Syz155240 
4102393Syz155240 	rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
4112393Syz155240 
4122393Syz155240 	if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
4132393Syz155240 		m = (ip_pool_node_t *)rn;
4142393Syz155240 		ipo->ipo_hits++;
4152393Syz155240 		m->ipn_hits++;
4162393Syz155240 		rv = m->ipn_info;
4172393Syz155240 	}
418*3448Sdh155122 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
4192393Syz155240 	return rv;
4202393Syz155240 }
4212393Syz155240 
4222393Syz155240 
4232393Syz155240 /* ------------------------------------------------------------------------ */
4242393Syz155240 /* Function:    ip_pool_insert                                              */
4252393Syz155240 /* Returns:     int     - 0 = success, else error                           */
4262393Syz155240 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
4272393Syz155240 /*              addr(I) - IPv4/6 address being added as a node              */
4282393Syz155240 /*              mask(I) - IPv4/6 netmask to with the node being added       */
4292393Syz155240 /*              info(I) - extra information to store in this node.          */
4302393Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
4312393Syz155240 /*                                                                          */
4322393Syz155240 /* Add another node to the pool given by ipo.  The three parameters passed  */
4332393Syz155240 /* in (addr, mask, info) shold all be stored in the node.                   */
4342393Syz155240 /* ------------------------------------------------------------------------ */
435*3448Sdh155122 int ip_pool_insert(ipo, addr, mask, info, ifs)
4362393Syz155240 ip_pool_t *ipo;
4372393Syz155240 addrfamily_t *addr, *mask;
4382393Syz155240 int info;
439*3448Sdh155122 ipf_stack_t *ifs;
4402393Syz155240 {
4412393Syz155240 	struct radix_node *rn;
4422393Syz155240 	ip_pool_node_t *x;
4432393Syz155240 
444*3448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
4452393Syz155240 
4462393Syz155240 	KMALLOC(x, ip_pool_node_t *);
4472393Syz155240 	if (x == NULL) {
4482393Syz155240 		return ENOMEM;
4492393Syz155240 	}
4502393Syz155240 
4512393Syz155240 	bzero(x, sizeof(*x));
4522393Syz155240 
4532393Syz155240 	x->ipn_info = info;
4542393Syz155240 	(void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
4552393Syz155240 
4562393Syz155240 	bcopy(addr, &x->ipn_addr, sizeof(*addr));
4572393Syz155240 	x->ipn_addr.adf_len = sizeof(x->ipn_addr);
4582393Syz155240 	bcopy(mask, &x->ipn_mask, sizeof(*mask));
4592393Syz155240 	x->ipn_mask.adf_len = sizeof(x->ipn_mask);
4602393Syz155240 
4612393Syz155240 	rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
4622393Syz155240 					ipo->ipo_head, x->ipn_nodes);
4632393Syz155240 #ifdef	DEBUG_POOL
4642393Syz155240 	printf("Added %p at %p\n", x, rn);
4652393Syz155240 #endif
4662393Syz155240 
4672393Syz155240 	if (rn == NULL) {
4682393Syz155240 		KFREE(x);
4692393Syz155240 		return ENOMEM;
4702393Syz155240 	}
4712393Syz155240 
472*3448Sdh155122 	x->ipn_ref = 1;
4732393Syz155240 	x->ipn_next = ipo->ipo_list;
4742393Syz155240 	x->ipn_pnext = &ipo->ipo_list;
4752393Syz155240 	if (ipo->ipo_list != NULL)
4762393Syz155240 		ipo->ipo_list->ipn_pnext = &x->ipn_next;
4772393Syz155240 	ipo->ipo_list = x;
4782393Syz155240 
479*3448Sdh155122 	ifs->ifs_ipoolstat.ipls_nodes++;
4802393Syz155240 
4812393Syz155240 	return 0;
4822393Syz155240 }
4832393Syz155240 
4842393Syz155240 
4852393Syz155240 /* ------------------------------------------------------------------------ */
4862393Syz155240 /* Function:    ip_pool_create                                              */
4872393Syz155240 /* Returns:     int     - 0 = success, else error                           */
4882393Syz155240 /* Parameters:  op(I) - pointer to iplookup struct with call details        */
4892393Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
4902393Syz155240 /*                                                                          */
4912393Syz155240 /* Creates a new group according to the paramters passed in via the         */
4922393Syz155240 /* iplookupop structure.  Does not check to see if the group already exists */
4932393Syz155240 /* when being inserted - assume this has already been done.  If the pool is */
4942393Syz155240 /* marked as being anonymous, give it a new, unique, identifier.  Call any  */
4952393Syz155240 /* other functions required to initialise the structure.                    */
4962393Syz155240 /* ------------------------------------------------------------------------ */
497*3448Sdh155122 int ip_pool_create(op, ifs)
4982393Syz155240 iplookupop_t *op;
499*3448Sdh155122 ipf_stack_t *ifs;
5002393Syz155240 {
5012393Syz155240 	char name[FR_GROUPLEN];
5022393Syz155240 	int poolnum, unit;
5032393Syz155240 	ip_pool_t *h;
5042393Syz155240 
505*3448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
5062393Syz155240 
5072393Syz155240 	KMALLOC(h, ip_pool_t *);
5082393Syz155240 	if (h == NULL)
5092393Syz155240 		return ENOMEM;
5102393Syz155240 	bzero(h, sizeof(*h));
5112393Syz155240 
5122393Syz155240 	if (rn_inithead((void **)&h->ipo_head,
5132393Syz155240 			offsetof(addrfamily_t, adf_addr) << 3) == 0) {
5142393Syz155240 		KFREE(h);
5152393Syz155240 		return ENOMEM;
5162393Syz155240 	}
5172393Syz155240 
5182393Syz155240 	unit = op->iplo_unit;
5192393Syz155240 
5202393Syz155240 	if ((op->iplo_arg & IPOOL_ANON) != 0) {
5212393Syz155240 		ip_pool_t *p;
5222393Syz155240 
5232393Syz155240 		poolnum = IPOOL_ANON;
5242393Syz155240 
5252393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL)
5262393Syz155240 		(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
5272393Syz155240 #else
5282393Syz155240 		(void)sprintf(name, "%x", poolnum);
5292393Syz155240 #endif
5302393Syz155240 
531*3448Sdh155122 		for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; ) {
5322393Syz155240 			if (strncmp(name, p->ipo_name,
5332393Syz155240 				    sizeof(p->ipo_name)) == 0) {
5342393Syz155240 				poolnum++;
5352393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL)
5362393Syz155240 				(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
5372393Syz155240 #else
5382393Syz155240 				(void)sprintf(name, "%x", poolnum);
5392393Syz155240 #endif
540*3448Sdh155122 				p = ifs->ifs_ip_pool_list[unit];
5412393Syz155240 			} else
5422393Syz155240 				p = p->ipo_next;
5432393Syz155240 		}
5442393Syz155240 
5452393Syz155240 		(void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
5462393Syz155240 	} else {
5472393Syz155240 		(void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
5482393Syz155240 	}
5492393Syz155240 
5502393Syz155240 	h->ipo_ref = 1;
5512393Syz155240 	h->ipo_list = NULL;
5522393Syz155240 	h->ipo_unit = unit;
553*3448Sdh155122 	h->ipo_next = ifs->ifs_ip_pool_list[unit];
554*3448Sdh155122 	if (ifs->ifs_ip_pool_list[unit] != NULL)
555*3448Sdh155122 		ifs->ifs_ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
556*3448Sdh155122 	h->ipo_pnext = &ifs->ifs_ip_pool_list[unit];
557*3448Sdh155122 	ifs->ifs_ip_pool_list[unit] = h;
5582393Syz155240 
559*3448Sdh155122 	ifs->ifs_ipoolstat.ipls_pools++;
5602393Syz155240 
5612393Syz155240 	return 0;
5622393Syz155240 }
5632393Syz155240 
5642393Syz155240 
5652393Syz155240 /* ------------------------------------------------------------------------ */
5662393Syz155240 /* Function:    ip_pool_remove                                              */
5672393Syz155240 /* Returns:     int    - 0 = success, else error                            */
5682393Syz155240 /* Parameters:  ipo(I) - pointer to the pool to remove the node from.       */
5692393Syz155240 /*              ipe(I) - address being deleted as a node                    */
5702393Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
5712393Syz155240 /*                                                                          */
5722393Syz155240 /* Add another node to the pool given by ipo.  The three parameters passed  */
5732393Syz155240 /* in (addr, mask, info) shold all be stored in the node.                   */
5742393Syz155240 /* ------------------------------------------------------------------------ */
575*3448Sdh155122 int ip_pool_remove(ipo, ipe, ifs)
5762393Syz155240 ip_pool_t *ipo;
5772393Syz155240 ip_pool_node_t *ipe;
578*3448Sdh155122 ipf_stack_t *ifs;
5792393Syz155240 {
5802393Syz155240 	ip_pool_node_t **ipp, *n;
5812393Syz155240 
582*3448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
5832393Syz155240 
5842393Syz155240 	for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) {
5852393Syz155240 		if (ipe == n) {
5862393Syz155240 			*n->ipn_pnext = n->ipn_next;
5872393Syz155240 			if (n->ipn_next)
5882393Syz155240 				n->ipn_next->ipn_pnext = n->ipn_pnext;
5892393Syz155240 			break;
5902393Syz155240 		}
5912393Syz155240 	}
5922393Syz155240 
5932393Syz155240 	if (n == NULL)
5942393Syz155240 		return ENOENT;
5952393Syz155240 
5962393Syz155240 	ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
5972393Syz155240 				   ipo->ipo_head);
5982393Syz155240 	KFREE(n);
5992393Syz155240 
600*3448Sdh155122 	ifs->ifs_ipoolstat.ipls_nodes--;
6012393Syz155240 
6022393Syz155240 	return 0;
6032393Syz155240 }
6042393Syz155240 
6052393Syz155240 
6062393Syz155240 /* ------------------------------------------------------------------------ */
6072393Syz155240 /* Function:    ip_pool_destroy                                             */
6082393Syz155240 /* Returns:     int    - 0 = success, else error                            */
6092393Syz155240 /* Parameters:  op(I)  -  information about the pool to remove              */
6102393Syz155240 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
6112393Syz155240 /*                                                                          */
6122393Syz155240 /* Search for a pool using paramters passed in and if it's not otherwise    */
6132393Syz155240 /* busy, free it.                                                           */
6142393Syz155240 /*                                                                          */
6152393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6162393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
6172393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
6182393Syz155240 /* ------------------------------------------------------------------------ */
619*3448Sdh155122 int ip_pool_destroy(op, ifs)
6202393Syz155240 iplookupop_t *op;
621*3448Sdh155122 ipf_stack_t *ifs;
6222393Syz155240 {
6232393Syz155240 	ip_pool_t *ipo;
6242393Syz155240 
625*3448Sdh155122 	ipo = ip_pool_find(op->iplo_unit, op->iplo_name, ifs);
6262393Syz155240 	if (ipo == NULL)
6272393Syz155240 		return ESRCH;
6282393Syz155240 
6292393Syz155240 	if (ipo->ipo_ref != 1)
6302393Syz155240 		return EBUSY;
6312393Syz155240 
632*3448Sdh155122 	ip_pool_free(ipo, ifs);
6332393Syz155240 	return 0;
6342393Syz155240 }
6352393Syz155240 
6362393Syz155240 
6372393Syz155240 /* ------------------------------------------------------------------------ */
6382393Syz155240 /* Function:    ip_pool_flush                                               */
6392393Syz155240 /* Returns:     int    - number of pools deleted                            */
6402393Syz155240 /* Parameters:  fp(I)  - which pool(s) to flush                             */
6412393Syz155240 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
6422393Syz155240 /*                                                                          */
6432393Syz155240 /* Free all pools associated with the device that matches the unit number   */
6442393Syz155240 /* passed in with operation.                                                */
6452393Syz155240 /*                                                                          */
6462393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6472393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
6482393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
6492393Syz155240 /* ------------------------------------------------------------------------ */
650*3448Sdh155122 int ip_pool_flush(fp, ifs)
6512393Syz155240 iplookupflush_t *fp;
652*3448Sdh155122 ipf_stack_t *ifs;
6532393Syz155240 {
6542393Syz155240 	int i, num = 0, unit, err;
6552393Syz155240 	ip_pool_t *p, *q;
6562393Syz155240 	iplookupop_t op;
6572393Syz155240 
6582393Syz155240 	unit = fp->iplf_unit;
6592393Syz155240 
6602393Syz155240 	for (i = 0; i <= IPL_LOGMAX; i++) {
6612393Syz155240 		if (unit != IPLT_ALL && i != unit)
6622393Syz155240 			continue;
663*3448Sdh155122 		for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) {
6642393Syz155240 			op.iplo_unit = i;
6652393Syz155240 			(void)strncpy(op.iplo_name, p->ipo_name,
6662393Syz155240 				sizeof(op.iplo_name));
6672393Syz155240 			q = p->ipo_next;
668*3448Sdh155122 			err = ip_pool_destroy(&op, ifs);
6692393Syz155240 			if (err == 0)
6702393Syz155240 				num++;
6712393Syz155240 			else
6722393Syz155240 				break;
6732393Syz155240 		}
6742393Syz155240 	}
6752393Syz155240 	return num;
6762393Syz155240 }
6772393Syz155240 
6782393Syz155240 
6792393Syz155240 /* ------------------------------------------------------------------------ */
6802393Syz155240 /* Function:    ip_pool_free                                                */
6812393Syz155240 /* Returns:     void                                                        */
6822393Syz155240 /* Parameters:  ipo(I) -  pointer to pool structure                         */
6832393Syz155240 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
6842393Syz155240 /*                                                                          */
6852393Syz155240 /* Deletes the pool strucutre passed in from the list of pools and deletes  */
6862393Syz155240 /* all of the address information stored in it, including any tree data     */
6872393Syz155240 /* structures also allocated.                                               */
6882393Syz155240 /*                                                                          */
6892393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6902393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
6912393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
6922393Syz155240 /* ------------------------------------------------------------------------ */
693*3448Sdh155122 void ip_pool_free(ipo, ifs)
6942393Syz155240 ip_pool_t *ipo;
695*3448Sdh155122 ipf_stack_t *ifs;
6962393Syz155240 {
6972393Syz155240 	ip_pool_node_t *n;
6982393Syz155240 
6992393Syz155240 	while ((n = ipo->ipo_list) != NULL) {
7002393Syz155240 		ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
7012393Syz155240 					   ipo->ipo_head);
7022393Syz155240 
7032393Syz155240 		*n->ipn_pnext = n->ipn_next;
7042393Syz155240 		if (n->ipn_next)
7052393Syz155240 			n->ipn_next->ipn_pnext = n->ipn_pnext;
7062393Syz155240 
7072393Syz155240 		KFREE(n);
7082393Syz155240 
709*3448Sdh155122 		ifs->ifs_ipoolstat.ipls_nodes--;
7102393Syz155240 	}
7112393Syz155240 
7122393Syz155240 	ipo->ipo_list = NULL;
7132393Syz155240 	if (ipo->ipo_next != NULL)
7142393Syz155240 		ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
7152393Syz155240 	*ipo->ipo_pnext = ipo->ipo_next;
7162393Syz155240 	rn_freehead(ipo->ipo_head);
7172393Syz155240 	KFREE(ipo);
7182393Syz155240 
719*3448Sdh155122 	ifs->ifs_ipoolstat.ipls_pools--;
7202393Syz155240 }
7212393Syz155240 
7222393Syz155240 
7232393Syz155240 /* ------------------------------------------------------------------------ */
7242393Syz155240 /* Function:    ip_pool_deref                                               */
7252393Syz155240 /* Returns:     void                                                        */
7262393Syz155240 /* Parameters:  ipo(I) -  pointer to pool structure                         */
7272393Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
7282393Syz155240 /*                                                                          */
7292393Syz155240 /* Drop the number of known references to this pool structure by one and if */
7302393Syz155240 /* we arrive at zero known references, free it.                             */
7312393Syz155240 /* ------------------------------------------------------------------------ */
732*3448Sdh155122 void ip_pool_deref(ipo, ifs)
7332393Syz155240 ip_pool_t *ipo;
734*3448Sdh155122 ipf_stack_t *ifs;
7352393Syz155240 {
7362393Syz155240 
737*3448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
7382393Syz155240 
7392393Syz155240 	ipo->ipo_ref--;
7402393Syz155240 	if (ipo->ipo_ref == 0)
741*3448Sdh155122 		ip_pool_free(ipo, ifs);
742*3448Sdh155122 }
743*3448Sdh155122 
744*3448Sdh155122 
745*3448Sdh155122 
746*3448Sdh155122 void ip_pool_node_deref(ipn, ifs)
747*3448Sdh155122 ip_pool_node_t *ipn;
748*3448Sdh155122 ipf_stack_t *ifs;
749*3448Sdh155122 {
750*3448Sdh155122 
751*3448Sdh155122 	ipn->ipn_ref--;
752*3448Sdh155122 
753*3448Sdh155122 	if (ipn->ipn_ref == 0) {
754*3448Sdh155122 		KFREE(ipn);
755*3448Sdh155122 		ifs->ifs_ipoolstat.ipls_nodes--;
756*3448Sdh155122 	}
757*3448Sdh155122 }
758*3448Sdh155122 
759*3448Sdh155122 
760*3448Sdh155122 int ip_pool_getnext(token, ilp, ifs)
761*3448Sdh155122 ipftoken_t *token;
762*3448Sdh155122 ipflookupiter_t *ilp;
763*3448Sdh155122 ipf_stack_t *ifs;
764*3448Sdh155122 {
765*3448Sdh155122 	ip_pool_node_t *node, zn, *nextnode;
766*3448Sdh155122 	ip_pool_t *ipo, zp, *nextipo;
767*3448Sdh155122 	int err;
768*3448Sdh155122 
769*3448Sdh155122 	err = 0;
770*3448Sdh155122 	node = NULL;
771*3448Sdh155122 	nextnode = NULL;
772*3448Sdh155122 	ipo = NULL;
773*3448Sdh155122 	nextipo = NULL;
774*3448Sdh155122 
775*3448Sdh155122 	READ_ENTER(&ifs->ifs_ip_poolrw);
776*3448Sdh155122 
777*3448Sdh155122 	switch (ilp->ili_otype)
778*3448Sdh155122 	{
779*3448Sdh155122 	case IPFLOOKUPITER_LIST :
780*3448Sdh155122 		ipo = token->ipt_data;
781*3448Sdh155122 		if (ipo == NULL) {
782*3448Sdh155122 			nextipo = ifs->ifs_ip_pool_list[(int)ilp->ili_unit];
783*3448Sdh155122 		} else {
784*3448Sdh155122 			nextipo = ipo->ipo_next;
785*3448Sdh155122 		}
786*3448Sdh155122 
787*3448Sdh155122 		if (nextipo != NULL) {
788*3448Sdh155122 			if (nextipo->ipo_next == NULL)
789*3448Sdh155122 				token->ipt_alive = 0;
790*3448Sdh155122 			else {
791*3448Sdh155122 				ATOMIC_INC(nextipo->ipo_ref);
792*3448Sdh155122 			}
793*3448Sdh155122 		} else {
794*3448Sdh155122 			bzero((char *)&zp, sizeof(zp));
795*3448Sdh155122 			nextipo = &zp;
796*3448Sdh155122 		}
797*3448Sdh155122 		break;
798*3448Sdh155122 
799*3448Sdh155122 	case IPFLOOKUPITER_NODE :
800*3448Sdh155122 		node = token->ipt_data;
801*3448Sdh155122 		if (node == NULL) {
802*3448Sdh155122 			ipo = ip_pool_find(ilp->ili_unit, ilp->ili_name, ifs);
803*3448Sdh155122 			if (ipo == NULL)
804*3448Sdh155122 				err = ESRCH;
805*3448Sdh155122 			else {
806*3448Sdh155122 				nextnode = ipo->ipo_list;
807*3448Sdh155122 				ipo = NULL;
808*3448Sdh155122 			}
809*3448Sdh155122 		} else {
810*3448Sdh155122 			nextnode = node->ipn_next;
811*3448Sdh155122 		}
812*3448Sdh155122 
813*3448Sdh155122 		if (nextnode != NULL) {
814*3448Sdh155122 			if (nextnode->ipn_next == NULL)
815*3448Sdh155122 				token->ipt_alive = 0;
816*3448Sdh155122 			else {
817*3448Sdh155122 				ATOMIC_INC(nextnode->ipn_ref);
818*3448Sdh155122 			}
819*3448Sdh155122 		} else {
820*3448Sdh155122 			bzero((char *)&zn, sizeof(zn));
821*3448Sdh155122 			nextnode = &zn;
822*3448Sdh155122 		}
823*3448Sdh155122 		break;
824*3448Sdh155122 	default :
825*3448Sdh155122 		err = EINVAL;
826*3448Sdh155122 		break;
827*3448Sdh155122 	}
828*3448Sdh155122 
829*3448Sdh155122 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
830*3448Sdh155122 
831*3448Sdh155122 	if (err != 0)
832*3448Sdh155122 		return err;
833*3448Sdh155122 
834*3448Sdh155122 	switch (ilp->ili_otype)
835*3448Sdh155122 	{
836*3448Sdh155122 	case IPFLOOKUPITER_LIST :
837*3448Sdh155122 		if (ipo != NULL) {
838*3448Sdh155122 			WRITE_ENTER(&ifs->ifs_ip_poolrw);
839*3448Sdh155122 			ip_pool_deref(ipo, ifs);
840*3448Sdh155122 			RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
841*3448Sdh155122 		}
842*3448Sdh155122 		token->ipt_data = nextipo;
843*3448Sdh155122 		err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo));
844*3448Sdh155122 		if (err != 0)
845*3448Sdh155122 			err = EFAULT;
846*3448Sdh155122 		break;
847*3448Sdh155122 
848*3448Sdh155122 	case IPFLOOKUPITER_NODE :
849*3448Sdh155122 		if (node != NULL) {
850*3448Sdh155122 			WRITE_ENTER(&ifs->ifs_ip_poolrw);
851*3448Sdh155122 			ip_pool_node_deref(node, ifs);
852*3448Sdh155122 			RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
853*3448Sdh155122 		}
854*3448Sdh155122 		token->ipt_data = nextnode;
855*3448Sdh155122 		err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
856*3448Sdh155122 		if (err != 0)
857*3448Sdh155122 			err = EFAULT;
858*3448Sdh155122 		break;
859*3448Sdh155122 	}
860*3448Sdh155122 
861*3448Sdh155122 	return err;
862*3448Sdh155122 }
863*3448Sdh155122 
864*3448Sdh155122 
865*3448Sdh155122 void ip_pool_iterderef(otype, unit, data, ifs)
866*3448Sdh155122 u_int otype;
867*3448Sdh155122 int unit;
868*3448Sdh155122 void *data;
869*3448Sdh155122 ipf_stack_t *ifs;
870*3448Sdh155122 {
871*3448Sdh155122 
872*3448Sdh155122 	if (data == NULL)
873*3448Sdh155122 		return;
874*3448Sdh155122 
875*3448Sdh155122 	if (unit < 0 || unit > IPL_LOGMAX)
876*3448Sdh155122 		return;
877*3448Sdh155122 
878*3448Sdh155122 	switch (otype)
879*3448Sdh155122 	{
880*3448Sdh155122 	case IPFLOOKUPITER_LIST :
881*3448Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
882*3448Sdh155122 		ip_pool_deref((ip_pool_t *)data, ifs);
883*3448Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
884*3448Sdh155122 		break;
885*3448Sdh155122 
886*3448Sdh155122 	case IPFLOOKUPITER_NODE :
887*3448Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
888*3448Sdh155122 		ip_pool_node_deref((ip_pool_node_t *)data, ifs);
889*3448Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
890*3448Sdh155122 		break;
891*3448Sdh155122 	default :
892*3448Sdh155122 		break;
893*3448Sdh155122 	}
8942393Syz155240 }
8952393Syz155240 
8962393Syz155240 
8972393Syz155240 # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
8982393Syz155240       !defined(__hpux) && !defined(__sgi))
8992393Syz155240 static int
900*3448Sdh155122 rn_freenode(struct radix_node *n, void *p, ipf_stack_t *ifs)
9012393Syz155240 {
9022393Syz155240 	struct radix_node_head *rnh = p;
9032393Syz155240 	struct radix_node *d;
9042393Syz155240 
9052393Syz155240 	d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
9062393Syz155240 	if (d != NULL) {
907*3448Sdh155122 		FreeS(d, ifs->ifs_max_keylen + 2 * sizeof (*d));
9082393Syz155240 	}
9092393Syz155240 	return 0;
9102393Syz155240 }
9112393Syz155240 
9122393Syz155240 
9132393Syz155240 void
9142393Syz155240 rn_freehead(rnh)
9152393Syz155240       struct radix_node_head *rnh;
9162393Syz155240 {
9172393Syz155240 
9182393Syz155240 	(*rnh->rnh_walktree)(rnh, rn_freenode, rnh);
9192393Syz155240 
9202393Syz155240 	rnh->rnh_addaddr = NULL;
9212393Syz155240 	rnh->rnh_deladdr = NULL;
9222393Syz155240 	rnh->rnh_matchaddr = NULL;
9232393Syz155240 	rnh->rnh_lookup = NULL;
9242393Syz155240 	rnh->rnh_walktree = NULL;
9252393Syz155240 
9262393Syz155240 	Free(rnh);
9272393Syz155240 }
9282393Syz155240 # endif
9292393Syz155240 
9302393Syz155240 #endif /* IPFILTER_LOOKUP */
931