xref: /onnv-gate/usr/src/uts/common/inet/ipf/ip_pool.c (revision 12255:f9a1f4ae1259)
12393Syz155240 /*
22393Syz155240  * Copyright (C) 1993-2001, 2003 by Darren Reed.
32393Syz155240  *
42393Syz155240  * See the IPFILTER.LICENCE file for details on licencing.
52393Syz155240  *
6*12255SJohn.Ojemann@Oracle.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
72393Syz155240  */
82393Syz155240 
92393Syz155240 #if defined(KERNEL) || defined(_KERNEL)
102393Syz155240 # undef KERNEL
112393Syz155240 # undef _KERNEL
122393Syz155240 # define        KERNEL	1
132393Syz155240 # define        _KERNEL	1
142393Syz155240 #endif
152393Syz155240 #if defined(__osf__)
162393Syz155240 # define _PROTO_NET_H_
172393Syz155240 #endif
182393Syz155240 #include <sys/errno.h>
192393Syz155240 #include <sys/types.h>
202393Syz155240 #include <sys/param.h>
212393Syz155240 #include <sys/file.h>
222393Syz155240 #if !defined(_KERNEL) && !defined(__KERNEL__)
232393Syz155240 # include <stdio.h>
242393Syz155240 # include <stdlib.h>
252393Syz155240 # include <string.h>
262393Syz155240 # define _KERNEL
272393Syz155240 # ifdef __OpenBSD__
282393Syz155240 struct file;
292393Syz155240 # endif
302393Syz155240 # include <sys/uio.h>
312393Syz155240 # undef _KERNEL
322393Syz155240 #else
332393Syz155240 # include <sys/systm.h>
342393Syz155240 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
352393Syz155240 #  include <sys/proc.h>
362393Syz155240 # endif
372393Syz155240 #endif
382393Syz155240 #include <sys/time.h>
392393Syz155240 #if !defined(linux)
402393Syz155240 # include <sys/protosw.h>
412393Syz155240 #endif
422393Syz155240 #include <sys/socket.h>
432393Syz155240 #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
442393Syz155240 # include <sys/mbuf.h>
452393Syz155240 #endif
462393Syz155240 #if defined(__SVR4) || defined(__svr4__)
472393Syz155240 # include <sys/filio.h>
482393Syz155240 # include <sys/byteorder.h>
492393Syz155240 # ifdef _KERNEL
502393Syz155240 #  include <sys/dditypes.h>
512393Syz155240 # endif
522393Syz155240 # include <sys/stream.h>
532393Syz155240 # include <sys/kmem.h>
542393Syz155240 #endif
552393Syz155240 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
562393Syz155240 # include <sys/malloc.h>
572393Syz155240 #endif
582393Syz155240 
592393Syz155240 #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
602393Syz155240      defined(__hpux) || defined(__sgi))
612393Syz155240 # ifdef __osf__
622393Syz155240 #  include <net/radix.h>
632393Syz155240 # endif
642393Syz155240 # include "radix_ipf_local.h"
652393Syz155240 # define _RADIX_H_
662393Syz155240 #endif
672393Syz155240 #include <net/if.h>
682393Syz155240 #include <netinet/in.h>
692393Syz155240 
703448Sdh155122 #include "netinet/ipf_stack.h"
712393Syz155240 #include "netinet/ip_compat.h"
722393Syz155240 #include "netinet/ip_fil.h"
732393Syz155240 #include "netinet/ip_pool.h"
742393Syz155240 
752393Syz155240 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
762393Syz155240       ((BSD >= 198911) && !defined(__osf__) && \
772393Syz155240       !defined(__hpux) && !defined(__sgi))
782393Syz155240 static int rn_freenode __P((struct radix_node *, void *));
792393Syz155240 #endif
802393Syz155240 
812393Syz155240 /* END OF INCLUDES */
822393Syz155240 
832393Syz155240 #if !defined(lint)
842393Syz155240 static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
852393Syz155240 static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $";
862393Syz155240 #endif
872393Syz155240 
882393Syz155240 #ifdef IPFILTER_LOOKUP
892393Syz155240 
902393Syz155240 /*
912393Syz155240  * Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
922393Syz155240  * NOTE: Insertion *MUST* be from greatest range to least for it to work!
932393Syz155240  * These should be replaced, eventually, by something else - most notably a
942393Syz155240  * interval searching method.  The important feature is to be able to find
952393Syz155240  * the best match.
962393Syz155240  *
972393Syz155240  * So why not use a radix tree for this?  As the first line implies, it
982393Syz155240  * has been written to work with a _range_ of addresses.  A range is not
992393Syz155240  * necessarily a match with any given netmask so what we end up dealing
1002393Syz155240  * with is an interval tree.  Implementations of these are hard to find
1012393Syz155240  * and the one herein is far from bug free.
1022393Syz155240  *
1032393Syz155240  * Sigh, in the end I became convinced that the bugs the code contained did
1042393Syz155240  * not make it worthwhile not using radix trees.  For now the radix tree from
1052393Syz155240  * 4.4 BSD is used, but this is not viewed as a long term solution.
1062393Syz155240  */
1072393Syz155240 
1082393Syz155240 #ifdef TEST_POOL
1092393Syz155240 void treeprint __P((ip_pool_t *));
1102393Syz155240 
1112393Syz155240 int
main(argc,argv)1122393Syz155240 main(argc, argv)
1132393Syz155240 	int argc;
1142393Syz155240 	char *argv[];
1152393Syz155240 {
1162393Syz155240 	addrfamily_t a, b;
1172393Syz155240 	iplookupop_t op;
1182393Syz155240 	ip_pool_t *ipo;
1192393Syz155240 	i6addr_t ip;
120*12255SJohn.Ojemann@Oracle.COM 	fr_info_t fin;
1212393Syz155240 
1223448Sdh155122 	RWLOCK_INIT(&ifs->ifs_ip_poolrw, "poolrw");
1233448Sdh155122 	ip_pool_init(ifs);
1242393Syz155240 
1252393Syz155240 	bzero((char *)&a, sizeof(a));
1262393Syz155240 	bzero((char *)&b, sizeof(b));
1272393Syz155240 	bzero((char *)&ip, sizeof(ip));
1282393Syz155240 	bzero((char *)&op, sizeof(op));
1292393Syz155240 	strcpy(op.iplo_name, "0");
1302393Syz155240 
1313448Sdh155122 	if (ip_pool_create(&op, ifs) == 0)
1323448Sdh155122 		ipo = ip_pool_find(0, "0", ifs);
1332393Syz155240 
1342393Syz155240 	a.adf_addr.in4.s_addr = 0x0a010203;
1352393Syz155240 	b.adf_addr.in4.s_addr = 0xffffffff;
1363448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1373448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1382393Syz155240 
1392393Syz155240 	a.adf_addr.in4.s_addr = 0x0a000000;
1402393Syz155240 	b.adf_addr.in4.s_addr = 0xff000000;
1413448Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
1423448Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
1432393Syz155240 
1442393Syz155240 	a.adf_addr.in4.s_addr = 0x0a010100;
1452393Syz155240 	b.adf_addr.in4.s_addr = 0xffffff00;
1463448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1473448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1482393Syz155240 
1492393Syz155240 	a.adf_addr.in4.s_addr = 0x0a010200;
1502393Syz155240 	b.adf_addr.in4.s_addr = 0xffffff00;
1513448Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
1523448Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
1532393Syz155240 
1542393Syz155240 	a.adf_addr.in4.s_addr = 0x0a010000;
1552393Syz155240 	b.adf_addr.in4.s_addr = 0xffff0000;
1563448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1573448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1582393Syz155240 
1592393Syz155240 	a.adf_addr.in4.s_addr = 0x0a01020f;
1602393Syz155240 	b.adf_addr.in4.s_addr = 0xffffffff;
1613448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1623448Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
1632393Syz155240 #ifdef	DEBUG_POOL
1642393Syz155240 treeprint(ipo);
1652393Syz155240 #endif
166*12255SJohn.Ojemann@Oracle.COM 	fin.fin_plen = 20;
1672393Syz155240 	ip.in4.s_addr = 0x0a00aabb;
1682393Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
169*12255SJohn.Ojemann@Oracle.COM 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1702393Syz155240 
1712393Syz155240 	ip.in4.s_addr = 0x0a000001;
1722393Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
173*12255SJohn.Ojemann@Oracle.COM 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1742393Syz155240 
1752393Syz155240 	ip.in4.s_addr = 0x0a000101;
1762393Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
177*12255SJohn.Ojemann@Oracle.COM 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1782393Syz155240 
1792393Syz155240 	ip.in4.s_addr = 0x0a010001;
1802393Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
181*12255SJohn.Ojemann@Oracle.COM 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1822393Syz155240 
1832393Syz155240 	ip.in4.s_addr = 0x0a010101;
1842393Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
185*12255SJohn.Ojemann@Oracle.COM 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1862393Syz155240 
1872393Syz155240 	ip.in4.s_addr = 0x0a010201;
1882393Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
189*12255SJohn.Ojemann@Oracle.COM 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1902393Syz155240 
1912393Syz155240 	ip.in4.s_addr = 0x0a010203;
1922393Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
193*12255SJohn.Ojemann@Oracle.COM 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1942393Syz155240 
1952393Syz155240 	ip.in4.s_addr = 0x0a01020f;
1962393Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
197*12255SJohn.Ojemann@Oracle.COM 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
1982393Syz155240 
1992393Syz155240 	ip.in4.s_addr = 0x0b00aabb;
2002393Syz155240 	printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
201*12255SJohn.Ojemann@Oracle.COM 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
2022393Syz155240 
2032393Syz155240 #ifdef	DEBUG_POOL
2042393Syz155240 treeprint(ipo);
2052393Syz155240 #endif
2062393Syz155240 
2073448Sdh155122 	ip_pool_fini(ifs);
2082393Syz155240 
2092393Syz155240 	return 0;
2102393Syz155240 }
2112393Syz155240 
2122393Syz155240 
2132393Syz155240 void
treeprint(ipo)2142393Syz155240 treeprint(ipo)
2152393Syz155240 ip_pool_t *ipo;
2162393Syz155240 {
2172393Syz155240 	ip_pool_node_t *c;
2182393Syz155240 
2192393Syz155240 	for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
2202393Syz155240 		printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
2212393Syz155240 			c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
2222393Syz155240 			c->ipn_mask.adf_addr.in4.s_addr,
2232393Syz155240 			c->ipn_info, c->ipn_hits);
2242393Syz155240 }
2252393Syz155240 #endif /* TEST_POOL */
2262393Syz155240 
2272393Syz155240 
2282393Syz155240 /* ------------------------------------------------------------------------ */
2292393Syz155240 /* Function:    ip_pool_init                                                */
2302393Syz155240 /* Returns:     int     - 0 = success, else error                           */
2312393Syz155240 /*                                                                          */
2322393Syz155240 /* Initialise the routing table data structures where required.             */
2332393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_init(ifs)2343448Sdh155122 int ip_pool_init(ifs)
2353448Sdh155122 ipf_stack_t *ifs;
2362393Syz155240 {
2372393Syz155240 
2383448Sdh155122 	bzero(&ifs->ifs_ipoolstat, sizeof (ip_pool_stat_t));
2392393Syz155240 
2402535Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
2412393Syz155240 	rn_init();
2422393Syz155240 #endif
2432393Syz155240 	return 0;
2442393Syz155240 }
2452393Syz155240 
2462393Syz155240 
2472393Syz155240 /* ------------------------------------------------------------------------ */
2482393Syz155240 /* Function:    ip_pool_fini                                                */
2492393Syz155240 /* Returns:     int     - 0 = success, else error                           */
2502393Syz155240 /* Locks:       WRITE(ipf_global)                                           */
2512393Syz155240 /*                                                                          */
2522393Syz155240 /* Clean up all the pool data structures allocated and call the cleanup     */
2532393Syz155240 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
2542393Syz155240 /* used to delete the pools one by one to ensure they're properly freed up. */
2552393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_fini(ifs)2563448Sdh155122 void ip_pool_fini(ifs)
2573448Sdh155122 ipf_stack_t *ifs;
2582393Syz155240 {
2592393Syz155240 	ip_pool_t *p, *q;
2602393Syz155240 	iplookupop_t op;
2612393Syz155240 	int i;
2622393Syz155240 
2633448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0);
2642393Syz155240 
2652393Syz155240 	for (i = 0; i <= IPL_LOGMAX; i++) {
2663448Sdh155122 		for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) {
2672393Syz155240 			op.iplo_unit = i;
2682393Syz155240 			(void)strncpy(op.iplo_name, p->ipo_name,
2692393Syz155240 				sizeof(op.iplo_name));
2702393Syz155240 			q = p->ipo_next;
2713448Sdh155122 			(void) ip_pool_destroy(&op, ifs);
2722393Syz155240 		}
2732393Syz155240 	}
2742393Syz155240 
2752535Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
2762393Syz155240 	rn_fini();
2772393Syz155240 #endif
2782393Syz155240 }
2792393Syz155240 
2802393Syz155240 
2812393Syz155240 /* ------------------------------------------------------------------------ */
2822393Syz155240 /* Function:    ip_pool_statistics                                          */
2832393Syz155240 /* Returns:     int     - 0 = success, else error                           */
2842393Syz155240 /* Parameters:  op(I)   - pointer to lookup operation arguments             */
2852393Syz155240 /*                                                                          */
2862393Syz155240 /* Copy the current statistics out into user space, collecting pool list    */
2872393Syz155240 /* pointers as appropriate for later use.                                   */
2882393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_statistics(op,ifs)2893448Sdh155122 int ip_pool_statistics(op, ifs)
2902393Syz155240 iplookupop_t *op;
2913448Sdh155122 ipf_stack_t *ifs;
2922393Syz155240 {
2932393Syz155240 	ip_pool_stat_t stats;
2942393Syz155240 	int unit, i, err = 0;
2952393Syz155240 
2963448Sdh155122 	if (op->iplo_size != sizeof(ip_pool_stat_t))
2972393Syz155240 		return EINVAL;
2982393Syz155240 
2993448Sdh155122 	bcopy((char *)&ifs->ifs_ipoolstat, (char *)&stats, sizeof(stats));
3002393Syz155240 	unit = op->iplo_unit;
3012393Syz155240 	if (unit == IPL_LOGALL) {
3022393Syz155240 		for (i = 0; i < IPL_LOGSIZE; i++)
3033448Sdh155122 			stats.ipls_list[i] = ifs->ifs_ip_pool_list[i];
3042393Syz155240 	} else if (unit >= 0 && unit < IPL_LOGSIZE) {
3052393Syz155240 		if (op->iplo_name[0] != '\0')
3062393Syz155240 			stats.ipls_list[unit] = ip_pool_find(unit,
3073448Sdh155122 							     op->iplo_name, ifs);
3082393Syz155240 		else
3093448Sdh155122 			stats.ipls_list[unit] = ifs->ifs_ip_pool_list[unit];
3102393Syz155240 	} else
3112393Syz155240 		err = EINVAL;
3122393Syz155240 	if (err == 0)
3132393Syz155240 		err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
3142393Syz155240 	return err;
3152393Syz155240 }
3162393Syz155240 
3172393Syz155240 
3182393Syz155240 
3192393Syz155240 /* ------------------------------------------------------------------------ */
3202393Syz155240 /* Function:    ip_pool_find                                                */
3212393Syz155240 /* Returns:     int     - 0 = success, else error                           */
3222393Syz155240 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
3232393Syz155240 /*                                                                          */
3242393Syz155240 /* Find a matching pool inside the collection of pools for a particular     */
3252393Syz155240 /* device, indicated by the unit number.                                    */
3262393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_find(unit,name,ifs)3273448Sdh155122 void *ip_pool_find(unit, name, ifs)
3282393Syz155240 int unit;
3292393Syz155240 char *name;
3303448Sdh155122 ipf_stack_t *ifs;
3312393Syz155240 {
3322393Syz155240 	ip_pool_t *p;
3332393Syz155240 
3343448Sdh155122 	for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; p = p->ipo_next)
3352393Syz155240 		if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
3362393Syz155240 			break;
3372393Syz155240 	return p;
3382393Syz155240 }
3392393Syz155240 
3402393Syz155240 
3412393Syz155240 /* ------------------------------------------------------------------------ */
3422393Syz155240 /* Function:    ip_pool_findeq                                              */
3432393Syz155240 /* Returns:     int     - 0 = success, else error                           */
3442393Syz155240 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
3452393Syz155240 /*              addr(I) - pointer to address information to delete          */
3462393Syz155240 /*              mask(I) -                                                   */
3472393Syz155240 /*                                                                          */
3482393Syz155240 /* Searches for an exact match of an entry in the pool.                     */
3492393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_findeq(ipo,addr,mask)3502393Syz155240 ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
3512393Syz155240 ip_pool_t *ipo;
3522393Syz155240 addrfamily_t *addr, *mask;
3532393Syz155240 {
3542393Syz155240 	struct radix_node *n;
3552393Syz155240 	SPL_INT(s);
3562393Syz155240 
3572393Syz155240 	SPL_NET(s);
3582393Syz155240 	n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
3592393Syz155240 	SPL_X(s);
3602393Syz155240 	return (ip_pool_node_t *)n;
3612393Syz155240 }
3622393Syz155240 
3632393Syz155240 
3642393Syz155240 /* ------------------------------------------------------------------------ */
3652393Syz155240 /* Function:    ip_pool_search                                              */
3662393Syz155240 /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve/no match    */
3672393Syz155240 /* Parameters:  tptr(I)    - pointer to the pool to search                  */
3682393Syz155240 /*              version(I) - IP protocol version (4 or 6)                   */
3692393Syz155240 /*              dptr(I)    - pointer to address information                 */
370*12255SJohn.Ojemann@Oracle.COM /*		fin	   - pointer to packet information		    */
371*12255SJohn.Ojemann@Oracle.COM /*		ifs	   - ipf stack instance				    */
3722393Syz155240 /*                                                                          */
3732393Syz155240 /* Search the pool for a given address and return a search result.          */
3742393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_search(tptr,version,dptr,fin,ifs)375*12255SJohn.Ojemann@Oracle.COM int ip_pool_search(tptr, version, dptr, fin, ifs)
3762393Syz155240 void *tptr;
3772393Syz155240 int version;
3782393Syz155240 void *dptr;
379*12255SJohn.Ojemann@Oracle.COM fr_info_t *fin;
3803448Sdh155122 ipf_stack_t *ifs;
3812393Syz155240 {
3822393Syz155240 	struct radix_node *rn;
3832393Syz155240 	ip_pool_node_t *m;
3842393Syz155240 	i6addr_t *addr;
3852393Syz155240 	addrfamily_t v;
3862393Syz155240 	ip_pool_t *ipo;
3872393Syz155240 	int rv;
3882393Syz155240 
3892393Syz155240 	ipo = tptr;
3902393Syz155240 	if (ipo == NULL)
3912393Syz155240 		return -1;
3922393Syz155240 
3932393Syz155240 	rv = 1;
3942393Syz155240 	m = NULL;
3952393Syz155240 	addr = (i6addr_t *)dptr;
3962393Syz155240 	bzero(&v, sizeof(v));
3972393Syz155240 	v.adf_len = offsetof(addrfamily_t, adf_addr);
3982393Syz155240 
3992393Syz155240 	if (version == 4) {
4002393Syz155240 		v.adf_len += sizeof(addr->in4);
4012393Syz155240 		v.adf_addr.in4 = addr->in4;
4022393Syz155240 #ifdef USE_INET6
4032393Syz155240 	} else if (version == 6) {
4042393Syz155240 		v.adf_len += sizeof(addr->in6);
4052393Syz155240 		v.adf_addr.in6 = addr->in6;
4062393Syz155240 #endif
4072393Syz155240 	} else
4082393Syz155240 		return -1;
4092393Syz155240 
4103448Sdh155122 	READ_ENTER(&ifs->ifs_ip_poolrw);
4112393Syz155240 
4122393Syz155240 	rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
4132393Syz155240 
4142393Syz155240 	if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
4152393Syz155240 		m = (ip_pool_node_t *)rn;
4162393Syz155240 		ipo->ipo_hits++;
4172393Syz155240 		m->ipn_hits++;
418*12255SJohn.Ojemann@Oracle.COM 		m->ipn_bytes += fin->fin_plen;
4192393Syz155240 		rv = m->ipn_info;
4202393Syz155240 	}
4213448Sdh155122 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
4222393Syz155240 	return rv;
4232393Syz155240 }
4242393Syz155240 
4252393Syz155240 
4262393Syz155240 /* ------------------------------------------------------------------------ */
4272393Syz155240 /* Function:    ip_pool_insert                                              */
4282393Syz155240 /* Returns:     int     - 0 = success, else error                           */
4292393Syz155240 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
4302393Syz155240 /*              addr(I) - IPv4/6 address being added as a node              */
4312393Syz155240 /*              mask(I) - IPv4/6 netmask to with the node being added       */
4322393Syz155240 /*              info(I) - extra information to store in this node.          */
4332393Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
4342393Syz155240 /*                                                                          */
4352393Syz155240 /* Add another node to the pool given by ipo.  The three parameters passed  */
4362393Syz155240 /* in (addr, mask, info) shold all be stored in the node.                   */
4372393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_insert(ipo,addr,mask,info,ifs)4383448Sdh155122 int ip_pool_insert(ipo, addr, mask, info, ifs)
4392393Syz155240 ip_pool_t *ipo;
4402393Syz155240 addrfamily_t *addr, *mask;
4412393Syz155240 int info;
4423448Sdh155122 ipf_stack_t *ifs;
4432393Syz155240 {
4442393Syz155240 	struct radix_node *rn;
4452393Syz155240 	ip_pool_node_t *x;
4462393Syz155240 
4473448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
4482393Syz155240 
4492393Syz155240 	KMALLOC(x, ip_pool_node_t *);
4502393Syz155240 	if (x == NULL) {
4512393Syz155240 		return ENOMEM;
4522393Syz155240 	}
4532393Syz155240 
4542393Syz155240 	bzero(x, sizeof(*x));
4552393Syz155240 
4562393Syz155240 	x->ipn_info = info;
4572393Syz155240 	(void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
4582393Syz155240 
4592393Syz155240 	bcopy(addr, &x->ipn_addr, sizeof(*addr));
4602393Syz155240 	x->ipn_addr.adf_len = sizeof(x->ipn_addr);
4612393Syz155240 	bcopy(mask, &x->ipn_mask, sizeof(*mask));
4622393Syz155240 	x->ipn_mask.adf_len = sizeof(x->ipn_mask);
4632393Syz155240 
4642393Syz155240 	rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
4652393Syz155240 					ipo->ipo_head, x->ipn_nodes);
4662393Syz155240 #ifdef	DEBUG_POOL
4672393Syz155240 	printf("Added %p at %p\n", x, rn);
4682393Syz155240 #endif
4692393Syz155240 
4702393Syz155240 	if (rn == NULL) {
4712393Syz155240 		KFREE(x);
4722393Syz155240 		return ENOMEM;
4732393Syz155240 	}
4742393Syz155240 
4753448Sdh155122 	x->ipn_ref = 1;
4762393Syz155240 	x->ipn_next = ipo->ipo_list;
4772393Syz155240 	x->ipn_pnext = &ipo->ipo_list;
4782393Syz155240 	if (ipo->ipo_list != NULL)
4792393Syz155240 		ipo->ipo_list->ipn_pnext = &x->ipn_next;
4802393Syz155240 	ipo->ipo_list = x;
4812393Syz155240 
4823448Sdh155122 	ifs->ifs_ipoolstat.ipls_nodes++;
4832393Syz155240 
4842393Syz155240 	return 0;
4852393Syz155240 }
4862393Syz155240 
4872393Syz155240 
4882393Syz155240 /* ------------------------------------------------------------------------ */
4892393Syz155240 /* Function:    ip_pool_create                                              */
4902393Syz155240 /* Returns:     int     - 0 = success, else error                           */
4912393Syz155240 /* Parameters:  op(I) - pointer to iplookup struct with call details        */
4922393Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
4932393Syz155240 /*                                                                          */
4942393Syz155240 /* Creates a new group according to the paramters passed in via the         */
4952393Syz155240 /* iplookupop structure.  Does not check to see if the group already exists */
4962393Syz155240 /* when being inserted - assume this has already been done.  If the pool is */
4972393Syz155240 /* marked as being anonymous, give it a new, unique, identifier.  Call any  */
4982393Syz155240 /* other functions required to initialise the structure.                    */
4992393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_create(op,ifs)5003448Sdh155122 int ip_pool_create(op, ifs)
5012393Syz155240 iplookupop_t *op;
5023448Sdh155122 ipf_stack_t *ifs;
5032393Syz155240 {
5042393Syz155240 	char name[FR_GROUPLEN];
5052393Syz155240 	int poolnum, unit;
5062393Syz155240 	ip_pool_t *h;
5072393Syz155240 
5083448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
5092393Syz155240 
5102393Syz155240 	KMALLOC(h, ip_pool_t *);
5112393Syz155240 	if (h == NULL)
5122393Syz155240 		return ENOMEM;
5132393Syz155240 	bzero(h, sizeof(*h));
5142393Syz155240 
5152393Syz155240 	if (rn_inithead((void **)&h->ipo_head,
5162393Syz155240 			offsetof(addrfamily_t, adf_addr) << 3) == 0) {
5172393Syz155240 		KFREE(h);
5182393Syz155240 		return ENOMEM;
5192393Syz155240 	}
5202393Syz155240 
5212393Syz155240 	unit = op->iplo_unit;
5222393Syz155240 
5232393Syz155240 	if ((op->iplo_arg & IPOOL_ANON) != 0) {
5242393Syz155240 		ip_pool_t *p;
5252393Syz155240 
5262393Syz155240 		poolnum = IPOOL_ANON;
5272393Syz155240 
5282393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL)
5292393Syz155240 		(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
5302393Syz155240 #else
5312393Syz155240 		(void)sprintf(name, "%x", poolnum);
5322393Syz155240 #endif
5332393Syz155240 
5343448Sdh155122 		for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; ) {
5352393Syz155240 			if (strncmp(name, p->ipo_name,
5362393Syz155240 				    sizeof(p->ipo_name)) == 0) {
5372393Syz155240 				poolnum++;
5382393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL)
5392393Syz155240 				(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
5402393Syz155240 #else
5412393Syz155240 				(void)sprintf(name, "%x", poolnum);
5422393Syz155240 #endif
5433448Sdh155122 				p = ifs->ifs_ip_pool_list[unit];
5442393Syz155240 			} else
5452393Syz155240 				p = p->ipo_next;
5462393Syz155240 		}
5472393Syz155240 
5482393Syz155240 		(void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
5492393Syz155240 	} else {
5502393Syz155240 		(void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
5512393Syz155240 	}
5522393Syz155240 
5532393Syz155240 	h->ipo_ref = 1;
5542393Syz155240 	h->ipo_list = NULL;
5552393Syz155240 	h->ipo_unit = unit;
5563448Sdh155122 	h->ipo_next = ifs->ifs_ip_pool_list[unit];
5573448Sdh155122 	if (ifs->ifs_ip_pool_list[unit] != NULL)
5583448Sdh155122 		ifs->ifs_ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
5593448Sdh155122 	h->ipo_pnext = &ifs->ifs_ip_pool_list[unit];
5603448Sdh155122 	ifs->ifs_ip_pool_list[unit] = h;
5612393Syz155240 
5623448Sdh155122 	ifs->ifs_ipoolstat.ipls_pools++;
5632393Syz155240 
5642393Syz155240 	return 0;
5652393Syz155240 }
5662393Syz155240 
5672393Syz155240 
5682393Syz155240 /* ------------------------------------------------------------------------ */
5692393Syz155240 /* Function:    ip_pool_remove                                              */
5702393Syz155240 /* Returns:     int    - 0 = success, else error                            */
5712393Syz155240 /* Parameters:  ipo(I) - pointer to the pool to remove the node from.       */
5722393Syz155240 /*              ipe(I) - address being deleted as a node                    */
5732393Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
5742393Syz155240 /*                                                                          */
5752393Syz155240 /* Add another node to the pool given by ipo.  The three parameters passed  */
5762393Syz155240 /* in (addr, mask, info) shold all be stored in the node.                   */
5772393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_remove(ipo,ipe,ifs)5783448Sdh155122 int ip_pool_remove(ipo, ipe, ifs)
5792393Syz155240 ip_pool_t *ipo;
5802393Syz155240 ip_pool_node_t *ipe;
5813448Sdh155122 ipf_stack_t *ifs;
5822393Syz155240 {
5832393Syz155240 	ip_pool_node_t **ipp, *n;
5842393Syz155240 
5853448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
5862393Syz155240 
5872393Syz155240 	for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) {
5882393Syz155240 		if (ipe == n) {
5892393Syz155240 			*n->ipn_pnext = n->ipn_next;
5902393Syz155240 			if (n->ipn_next)
5912393Syz155240 				n->ipn_next->ipn_pnext = n->ipn_pnext;
5922393Syz155240 			break;
5932393Syz155240 		}
5942393Syz155240 	}
5952393Syz155240 
5962393Syz155240 	if (n == NULL)
5972393Syz155240 		return ENOENT;
5982393Syz155240 
5992393Syz155240 	ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
6002393Syz155240 				   ipo->ipo_head);
6012393Syz155240 	KFREE(n);
6022393Syz155240 
6033448Sdh155122 	ifs->ifs_ipoolstat.ipls_nodes--;
6042393Syz155240 
6052393Syz155240 	return 0;
6062393Syz155240 }
6072393Syz155240 
6082393Syz155240 
6092393Syz155240 /* ------------------------------------------------------------------------ */
6102393Syz155240 /* Function:    ip_pool_destroy                                             */
6112393Syz155240 /* Returns:     int    - 0 = success, else error                            */
6122393Syz155240 /* Parameters:  op(I)  -  information about the pool to remove              */
6132393Syz155240 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
6142393Syz155240 /*                                                                          */
6152393Syz155240 /* Search for a pool using paramters passed in and if it's not otherwise    */
6162393Syz155240 /* busy, free it.                                                           */
6172393Syz155240 /*                                                                          */
6182393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6192393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
6202393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
6212393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_destroy(op,ifs)6223448Sdh155122 int ip_pool_destroy(op, ifs)
6232393Syz155240 iplookupop_t *op;
6243448Sdh155122 ipf_stack_t *ifs;
6252393Syz155240 {
6262393Syz155240 	ip_pool_t *ipo;
6272393Syz155240 
6283448Sdh155122 	ipo = ip_pool_find(op->iplo_unit, op->iplo_name, ifs);
6292393Syz155240 	if (ipo == NULL)
6302393Syz155240 		return ESRCH;
6312393Syz155240 
6322393Syz155240 	if (ipo->ipo_ref != 1)
6332393Syz155240 		return EBUSY;
6342393Syz155240 
6353448Sdh155122 	ip_pool_free(ipo, ifs);
6362393Syz155240 	return 0;
6372393Syz155240 }
6382393Syz155240 
6392393Syz155240 
6402393Syz155240 /* ------------------------------------------------------------------------ */
6412393Syz155240 /* Function:    ip_pool_flush                                               */
6422393Syz155240 /* Returns:     int    - number of pools deleted                            */
6432393Syz155240 /* Parameters:  fp(I)  - which pool(s) to flush                             */
6442393Syz155240 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
6452393Syz155240 /*                                                                          */
6462393Syz155240 /* Free all pools associated with the device that matches the unit number   */
6472393Syz155240 /* passed in with operation.                                                */
6482393Syz155240 /*                                                                          */
6492393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6502393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
6512393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
6522393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_flush(fp,ifs)6533448Sdh155122 int ip_pool_flush(fp, ifs)
6542393Syz155240 iplookupflush_t *fp;
6553448Sdh155122 ipf_stack_t *ifs;
6562393Syz155240 {
6572393Syz155240 	int i, num = 0, unit, err;
6582393Syz155240 	ip_pool_t *p, *q;
6592393Syz155240 	iplookupop_t op;
6602393Syz155240 
6612393Syz155240 	unit = fp->iplf_unit;
6622393Syz155240 
6632393Syz155240 	for (i = 0; i <= IPL_LOGMAX; i++) {
6642393Syz155240 		if (unit != IPLT_ALL && i != unit)
6652393Syz155240 			continue;
6663448Sdh155122 		for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) {
6672393Syz155240 			op.iplo_unit = i;
6682393Syz155240 			(void)strncpy(op.iplo_name, p->ipo_name,
6692393Syz155240 				sizeof(op.iplo_name));
6702393Syz155240 			q = p->ipo_next;
6713448Sdh155122 			err = ip_pool_destroy(&op, ifs);
6722393Syz155240 			if (err == 0)
6732393Syz155240 				num++;
6742393Syz155240 			else
6752393Syz155240 				break;
6762393Syz155240 		}
6772393Syz155240 	}
6782393Syz155240 	return num;
6792393Syz155240 }
6802393Syz155240 
6812393Syz155240 
6822393Syz155240 /* ------------------------------------------------------------------------ */
6832393Syz155240 /* Function:    ip_pool_free                                                */
6842393Syz155240 /* Returns:     void                                                        */
6852393Syz155240 /* Parameters:  ipo(I) -  pointer to pool structure                         */
6862393Syz155240 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
6872393Syz155240 /*                                                                          */
6882393Syz155240 /* Deletes the pool strucutre passed in from the list of pools and deletes  */
6892393Syz155240 /* all of the address information stored in it, including any tree data     */
6902393Syz155240 /* structures also allocated.                                               */
6912393Syz155240 /*                                                                          */
6922393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6932393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
6942393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
6952393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_free(ipo,ifs)6963448Sdh155122 void ip_pool_free(ipo, ifs)
6972393Syz155240 ip_pool_t *ipo;
6983448Sdh155122 ipf_stack_t *ifs;
6992393Syz155240 {
7002393Syz155240 	ip_pool_node_t *n;
7012393Syz155240 
7022393Syz155240 	while ((n = ipo->ipo_list) != NULL) {
7032393Syz155240 		ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
7042393Syz155240 					   ipo->ipo_head);
7052393Syz155240 
7062393Syz155240 		*n->ipn_pnext = n->ipn_next;
7072393Syz155240 		if (n->ipn_next)
7082393Syz155240 			n->ipn_next->ipn_pnext = n->ipn_pnext;
7092393Syz155240 
7102393Syz155240 		KFREE(n);
7112393Syz155240 
7123448Sdh155122 		ifs->ifs_ipoolstat.ipls_nodes--;
7132393Syz155240 	}
7142393Syz155240 
7152393Syz155240 	ipo->ipo_list = NULL;
7162393Syz155240 	if (ipo->ipo_next != NULL)
7172393Syz155240 		ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
7182393Syz155240 	*ipo->ipo_pnext = ipo->ipo_next;
7192393Syz155240 	rn_freehead(ipo->ipo_head);
7202393Syz155240 	KFREE(ipo);
7212393Syz155240 
7223448Sdh155122 	ifs->ifs_ipoolstat.ipls_pools--;
7232393Syz155240 }
7242393Syz155240 
7252393Syz155240 
7262393Syz155240 /* ------------------------------------------------------------------------ */
7272393Syz155240 /* Function:    ip_pool_deref                                               */
7282393Syz155240 /* Returns:     void                                                        */
7292393Syz155240 /* Parameters:  ipo(I) -  pointer to pool structure                         */
7302393Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
7312393Syz155240 /*                                                                          */
7322393Syz155240 /* Drop the number of known references to this pool structure by one and if */
7332393Syz155240 /* we arrive at zero known references, free it.                             */
7342393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_deref(ipo,ifs)7353448Sdh155122 void ip_pool_deref(ipo, ifs)
7362393Syz155240 ip_pool_t *ipo;
7373448Sdh155122 ipf_stack_t *ifs;
7382393Syz155240 {
7392393Syz155240 
7403448Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
7412393Syz155240 
7422393Syz155240 	ipo->ipo_ref--;
7432393Syz155240 	if (ipo->ipo_ref == 0)
7443448Sdh155122 		ip_pool_free(ipo, ifs);
7453448Sdh155122 }
7463448Sdh155122 
7473448Sdh155122 
7483448Sdh155122 
ip_pool_node_deref(ipn,ifs)7493448Sdh155122 void ip_pool_node_deref(ipn, ifs)
7503448Sdh155122 ip_pool_node_t *ipn;
7513448Sdh155122 ipf_stack_t *ifs;
7523448Sdh155122 {
7533448Sdh155122 
7543448Sdh155122 	ipn->ipn_ref--;
7553448Sdh155122 
7563448Sdh155122 	if (ipn->ipn_ref == 0) {
7573448Sdh155122 		KFREE(ipn);
7583448Sdh155122 		ifs->ifs_ipoolstat.ipls_nodes--;
7593448Sdh155122 	}
7603448Sdh155122 }
7613448Sdh155122 
7623448Sdh155122 
ip_pool_getnext(token,ilp,ifs)7633448Sdh155122 int ip_pool_getnext(token, ilp, ifs)
7643448Sdh155122 ipftoken_t *token;
7653448Sdh155122 ipflookupiter_t *ilp;
7663448Sdh155122 ipf_stack_t *ifs;
7673448Sdh155122 {
7683448Sdh155122 	ip_pool_node_t *node, zn, *nextnode;
7693448Sdh155122 	ip_pool_t *ipo, zp, *nextipo;
7703448Sdh155122 	int err;
7713448Sdh155122 
7723448Sdh155122 	err = 0;
7733448Sdh155122 	node = NULL;
7743448Sdh155122 	nextnode = NULL;
7753448Sdh155122 	ipo = NULL;
7763448Sdh155122 	nextipo = NULL;
7773448Sdh155122 
7783448Sdh155122 	READ_ENTER(&ifs->ifs_ip_poolrw);
7793448Sdh155122 
7806518Sjojemann 	/*
7816518Sjojemann 	 * Get "previous" entry from the token and find the next entry.
7826518Sjojemann 	 *
7836518Sjojemann 	 * If we found an entry, add a reference to it and update the token.
7846518Sjojemann 	 * Otherwise, zero out data to be returned and NULL out token.
7856518Sjojemann 	 */
7863448Sdh155122 	switch (ilp->ili_otype)
7873448Sdh155122 	{
7883448Sdh155122 	case IPFLOOKUPITER_LIST :
7893448Sdh155122 		ipo = token->ipt_data;
7903448Sdh155122 		if (ipo == NULL) {
7913448Sdh155122 			nextipo = ifs->ifs_ip_pool_list[(int)ilp->ili_unit];
7923448Sdh155122 		} else {
7933448Sdh155122 			nextipo = ipo->ipo_next;
7943448Sdh155122 		}
7953448Sdh155122 		if (nextipo != NULL) {
7966518Sjojemann 			ATOMIC_INC(nextipo->ipo_ref);
7976518Sjojemann 			token->ipt_data = nextipo;
7983448Sdh155122 		} else {
7993448Sdh155122 			bzero((char *)&zp, sizeof(zp));
8003448Sdh155122 			nextipo = &zp;
8016518Sjojemann 			token->ipt_data = NULL;
8023448Sdh155122 		}
8033448Sdh155122 		break;
8043448Sdh155122 
8053448Sdh155122 	case IPFLOOKUPITER_NODE :
8063448Sdh155122 		node = token->ipt_data;
8073448Sdh155122 		if (node == NULL) {
8083448Sdh155122 			ipo = ip_pool_find(ilp->ili_unit, ilp->ili_name, ifs);
8093448Sdh155122 			if (ipo == NULL)
8103448Sdh155122 				err = ESRCH;
8113448Sdh155122 			else {
8123448Sdh155122 				nextnode = ipo->ipo_list;
8133448Sdh155122 				ipo = NULL;
8143448Sdh155122 			}
8153448Sdh155122 		} else {
8163448Sdh155122 			nextnode = node->ipn_next;
8173448Sdh155122 		}
8183448Sdh155122 		if (nextnode != NULL) {
8196518Sjojemann 			ATOMIC_INC(nextnode->ipn_ref);
8206518Sjojemann 			token->ipt_data = nextnode;
8213448Sdh155122 		} else {
8223448Sdh155122 			bzero((char *)&zn, sizeof(zn));
8233448Sdh155122 			nextnode = &zn;
8246518Sjojemann 			token->ipt_data = NULL;
8253448Sdh155122 		}
8263448Sdh155122 		break;
8276518Sjojemann 
8283448Sdh155122 	default :
8293448Sdh155122 		err = EINVAL;
8303448Sdh155122 		break;
8313448Sdh155122 	}
8323448Sdh155122 
8336518Sjojemann 	/*
8346518Sjojemann 	 * Now that we have ref, it's save to give up lock.
8356518Sjojemann 	 */
8363448Sdh155122 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
8373448Sdh155122 
8383448Sdh155122 	if (err != 0)
8393448Sdh155122 		return err;
8403448Sdh155122 
8416518Sjojemann 	/*
8426518Sjojemann 	 * Copy out the data and update the references and token as needed.
8436518Sjojemann 	 */
8443448Sdh155122 	switch (ilp->ili_otype)
8453448Sdh155122 	{
8463448Sdh155122 	case IPFLOOKUPITER_LIST :
8473448Sdh155122 		err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo));
8483448Sdh155122 		if (err != 0)
8493448Sdh155122 			err = EFAULT;
8506518Sjojemann 		if (token->ipt_data == NULL) {
8516518Sjojemann 			ipf_freetoken(token, ifs);
8526518Sjojemann 		} else {
8536518Sjojemann 			if (ipo != NULL) {
8546518Sjojemann 				WRITE_ENTER(&ifs->ifs_ip_poolrw);
8556518Sjojemann 				ip_pool_deref(ipo, ifs);
8566518Sjojemann 				RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
8576518Sjojemann 			}
8586518Sjojemann 			if (nextipo->ipo_next == NULL)
8596518Sjojemann 				ipf_freetoken(token, ifs);
8606518Sjojemann 		}
8613448Sdh155122 		break;
8623448Sdh155122 
8633448Sdh155122 	case IPFLOOKUPITER_NODE :
8643448Sdh155122 		err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
8653448Sdh155122 		if (err != 0)
8663448Sdh155122 			err = EFAULT;
8676518Sjojemann 		if (token->ipt_data == NULL) {
8686518Sjojemann 			ipf_freetoken(token, ifs);
8696518Sjojemann 		} else {
8706518Sjojemann 			if (node != NULL) {
8716518Sjojemann 				WRITE_ENTER(&ifs->ifs_ip_poolrw);
8726518Sjojemann 				ip_pool_node_deref(node, ifs);
8736518Sjojemann 				RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
8746518Sjojemann 			}
8756518Sjojemann 			if (nextnode->ipn_next == NULL)
8766518Sjojemann 				ipf_freetoken(token, ifs);
8776518Sjojemann 		}
8783448Sdh155122 		break;
8793448Sdh155122 	}
8803448Sdh155122 
8813448Sdh155122 	return err;
8823448Sdh155122 }
8833448Sdh155122 
8843448Sdh155122 
ip_pool_iterderef(otype,unit,data,ifs)8853448Sdh155122 void ip_pool_iterderef(otype, unit, data, ifs)
8863448Sdh155122 u_int otype;
8873448Sdh155122 int unit;
8883448Sdh155122 void *data;
8893448Sdh155122 ipf_stack_t *ifs;
8903448Sdh155122 {
8913448Sdh155122 
8923448Sdh155122 	if (data == NULL)
8933448Sdh155122 		return;
8943448Sdh155122 
8953448Sdh155122 	if (unit < 0 || unit > IPL_LOGMAX)
8963448Sdh155122 		return;
8973448Sdh155122 
8983448Sdh155122 	switch (otype)
8993448Sdh155122 	{
9003448Sdh155122 	case IPFLOOKUPITER_LIST :
9013448Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
9023448Sdh155122 		ip_pool_deref((ip_pool_t *)data, ifs);
9033448Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
9043448Sdh155122 		break;
9053448Sdh155122 
9063448Sdh155122 	case IPFLOOKUPITER_NODE :
9073448Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
9083448Sdh155122 		ip_pool_node_deref((ip_pool_node_t *)data, ifs);
9093448Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
9103448Sdh155122 		break;
9113448Sdh155122 	default :
9123448Sdh155122 		break;
9133448Sdh155122 	}
9142393Syz155240 }
9152393Syz155240 
9162393Syz155240 
9172393Syz155240 # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
9182393Syz155240       !defined(__hpux) && !defined(__sgi))
9192393Syz155240 static int
rn_freenode(struct radix_node * n,void * p,ipf_stack_t * ifs)9203448Sdh155122 rn_freenode(struct radix_node *n, void *p, ipf_stack_t *ifs)
9212393Syz155240 {
9222393Syz155240 	struct radix_node_head *rnh = p;
9232393Syz155240 	struct radix_node *d;
9242393Syz155240 
9252393Syz155240 	d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
9262393Syz155240 	if (d != NULL) {
9273448Sdh155122 		FreeS(d, ifs->ifs_max_keylen + 2 * sizeof (*d));
9282393Syz155240 	}
9292393Syz155240 	return 0;
9302393Syz155240 }
9312393Syz155240 
9322393Syz155240 
9332393Syz155240 void
rn_freehead(rnh)9342393Syz155240 rn_freehead(rnh)
9352393Syz155240       struct radix_node_head *rnh;
9362393Syz155240 {
9372393Syz155240 
9382393Syz155240 	(*rnh->rnh_walktree)(rnh, rn_freenode, rnh);
9392393Syz155240 
9402393Syz155240 	rnh->rnh_addaddr = NULL;
9412393Syz155240 	rnh->rnh_deladdr = NULL;
9422393Syz155240 	rnh->rnh_matchaddr = NULL;
9432393Syz155240 	rnh->rnh_lookup = NULL;
9442393Syz155240 	rnh->rnh_walktree = NULL;
9452393Syz155240 
9462393Syz155240 	Free(rnh);
9472393Syz155240 }
9482393Syz155240 # endif
9492393Syz155240 
9502393Syz155240 #endif /* IPFILTER_LOOKUP */
951