xref: /titanic_52/usr/src/uts/common/inet/ipf/ip_pool.c (revision de22af4e795d4c10cbff9a60ec725aab46c03afe)
1ab25eeb5Syz155240 /*
2ab25eeb5Syz155240  * Copyright (C) 1993-2001, 2003 by Darren Reed.
3ab25eeb5Syz155240  *
4ab25eeb5Syz155240  * See the IPFILTER.LICENCE file for details on licencing.
5ab25eeb5Syz155240  *
6*de22af4eSJohn Ojemann  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
7ab25eeb5Syz155240  */
8ab25eeb5Syz155240 
9ab25eeb5Syz155240 #if defined(KERNEL) || defined(_KERNEL)
10ab25eeb5Syz155240 # undef KERNEL
11ab25eeb5Syz155240 # undef _KERNEL
12ab25eeb5Syz155240 # define        KERNEL	1
13ab25eeb5Syz155240 # define        _KERNEL	1
14ab25eeb5Syz155240 #endif
15ab25eeb5Syz155240 #if defined(__osf__)
16ab25eeb5Syz155240 # define _PROTO_NET_H_
17ab25eeb5Syz155240 #endif
18ab25eeb5Syz155240 #include <sys/errno.h>
19ab25eeb5Syz155240 #include <sys/types.h>
20ab25eeb5Syz155240 #include <sys/param.h>
21ab25eeb5Syz155240 #include <sys/file.h>
22ab25eeb5Syz155240 #if !defined(_KERNEL) && !defined(__KERNEL__)
23ab25eeb5Syz155240 # include <stdio.h>
24ab25eeb5Syz155240 # include <stdlib.h>
25ab25eeb5Syz155240 # include <string.h>
26ab25eeb5Syz155240 # define _KERNEL
27ab25eeb5Syz155240 # ifdef __OpenBSD__
28ab25eeb5Syz155240 struct file;
29ab25eeb5Syz155240 # endif
30ab25eeb5Syz155240 # include <sys/uio.h>
31ab25eeb5Syz155240 # undef _KERNEL
32ab25eeb5Syz155240 #else
33ab25eeb5Syz155240 # include <sys/systm.h>
34ab25eeb5Syz155240 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
35ab25eeb5Syz155240 #  include <sys/proc.h>
36ab25eeb5Syz155240 # endif
37ab25eeb5Syz155240 #endif
38ab25eeb5Syz155240 #include <sys/time.h>
39ab25eeb5Syz155240 #if !defined(linux)
40ab25eeb5Syz155240 # include <sys/protosw.h>
41ab25eeb5Syz155240 #endif
42ab25eeb5Syz155240 #include <sys/socket.h>
43ab25eeb5Syz155240 #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
44ab25eeb5Syz155240 # include <sys/mbuf.h>
45ab25eeb5Syz155240 #endif
46ab25eeb5Syz155240 #if defined(__SVR4) || defined(__svr4__)
47ab25eeb5Syz155240 # include <sys/filio.h>
48ab25eeb5Syz155240 # include <sys/byteorder.h>
49ab25eeb5Syz155240 # ifdef _KERNEL
50ab25eeb5Syz155240 #  include <sys/dditypes.h>
51ab25eeb5Syz155240 # endif
52ab25eeb5Syz155240 # include <sys/stream.h>
53ab25eeb5Syz155240 # include <sys/kmem.h>
54ab25eeb5Syz155240 #endif
55ab25eeb5Syz155240 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
56ab25eeb5Syz155240 # include <sys/malloc.h>
57ab25eeb5Syz155240 #endif
58ab25eeb5Syz155240 
59ab25eeb5Syz155240 #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
60ab25eeb5Syz155240      defined(__hpux) || defined(__sgi))
61ab25eeb5Syz155240 # ifdef __osf__
62ab25eeb5Syz155240 #  include <net/radix.h>
63ab25eeb5Syz155240 # endif
64ab25eeb5Syz155240 # include "radix_ipf_local.h"
65ab25eeb5Syz155240 # define _RADIX_H_
66ab25eeb5Syz155240 #endif
67ab25eeb5Syz155240 #include <net/if.h>
68ab25eeb5Syz155240 #include <netinet/in.h>
69ab25eeb5Syz155240 
70f4b3ec61Sdh155122 #include "netinet/ipf_stack.h"
71ab25eeb5Syz155240 #include "netinet/ip_compat.h"
72ab25eeb5Syz155240 #include "netinet/ip_fil.h"
73ab25eeb5Syz155240 #include "netinet/ip_pool.h"
74ab25eeb5Syz155240 
75ab25eeb5Syz155240 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
76ab25eeb5Syz155240       ((BSD >= 198911) && !defined(__osf__) && \
77ab25eeb5Syz155240       !defined(__hpux) && !defined(__sgi))
78ab25eeb5Syz155240 static int rn_freenode __P((struct radix_node *, void *));
79ab25eeb5Syz155240 #endif
80ab25eeb5Syz155240 
81ab25eeb5Syz155240 /* END OF INCLUDES */
82ab25eeb5Syz155240 
83ab25eeb5Syz155240 #if !defined(lint)
84ab25eeb5Syz155240 static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
85ab25eeb5Syz155240 static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $";
86ab25eeb5Syz155240 #endif
87ab25eeb5Syz155240 
88ab25eeb5Syz155240 #ifdef IPFILTER_LOOKUP
89ab25eeb5Syz155240 
90ab25eeb5Syz155240 /*
91ab25eeb5Syz155240  * Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
92ab25eeb5Syz155240  * NOTE: Insertion *MUST* be from greatest range to least for it to work!
93ab25eeb5Syz155240  * These should be replaced, eventually, by something else - most notably a
94ab25eeb5Syz155240  * interval searching method.  The important feature is to be able to find
95ab25eeb5Syz155240  * the best match.
96ab25eeb5Syz155240  *
97ab25eeb5Syz155240  * So why not use a radix tree for this?  As the first line implies, it
98ab25eeb5Syz155240  * has been written to work with a _range_ of addresses.  A range is not
99ab25eeb5Syz155240  * necessarily a match with any given netmask so what we end up dealing
100ab25eeb5Syz155240  * with is an interval tree.  Implementations of these are hard to find
101ab25eeb5Syz155240  * and the one herein is far from bug free.
102ab25eeb5Syz155240  *
103ab25eeb5Syz155240  * Sigh, in the end I became convinced that the bugs the code contained did
104ab25eeb5Syz155240  * not make it worthwhile not using radix trees.  For now the radix tree from
105ab25eeb5Syz155240  * 4.4 BSD is used, but this is not viewed as a long term solution.
106ab25eeb5Syz155240  */
107ab25eeb5Syz155240 
108ab25eeb5Syz155240 #ifdef TEST_POOL
109ab25eeb5Syz155240 void treeprint __P((ip_pool_t *));
110ab25eeb5Syz155240 
111ab25eeb5Syz155240 int
112ab25eeb5Syz155240 main(argc, argv)
113ab25eeb5Syz155240 	int argc;
114ab25eeb5Syz155240 	char *argv[];
115ab25eeb5Syz155240 {
116ab25eeb5Syz155240 	addrfamily_t a, b;
117ab25eeb5Syz155240 	iplookupop_t op;
118ab25eeb5Syz155240 	ip_pool_t *ipo;
119ab25eeb5Syz155240 	i6addr_t ip;
120*de22af4eSJohn Ojemann 	fr_info_t fin;
121ab25eeb5Syz155240 
122f4b3ec61Sdh155122 	RWLOCK_INIT(&ifs->ifs_ip_poolrw, "poolrw");
123f4b3ec61Sdh155122 	ip_pool_init(ifs);
124ab25eeb5Syz155240 
125ab25eeb5Syz155240 	bzero((char *)&a, sizeof(a));
126ab25eeb5Syz155240 	bzero((char *)&b, sizeof(b));
127ab25eeb5Syz155240 	bzero((char *)&ip, sizeof(ip));
128ab25eeb5Syz155240 	bzero((char *)&op, sizeof(op));
129ab25eeb5Syz155240 	strcpy(op.iplo_name, "0");
130ab25eeb5Syz155240 
131f4b3ec61Sdh155122 	if (ip_pool_create(&op, ifs) == 0)
132f4b3ec61Sdh155122 		ipo = ip_pool_find(0, "0", ifs);
133ab25eeb5Syz155240 
134ab25eeb5Syz155240 	a.adf_addr.in4.s_addr = 0x0a010203;
135ab25eeb5Syz155240 	b.adf_addr.in4.s_addr = 0xffffffff;
136f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
137f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
138ab25eeb5Syz155240 
139ab25eeb5Syz155240 	a.adf_addr.in4.s_addr = 0x0a000000;
140ab25eeb5Syz155240 	b.adf_addr.in4.s_addr = 0xff000000;
141f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
142f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
143ab25eeb5Syz155240 
144ab25eeb5Syz155240 	a.adf_addr.in4.s_addr = 0x0a010100;
145ab25eeb5Syz155240 	b.adf_addr.in4.s_addr = 0xffffff00;
146f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
147f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
148ab25eeb5Syz155240 
149ab25eeb5Syz155240 	a.adf_addr.in4.s_addr = 0x0a010200;
150ab25eeb5Syz155240 	b.adf_addr.in4.s_addr = 0xffffff00;
151f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
152f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 0, ifs);
153ab25eeb5Syz155240 
154ab25eeb5Syz155240 	a.adf_addr.in4.s_addr = 0x0a010000;
155ab25eeb5Syz155240 	b.adf_addr.in4.s_addr = 0xffff0000;
156f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
157f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
158ab25eeb5Syz155240 
159ab25eeb5Syz155240 	a.adf_addr.in4.s_addr = 0x0a01020f;
160ab25eeb5Syz155240 	b.adf_addr.in4.s_addr = 0xffffffff;
161f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
162f4b3ec61Sdh155122 	ip_pool_insert(ipo, &a, &b, 1, ifs);
163ab25eeb5Syz155240 #ifdef	DEBUG_POOL
164ab25eeb5Syz155240 treeprint(ipo);
165ab25eeb5Syz155240 #endif
166*de22af4eSJohn Ojemann 	fin.fin_plen = 20;
167ab25eeb5Syz155240 	ip.in4.s_addr = 0x0a00aabb;
168ab25eeb5Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
169*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
170ab25eeb5Syz155240 
171ab25eeb5Syz155240 	ip.in4.s_addr = 0x0a000001;
172ab25eeb5Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
173*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
174ab25eeb5Syz155240 
175ab25eeb5Syz155240 	ip.in4.s_addr = 0x0a000101;
176ab25eeb5Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
177*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
178ab25eeb5Syz155240 
179ab25eeb5Syz155240 	ip.in4.s_addr = 0x0a010001;
180ab25eeb5Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
181*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
182ab25eeb5Syz155240 
183ab25eeb5Syz155240 	ip.in4.s_addr = 0x0a010101;
184ab25eeb5Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
185*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
186ab25eeb5Syz155240 
187ab25eeb5Syz155240 	ip.in4.s_addr = 0x0a010201;
188ab25eeb5Syz155240 	printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
189*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
190ab25eeb5Syz155240 
191ab25eeb5Syz155240 	ip.in4.s_addr = 0x0a010203;
192ab25eeb5Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
193*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
194ab25eeb5Syz155240 
195ab25eeb5Syz155240 	ip.in4.s_addr = 0x0a01020f;
196ab25eeb5Syz155240 	printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
197*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
198ab25eeb5Syz155240 
199ab25eeb5Syz155240 	ip.in4.s_addr = 0x0b00aabb;
200ab25eeb5Syz155240 	printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
201*de22af4eSJohn Ojemann 		ip_pool_search(ipo, 4, &ip, &fin, ifs));
202ab25eeb5Syz155240 
203ab25eeb5Syz155240 #ifdef	DEBUG_POOL
204ab25eeb5Syz155240 treeprint(ipo);
205ab25eeb5Syz155240 #endif
206ab25eeb5Syz155240 
207f4b3ec61Sdh155122 	ip_pool_fini(ifs);
208ab25eeb5Syz155240 
209ab25eeb5Syz155240 	return 0;
210ab25eeb5Syz155240 }
211ab25eeb5Syz155240 
212ab25eeb5Syz155240 
213ab25eeb5Syz155240 void
214ab25eeb5Syz155240 treeprint(ipo)
215ab25eeb5Syz155240 ip_pool_t *ipo;
216ab25eeb5Syz155240 {
217ab25eeb5Syz155240 	ip_pool_node_t *c;
218ab25eeb5Syz155240 
219ab25eeb5Syz155240 	for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
220ab25eeb5Syz155240 		printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
221ab25eeb5Syz155240 			c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
222ab25eeb5Syz155240 			c->ipn_mask.adf_addr.in4.s_addr,
223ab25eeb5Syz155240 			c->ipn_info, c->ipn_hits);
224ab25eeb5Syz155240 }
225ab25eeb5Syz155240 #endif /* TEST_POOL */
226ab25eeb5Syz155240 
227ab25eeb5Syz155240 
228ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
229ab25eeb5Syz155240 /* Function:    ip_pool_init                                                */
230ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
231ab25eeb5Syz155240 /*                                                                          */
232ab25eeb5Syz155240 /* Initialise the routing table data structures where required.             */
233ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
234f4b3ec61Sdh155122 int ip_pool_init(ifs)
235f4b3ec61Sdh155122 ipf_stack_t *ifs;
236ab25eeb5Syz155240 {
237ab25eeb5Syz155240 
238f4b3ec61Sdh155122 	bzero(&ifs->ifs_ipoolstat, sizeof (ip_pool_stat_t));
239ab25eeb5Syz155240 
240c793af95Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
241ab25eeb5Syz155240 	rn_init();
242ab25eeb5Syz155240 #endif
243ab25eeb5Syz155240 	return 0;
244ab25eeb5Syz155240 }
245ab25eeb5Syz155240 
246ab25eeb5Syz155240 
247ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
248ab25eeb5Syz155240 /* Function:    ip_pool_fini                                                */
249ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
250ab25eeb5Syz155240 /* Locks:       WRITE(ipf_global)                                           */
251ab25eeb5Syz155240 /*                                                                          */
252ab25eeb5Syz155240 /* Clean up all the pool data structures allocated and call the cleanup     */
253ab25eeb5Syz155240 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
254ab25eeb5Syz155240 /* used to delete the pools one by one to ensure they're properly freed up. */
255ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
256f4b3ec61Sdh155122 void ip_pool_fini(ifs)
257f4b3ec61Sdh155122 ipf_stack_t *ifs;
258ab25eeb5Syz155240 {
259ab25eeb5Syz155240 	ip_pool_t *p, *q;
260ab25eeb5Syz155240 	iplookupop_t op;
261ab25eeb5Syz155240 	int i;
262ab25eeb5Syz155240 
263f4b3ec61Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0);
264ab25eeb5Syz155240 
265ab25eeb5Syz155240 	for (i = 0; i <= IPL_LOGMAX; i++) {
266f4b3ec61Sdh155122 		for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) {
267ab25eeb5Syz155240 			op.iplo_unit = i;
268ab25eeb5Syz155240 			(void)strncpy(op.iplo_name, p->ipo_name,
269ab25eeb5Syz155240 				sizeof(op.iplo_name));
270ab25eeb5Syz155240 			q = p->ipo_next;
271f4b3ec61Sdh155122 			(void) ip_pool_destroy(&op, ifs);
272ab25eeb5Syz155240 		}
273ab25eeb5Syz155240 	}
274ab25eeb5Syz155240 
275c793af95Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
276ab25eeb5Syz155240 	rn_fini();
277ab25eeb5Syz155240 #endif
278ab25eeb5Syz155240 }
279ab25eeb5Syz155240 
280ab25eeb5Syz155240 
281ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
282ab25eeb5Syz155240 /* Function:    ip_pool_statistics                                          */
283ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
284ab25eeb5Syz155240 /* Parameters:  op(I)   - pointer to lookup operation arguments             */
285ab25eeb5Syz155240 /*                                                                          */
286ab25eeb5Syz155240 /* Copy the current statistics out into user space, collecting pool list    */
287ab25eeb5Syz155240 /* pointers as appropriate for later use.                                   */
288ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
289f4b3ec61Sdh155122 int ip_pool_statistics(op, ifs)
290ab25eeb5Syz155240 iplookupop_t *op;
291f4b3ec61Sdh155122 ipf_stack_t *ifs;
292ab25eeb5Syz155240 {
293ab25eeb5Syz155240 	ip_pool_stat_t stats;
294ab25eeb5Syz155240 	int unit, i, err = 0;
295ab25eeb5Syz155240 
296f4b3ec61Sdh155122 	if (op->iplo_size != sizeof(ip_pool_stat_t))
297ab25eeb5Syz155240 		return EINVAL;
298ab25eeb5Syz155240 
299f4b3ec61Sdh155122 	bcopy((char *)&ifs->ifs_ipoolstat, (char *)&stats, sizeof(stats));
300ab25eeb5Syz155240 	unit = op->iplo_unit;
301ab25eeb5Syz155240 	if (unit == IPL_LOGALL) {
302ab25eeb5Syz155240 		for (i = 0; i < IPL_LOGSIZE; i++)
303f4b3ec61Sdh155122 			stats.ipls_list[i] = ifs->ifs_ip_pool_list[i];
304ab25eeb5Syz155240 	} else if (unit >= 0 && unit < IPL_LOGSIZE) {
305ab25eeb5Syz155240 		if (op->iplo_name[0] != '\0')
306ab25eeb5Syz155240 			stats.ipls_list[unit] = ip_pool_find(unit,
307f4b3ec61Sdh155122 							     op->iplo_name, ifs);
308ab25eeb5Syz155240 		else
309f4b3ec61Sdh155122 			stats.ipls_list[unit] = ifs->ifs_ip_pool_list[unit];
310ab25eeb5Syz155240 	} else
311ab25eeb5Syz155240 		err = EINVAL;
312ab25eeb5Syz155240 	if (err == 0)
313ab25eeb5Syz155240 		err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
314ab25eeb5Syz155240 	return err;
315ab25eeb5Syz155240 }
316ab25eeb5Syz155240 
317ab25eeb5Syz155240 
318ab25eeb5Syz155240 
319ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
320ab25eeb5Syz155240 /* Function:    ip_pool_find                                                */
321ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
322ab25eeb5Syz155240 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
323ab25eeb5Syz155240 /*                                                                          */
324ab25eeb5Syz155240 /* Find a matching pool inside the collection of pools for a particular     */
325ab25eeb5Syz155240 /* device, indicated by the unit number.                                    */
326ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
327f4b3ec61Sdh155122 void *ip_pool_find(unit, name, ifs)
328ab25eeb5Syz155240 int unit;
329ab25eeb5Syz155240 char *name;
330f4b3ec61Sdh155122 ipf_stack_t *ifs;
331ab25eeb5Syz155240 {
332ab25eeb5Syz155240 	ip_pool_t *p;
333ab25eeb5Syz155240 
334f4b3ec61Sdh155122 	for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; p = p->ipo_next)
335ab25eeb5Syz155240 		if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
336ab25eeb5Syz155240 			break;
337ab25eeb5Syz155240 	return p;
338ab25eeb5Syz155240 }
339ab25eeb5Syz155240 
340ab25eeb5Syz155240 
341ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
342ab25eeb5Syz155240 /* Function:    ip_pool_findeq                                              */
343ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
344ab25eeb5Syz155240 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
345ab25eeb5Syz155240 /*              addr(I) - pointer to address information to delete          */
346ab25eeb5Syz155240 /*              mask(I) -                                                   */
347ab25eeb5Syz155240 /*                                                                          */
348ab25eeb5Syz155240 /* Searches for an exact match of an entry in the pool.                     */
349ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
350ab25eeb5Syz155240 ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
351ab25eeb5Syz155240 ip_pool_t *ipo;
352ab25eeb5Syz155240 addrfamily_t *addr, *mask;
353ab25eeb5Syz155240 {
354ab25eeb5Syz155240 	struct radix_node *n;
355ab25eeb5Syz155240 	SPL_INT(s);
356ab25eeb5Syz155240 
357ab25eeb5Syz155240 	SPL_NET(s);
358ab25eeb5Syz155240 	n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
359ab25eeb5Syz155240 	SPL_X(s);
360ab25eeb5Syz155240 	return (ip_pool_node_t *)n;
361ab25eeb5Syz155240 }
362ab25eeb5Syz155240 
363ab25eeb5Syz155240 
364ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
365ab25eeb5Syz155240 /* Function:    ip_pool_search                                              */
366ab25eeb5Syz155240 /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve/no match    */
367ab25eeb5Syz155240 /* Parameters:  tptr(I)    - pointer to the pool to search                  */
368ab25eeb5Syz155240 /*              version(I) - IP protocol version (4 or 6)                   */
369ab25eeb5Syz155240 /*              dptr(I)    - pointer to address information                 */
370*de22af4eSJohn Ojemann /*		fin	   - pointer to packet information		    */
371*de22af4eSJohn Ojemann /*		ifs	   - ipf stack instance				    */
372ab25eeb5Syz155240 /*                                                                          */
373ab25eeb5Syz155240 /* Search the pool for a given address and return a search result.          */
374ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
375*de22af4eSJohn Ojemann int ip_pool_search(tptr, version, dptr, fin, ifs)
376ab25eeb5Syz155240 void *tptr;
377ab25eeb5Syz155240 int version;
378ab25eeb5Syz155240 void *dptr;
379*de22af4eSJohn Ojemann fr_info_t *fin;
380f4b3ec61Sdh155122 ipf_stack_t *ifs;
381ab25eeb5Syz155240 {
382ab25eeb5Syz155240 	struct radix_node *rn;
383ab25eeb5Syz155240 	ip_pool_node_t *m;
384ab25eeb5Syz155240 	i6addr_t *addr;
385ab25eeb5Syz155240 	addrfamily_t v;
386ab25eeb5Syz155240 	ip_pool_t *ipo;
387ab25eeb5Syz155240 	int rv;
388ab25eeb5Syz155240 
389ab25eeb5Syz155240 	ipo = tptr;
390ab25eeb5Syz155240 	if (ipo == NULL)
391ab25eeb5Syz155240 		return -1;
392ab25eeb5Syz155240 
393ab25eeb5Syz155240 	rv = 1;
394ab25eeb5Syz155240 	m = NULL;
395ab25eeb5Syz155240 	addr = (i6addr_t *)dptr;
396ab25eeb5Syz155240 	bzero(&v, sizeof(v));
397ab25eeb5Syz155240 	v.adf_len = offsetof(addrfamily_t, adf_addr);
398ab25eeb5Syz155240 
399ab25eeb5Syz155240 	if (version == 4) {
400ab25eeb5Syz155240 		v.adf_len += sizeof(addr->in4);
401ab25eeb5Syz155240 		v.adf_addr.in4 = addr->in4;
402ab25eeb5Syz155240 #ifdef USE_INET6
403ab25eeb5Syz155240 	} else if (version == 6) {
404ab25eeb5Syz155240 		v.adf_len += sizeof(addr->in6);
405ab25eeb5Syz155240 		v.adf_addr.in6 = addr->in6;
406ab25eeb5Syz155240 #endif
407ab25eeb5Syz155240 	} else
408ab25eeb5Syz155240 		return -1;
409ab25eeb5Syz155240 
410f4b3ec61Sdh155122 	READ_ENTER(&ifs->ifs_ip_poolrw);
411ab25eeb5Syz155240 
412ab25eeb5Syz155240 	rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
413ab25eeb5Syz155240 
414ab25eeb5Syz155240 	if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
415ab25eeb5Syz155240 		m = (ip_pool_node_t *)rn;
416ab25eeb5Syz155240 		ipo->ipo_hits++;
417ab25eeb5Syz155240 		m->ipn_hits++;
418*de22af4eSJohn Ojemann 		m->ipn_bytes += fin->fin_plen;
419ab25eeb5Syz155240 		rv = m->ipn_info;
420ab25eeb5Syz155240 	}
421f4b3ec61Sdh155122 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
422ab25eeb5Syz155240 	return rv;
423ab25eeb5Syz155240 }
424ab25eeb5Syz155240 
425ab25eeb5Syz155240 
426ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
427ab25eeb5Syz155240 /* Function:    ip_pool_insert                                              */
428ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
429ab25eeb5Syz155240 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
430ab25eeb5Syz155240 /*              addr(I) - IPv4/6 address being added as a node              */
431ab25eeb5Syz155240 /*              mask(I) - IPv4/6 netmask to with the node being added       */
432ab25eeb5Syz155240 /*              info(I) - extra information to store in this node.          */
433ab25eeb5Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
434ab25eeb5Syz155240 /*                                                                          */
435ab25eeb5Syz155240 /* Add another node to the pool given by ipo.  The three parameters passed  */
436ab25eeb5Syz155240 /* in (addr, mask, info) shold all be stored in the node.                   */
437ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
438f4b3ec61Sdh155122 int ip_pool_insert(ipo, addr, mask, info, ifs)
439ab25eeb5Syz155240 ip_pool_t *ipo;
440ab25eeb5Syz155240 addrfamily_t *addr, *mask;
441ab25eeb5Syz155240 int info;
442f4b3ec61Sdh155122 ipf_stack_t *ifs;
443ab25eeb5Syz155240 {
444ab25eeb5Syz155240 	struct radix_node *rn;
445ab25eeb5Syz155240 	ip_pool_node_t *x;
446ab25eeb5Syz155240 
447f4b3ec61Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
448ab25eeb5Syz155240 
449ab25eeb5Syz155240 	KMALLOC(x, ip_pool_node_t *);
450ab25eeb5Syz155240 	if (x == NULL) {
451ab25eeb5Syz155240 		return ENOMEM;
452ab25eeb5Syz155240 	}
453ab25eeb5Syz155240 
454ab25eeb5Syz155240 	bzero(x, sizeof(*x));
455ab25eeb5Syz155240 
456ab25eeb5Syz155240 	x->ipn_info = info;
457ab25eeb5Syz155240 	(void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
458ab25eeb5Syz155240 
459ab25eeb5Syz155240 	bcopy(addr, &x->ipn_addr, sizeof(*addr));
460ab25eeb5Syz155240 	x->ipn_addr.adf_len = sizeof(x->ipn_addr);
461ab25eeb5Syz155240 	bcopy(mask, &x->ipn_mask, sizeof(*mask));
462ab25eeb5Syz155240 	x->ipn_mask.adf_len = sizeof(x->ipn_mask);
463ab25eeb5Syz155240 
464ab25eeb5Syz155240 	rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
465ab25eeb5Syz155240 					ipo->ipo_head, x->ipn_nodes);
466ab25eeb5Syz155240 #ifdef	DEBUG_POOL
467ab25eeb5Syz155240 	printf("Added %p at %p\n", x, rn);
468ab25eeb5Syz155240 #endif
469ab25eeb5Syz155240 
470ab25eeb5Syz155240 	if (rn == NULL) {
471ab25eeb5Syz155240 		KFREE(x);
472ab25eeb5Syz155240 		return ENOMEM;
473ab25eeb5Syz155240 	}
474ab25eeb5Syz155240 
475f4b3ec61Sdh155122 	x->ipn_ref = 1;
476ab25eeb5Syz155240 	x->ipn_next = ipo->ipo_list;
477ab25eeb5Syz155240 	x->ipn_pnext = &ipo->ipo_list;
478ab25eeb5Syz155240 	if (ipo->ipo_list != NULL)
479ab25eeb5Syz155240 		ipo->ipo_list->ipn_pnext = &x->ipn_next;
480ab25eeb5Syz155240 	ipo->ipo_list = x;
481ab25eeb5Syz155240 
482f4b3ec61Sdh155122 	ifs->ifs_ipoolstat.ipls_nodes++;
483ab25eeb5Syz155240 
484ab25eeb5Syz155240 	return 0;
485ab25eeb5Syz155240 }
486ab25eeb5Syz155240 
487ab25eeb5Syz155240 
488ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
489ab25eeb5Syz155240 /* Function:    ip_pool_create                                              */
490ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
491ab25eeb5Syz155240 /* Parameters:  op(I) - pointer to iplookup struct with call details        */
492ab25eeb5Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
493ab25eeb5Syz155240 /*                                                                          */
494ab25eeb5Syz155240 /* Creates a new group according to the paramters passed in via the         */
495ab25eeb5Syz155240 /* iplookupop structure.  Does not check to see if the group already exists */
496ab25eeb5Syz155240 /* when being inserted - assume this has already been done.  If the pool is */
497ab25eeb5Syz155240 /* marked as being anonymous, give it a new, unique, identifier.  Call any  */
498ab25eeb5Syz155240 /* other functions required to initialise the structure.                    */
499ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
500f4b3ec61Sdh155122 int ip_pool_create(op, ifs)
501ab25eeb5Syz155240 iplookupop_t *op;
502f4b3ec61Sdh155122 ipf_stack_t *ifs;
503ab25eeb5Syz155240 {
504ab25eeb5Syz155240 	char name[FR_GROUPLEN];
505ab25eeb5Syz155240 	int poolnum, unit;
506ab25eeb5Syz155240 	ip_pool_t *h;
507ab25eeb5Syz155240 
508f4b3ec61Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
509ab25eeb5Syz155240 
510ab25eeb5Syz155240 	KMALLOC(h, ip_pool_t *);
511ab25eeb5Syz155240 	if (h == NULL)
512ab25eeb5Syz155240 		return ENOMEM;
513ab25eeb5Syz155240 	bzero(h, sizeof(*h));
514ab25eeb5Syz155240 
515ab25eeb5Syz155240 	if (rn_inithead((void **)&h->ipo_head,
516ab25eeb5Syz155240 			offsetof(addrfamily_t, adf_addr) << 3) == 0) {
517ab25eeb5Syz155240 		KFREE(h);
518ab25eeb5Syz155240 		return ENOMEM;
519ab25eeb5Syz155240 	}
520ab25eeb5Syz155240 
521ab25eeb5Syz155240 	unit = op->iplo_unit;
522ab25eeb5Syz155240 
523ab25eeb5Syz155240 	if ((op->iplo_arg & IPOOL_ANON) != 0) {
524ab25eeb5Syz155240 		ip_pool_t *p;
525ab25eeb5Syz155240 
526ab25eeb5Syz155240 		poolnum = IPOOL_ANON;
527ab25eeb5Syz155240 
528ab25eeb5Syz155240 #if defined(SNPRINTF) && defined(_KERNEL)
529ab25eeb5Syz155240 		(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
530ab25eeb5Syz155240 #else
531ab25eeb5Syz155240 		(void)sprintf(name, "%x", poolnum);
532ab25eeb5Syz155240 #endif
533ab25eeb5Syz155240 
534f4b3ec61Sdh155122 		for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; ) {
535ab25eeb5Syz155240 			if (strncmp(name, p->ipo_name,
536ab25eeb5Syz155240 				    sizeof(p->ipo_name)) == 0) {
537ab25eeb5Syz155240 				poolnum++;
538ab25eeb5Syz155240 #if defined(SNPRINTF) && defined(_KERNEL)
539ab25eeb5Syz155240 				(void)SNPRINTF(name, sizeof(name), "%x", poolnum);
540ab25eeb5Syz155240 #else
541ab25eeb5Syz155240 				(void)sprintf(name, "%x", poolnum);
542ab25eeb5Syz155240 #endif
543f4b3ec61Sdh155122 				p = ifs->ifs_ip_pool_list[unit];
544ab25eeb5Syz155240 			} else
545ab25eeb5Syz155240 				p = p->ipo_next;
546ab25eeb5Syz155240 		}
547ab25eeb5Syz155240 
548ab25eeb5Syz155240 		(void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
549ab25eeb5Syz155240 	} else {
550ab25eeb5Syz155240 		(void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
551ab25eeb5Syz155240 	}
552ab25eeb5Syz155240 
553ab25eeb5Syz155240 	h->ipo_ref = 1;
554ab25eeb5Syz155240 	h->ipo_list = NULL;
555ab25eeb5Syz155240 	h->ipo_unit = unit;
556f4b3ec61Sdh155122 	h->ipo_next = ifs->ifs_ip_pool_list[unit];
557f4b3ec61Sdh155122 	if (ifs->ifs_ip_pool_list[unit] != NULL)
558f4b3ec61Sdh155122 		ifs->ifs_ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
559f4b3ec61Sdh155122 	h->ipo_pnext = &ifs->ifs_ip_pool_list[unit];
560f4b3ec61Sdh155122 	ifs->ifs_ip_pool_list[unit] = h;
561ab25eeb5Syz155240 
562f4b3ec61Sdh155122 	ifs->ifs_ipoolstat.ipls_pools++;
563ab25eeb5Syz155240 
564ab25eeb5Syz155240 	return 0;
565ab25eeb5Syz155240 }
566ab25eeb5Syz155240 
567ab25eeb5Syz155240 
568ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
569ab25eeb5Syz155240 /* Function:    ip_pool_remove                                              */
570ab25eeb5Syz155240 /* Returns:     int    - 0 = success, else error                            */
571ab25eeb5Syz155240 /* Parameters:  ipo(I) - pointer to the pool to remove the node from.       */
572ab25eeb5Syz155240 /*              ipe(I) - address being deleted as a node                    */
573ab25eeb5Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
574ab25eeb5Syz155240 /*                                                                          */
575ab25eeb5Syz155240 /* Add another node to the pool given by ipo.  The three parameters passed  */
576ab25eeb5Syz155240 /* in (addr, mask, info) shold all be stored in the node.                   */
577ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
578f4b3ec61Sdh155122 int ip_pool_remove(ipo, ipe, ifs)
579ab25eeb5Syz155240 ip_pool_t *ipo;
580ab25eeb5Syz155240 ip_pool_node_t *ipe;
581f4b3ec61Sdh155122 ipf_stack_t *ifs;
582ab25eeb5Syz155240 {
583ab25eeb5Syz155240 	ip_pool_node_t **ipp, *n;
584ab25eeb5Syz155240 
585f4b3ec61Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
586ab25eeb5Syz155240 
587ab25eeb5Syz155240 	for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) {
588ab25eeb5Syz155240 		if (ipe == n) {
589ab25eeb5Syz155240 			*n->ipn_pnext = n->ipn_next;
590ab25eeb5Syz155240 			if (n->ipn_next)
591ab25eeb5Syz155240 				n->ipn_next->ipn_pnext = n->ipn_pnext;
592ab25eeb5Syz155240 			break;
593ab25eeb5Syz155240 		}
594ab25eeb5Syz155240 	}
595ab25eeb5Syz155240 
596ab25eeb5Syz155240 	if (n == NULL)
597ab25eeb5Syz155240 		return ENOENT;
598ab25eeb5Syz155240 
599ab25eeb5Syz155240 	ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
600ab25eeb5Syz155240 				   ipo->ipo_head);
601ab25eeb5Syz155240 	KFREE(n);
602ab25eeb5Syz155240 
603f4b3ec61Sdh155122 	ifs->ifs_ipoolstat.ipls_nodes--;
604ab25eeb5Syz155240 
605ab25eeb5Syz155240 	return 0;
606ab25eeb5Syz155240 }
607ab25eeb5Syz155240 
608ab25eeb5Syz155240 
609ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
610ab25eeb5Syz155240 /* Function:    ip_pool_destroy                                             */
611ab25eeb5Syz155240 /* Returns:     int    - 0 = success, else error                            */
612ab25eeb5Syz155240 /* Parameters:  op(I)  -  information about the pool to remove              */
613ab25eeb5Syz155240 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
614ab25eeb5Syz155240 /*                                                                          */
615ab25eeb5Syz155240 /* Search for a pool using paramters passed in and if it's not otherwise    */
616ab25eeb5Syz155240 /* busy, free it.                                                           */
617ab25eeb5Syz155240 /*                                                                          */
618ab25eeb5Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
619ab25eeb5Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
620ab25eeb5Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
621ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
622f4b3ec61Sdh155122 int ip_pool_destroy(op, ifs)
623ab25eeb5Syz155240 iplookupop_t *op;
624f4b3ec61Sdh155122 ipf_stack_t *ifs;
625ab25eeb5Syz155240 {
626ab25eeb5Syz155240 	ip_pool_t *ipo;
627ab25eeb5Syz155240 
628f4b3ec61Sdh155122 	ipo = ip_pool_find(op->iplo_unit, op->iplo_name, ifs);
629ab25eeb5Syz155240 	if (ipo == NULL)
630ab25eeb5Syz155240 		return ESRCH;
631ab25eeb5Syz155240 
632ab25eeb5Syz155240 	if (ipo->ipo_ref != 1)
633ab25eeb5Syz155240 		return EBUSY;
634ab25eeb5Syz155240 
635f4b3ec61Sdh155122 	ip_pool_free(ipo, ifs);
636ab25eeb5Syz155240 	return 0;
637ab25eeb5Syz155240 }
638ab25eeb5Syz155240 
639ab25eeb5Syz155240 
640ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
641ab25eeb5Syz155240 /* Function:    ip_pool_flush                                               */
642ab25eeb5Syz155240 /* Returns:     int    - number of pools deleted                            */
643ab25eeb5Syz155240 /* Parameters:  fp(I)  - which pool(s) to flush                             */
644ab25eeb5Syz155240 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
645ab25eeb5Syz155240 /*                                                                          */
646ab25eeb5Syz155240 /* Free all pools associated with the device that matches the unit number   */
647ab25eeb5Syz155240 /* passed in with operation.                                                */
648ab25eeb5Syz155240 /*                                                                          */
649ab25eeb5Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
650ab25eeb5Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
651ab25eeb5Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
652ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
653f4b3ec61Sdh155122 int ip_pool_flush(fp, ifs)
654ab25eeb5Syz155240 iplookupflush_t *fp;
655f4b3ec61Sdh155122 ipf_stack_t *ifs;
656ab25eeb5Syz155240 {
657ab25eeb5Syz155240 	int i, num = 0, unit, err;
658ab25eeb5Syz155240 	ip_pool_t *p, *q;
659ab25eeb5Syz155240 	iplookupop_t op;
660ab25eeb5Syz155240 
661ab25eeb5Syz155240 	unit = fp->iplf_unit;
662ab25eeb5Syz155240 
663ab25eeb5Syz155240 	for (i = 0; i <= IPL_LOGMAX; i++) {
664ab25eeb5Syz155240 		if (unit != IPLT_ALL && i != unit)
665ab25eeb5Syz155240 			continue;
666f4b3ec61Sdh155122 		for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) {
667ab25eeb5Syz155240 			op.iplo_unit = i;
668ab25eeb5Syz155240 			(void)strncpy(op.iplo_name, p->ipo_name,
669ab25eeb5Syz155240 				sizeof(op.iplo_name));
670ab25eeb5Syz155240 			q = p->ipo_next;
671f4b3ec61Sdh155122 			err = ip_pool_destroy(&op, ifs);
672ab25eeb5Syz155240 			if (err == 0)
673ab25eeb5Syz155240 				num++;
674ab25eeb5Syz155240 			else
675ab25eeb5Syz155240 				break;
676ab25eeb5Syz155240 		}
677ab25eeb5Syz155240 	}
678ab25eeb5Syz155240 	return num;
679ab25eeb5Syz155240 }
680ab25eeb5Syz155240 
681ab25eeb5Syz155240 
682ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
683ab25eeb5Syz155240 /* Function:    ip_pool_free                                                */
684ab25eeb5Syz155240 /* Returns:     void                                                        */
685ab25eeb5Syz155240 /* Parameters:  ipo(I) -  pointer to pool structure                         */
686ab25eeb5Syz155240 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
687ab25eeb5Syz155240 /*                                                                          */
688ab25eeb5Syz155240 /* Deletes the pool strucutre passed in from the list of pools and deletes  */
689ab25eeb5Syz155240 /* all of the address information stored in it, including any tree data     */
690ab25eeb5Syz155240 /* structures also allocated.                                               */
691ab25eeb5Syz155240 /*                                                                          */
692ab25eeb5Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
693ab25eeb5Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
694ab25eeb5Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
695ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
696f4b3ec61Sdh155122 void ip_pool_free(ipo, ifs)
697ab25eeb5Syz155240 ip_pool_t *ipo;
698f4b3ec61Sdh155122 ipf_stack_t *ifs;
699ab25eeb5Syz155240 {
700ab25eeb5Syz155240 	ip_pool_node_t *n;
701ab25eeb5Syz155240 
702ab25eeb5Syz155240 	while ((n = ipo->ipo_list) != NULL) {
703ab25eeb5Syz155240 		ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
704ab25eeb5Syz155240 					   ipo->ipo_head);
705ab25eeb5Syz155240 
706ab25eeb5Syz155240 		*n->ipn_pnext = n->ipn_next;
707ab25eeb5Syz155240 		if (n->ipn_next)
708ab25eeb5Syz155240 			n->ipn_next->ipn_pnext = n->ipn_pnext;
709ab25eeb5Syz155240 
710ab25eeb5Syz155240 		KFREE(n);
711ab25eeb5Syz155240 
712f4b3ec61Sdh155122 		ifs->ifs_ipoolstat.ipls_nodes--;
713ab25eeb5Syz155240 	}
714ab25eeb5Syz155240 
715ab25eeb5Syz155240 	ipo->ipo_list = NULL;
716ab25eeb5Syz155240 	if (ipo->ipo_next != NULL)
717ab25eeb5Syz155240 		ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
718ab25eeb5Syz155240 	*ipo->ipo_pnext = ipo->ipo_next;
719ab25eeb5Syz155240 	rn_freehead(ipo->ipo_head);
720ab25eeb5Syz155240 	KFREE(ipo);
721ab25eeb5Syz155240 
722f4b3ec61Sdh155122 	ifs->ifs_ipoolstat.ipls_pools--;
723ab25eeb5Syz155240 }
724ab25eeb5Syz155240 
725ab25eeb5Syz155240 
726ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
727ab25eeb5Syz155240 /* Function:    ip_pool_deref                                               */
728ab25eeb5Syz155240 /* Returns:     void                                                        */
729ab25eeb5Syz155240 /* Parameters:  ipo(I) -  pointer to pool structure                         */
730ab25eeb5Syz155240 /* Locks:       WRITE(ip_poolrw)                                            */
731ab25eeb5Syz155240 /*                                                                          */
732ab25eeb5Syz155240 /* Drop the number of known references to this pool structure by one and if */
733ab25eeb5Syz155240 /* we arrive at zero known references, free it.                             */
734ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
735f4b3ec61Sdh155122 void ip_pool_deref(ipo, ifs)
736ab25eeb5Syz155240 ip_pool_t *ipo;
737f4b3ec61Sdh155122 ipf_stack_t *ifs;
738ab25eeb5Syz155240 {
739ab25eeb5Syz155240 
740f4b3ec61Sdh155122 	ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
741ab25eeb5Syz155240 
742ab25eeb5Syz155240 	ipo->ipo_ref--;
743ab25eeb5Syz155240 	if (ipo->ipo_ref == 0)
744f4b3ec61Sdh155122 		ip_pool_free(ipo, ifs);
745f4b3ec61Sdh155122 }
746f4b3ec61Sdh155122 
747f4b3ec61Sdh155122 
748f4b3ec61Sdh155122 
749f4b3ec61Sdh155122 void ip_pool_node_deref(ipn, ifs)
750f4b3ec61Sdh155122 ip_pool_node_t *ipn;
751f4b3ec61Sdh155122 ipf_stack_t *ifs;
752f4b3ec61Sdh155122 {
753f4b3ec61Sdh155122 
754f4b3ec61Sdh155122 	ipn->ipn_ref--;
755f4b3ec61Sdh155122 
756f4b3ec61Sdh155122 	if (ipn->ipn_ref == 0) {
757f4b3ec61Sdh155122 		KFREE(ipn);
758f4b3ec61Sdh155122 		ifs->ifs_ipoolstat.ipls_nodes--;
759f4b3ec61Sdh155122 	}
760f4b3ec61Sdh155122 }
761f4b3ec61Sdh155122 
762f4b3ec61Sdh155122 
763f4b3ec61Sdh155122 int ip_pool_getnext(token, ilp, ifs)
764f4b3ec61Sdh155122 ipftoken_t *token;
765f4b3ec61Sdh155122 ipflookupiter_t *ilp;
766f4b3ec61Sdh155122 ipf_stack_t *ifs;
767f4b3ec61Sdh155122 {
768f4b3ec61Sdh155122 	ip_pool_node_t *node, zn, *nextnode;
769f4b3ec61Sdh155122 	ip_pool_t *ipo, zp, *nextipo;
770f4b3ec61Sdh155122 	int err;
771f4b3ec61Sdh155122 
772f4b3ec61Sdh155122 	err = 0;
773f4b3ec61Sdh155122 	node = NULL;
774f4b3ec61Sdh155122 	nextnode = NULL;
775f4b3ec61Sdh155122 	ipo = NULL;
776f4b3ec61Sdh155122 	nextipo = NULL;
777f4b3ec61Sdh155122 
778f4b3ec61Sdh155122 	READ_ENTER(&ifs->ifs_ip_poolrw);
779f4b3ec61Sdh155122 
780786c7074Sjojemann 	/*
781786c7074Sjojemann 	 * Get "previous" entry from the token and find the next entry.
782786c7074Sjojemann 	 *
783786c7074Sjojemann 	 * If we found an entry, add a reference to it and update the token.
784786c7074Sjojemann 	 * Otherwise, zero out data to be returned and NULL out token.
785786c7074Sjojemann 	 */
786f4b3ec61Sdh155122 	switch (ilp->ili_otype)
787f4b3ec61Sdh155122 	{
788f4b3ec61Sdh155122 	case IPFLOOKUPITER_LIST :
789f4b3ec61Sdh155122 		ipo = token->ipt_data;
790f4b3ec61Sdh155122 		if (ipo == NULL) {
791f4b3ec61Sdh155122 			nextipo = ifs->ifs_ip_pool_list[(int)ilp->ili_unit];
792f4b3ec61Sdh155122 		} else {
793f4b3ec61Sdh155122 			nextipo = ipo->ipo_next;
794f4b3ec61Sdh155122 		}
795f4b3ec61Sdh155122 		if (nextipo != NULL) {
796f4b3ec61Sdh155122 			ATOMIC_INC(nextipo->ipo_ref);
797786c7074Sjojemann 			token->ipt_data = nextipo;
798f4b3ec61Sdh155122 		} else {
799f4b3ec61Sdh155122 			bzero((char *)&zp, sizeof(zp));
800f4b3ec61Sdh155122 			nextipo = &zp;
801786c7074Sjojemann 			token->ipt_data = NULL;
802f4b3ec61Sdh155122 		}
803f4b3ec61Sdh155122 		break;
804f4b3ec61Sdh155122 
805f4b3ec61Sdh155122 	case IPFLOOKUPITER_NODE :
806f4b3ec61Sdh155122 		node = token->ipt_data;
807f4b3ec61Sdh155122 		if (node == NULL) {
808f4b3ec61Sdh155122 			ipo = ip_pool_find(ilp->ili_unit, ilp->ili_name, ifs);
809f4b3ec61Sdh155122 			if (ipo == NULL)
810f4b3ec61Sdh155122 				err = ESRCH;
811f4b3ec61Sdh155122 			else {
812f4b3ec61Sdh155122 				nextnode = ipo->ipo_list;
813f4b3ec61Sdh155122 				ipo = NULL;
814f4b3ec61Sdh155122 			}
815f4b3ec61Sdh155122 		} else {
816f4b3ec61Sdh155122 			nextnode = node->ipn_next;
817f4b3ec61Sdh155122 		}
818f4b3ec61Sdh155122 		if (nextnode != NULL) {
819f4b3ec61Sdh155122 			ATOMIC_INC(nextnode->ipn_ref);
820786c7074Sjojemann 			token->ipt_data = nextnode;
821f4b3ec61Sdh155122 		} else {
822f4b3ec61Sdh155122 			bzero((char *)&zn, sizeof(zn));
823f4b3ec61Sdh155122 			nextnode = &zn;
824786c7074Sjojemann 			token->ipt_data = NULL;
825f4b3ec61Sdh155122 		}
826f4b3ec61Sdh155122 		break;
827786c7074Sjojemann 
828f4b3ec61Sdh155122 	default :
829f4b3ec61Sdh155122 		err = EINVAL;
830f4b3ec61Sdh155122 		break;
831f4b3ec61Sdh155122 	}
832f4b3ec61Sdh155122 
833786c7074Sjojemann 	/*
834786c7074Sjojemann 	 * Now that we have ref, it's save to give up lock.
835786c7074Sjojemann 	 */
836f4b3ec61Sdh155122 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
837f4b3ec61Sdh155122 
838f4b3ec61Sdh155122 	if (err != 0)
839f4b3ec61Sdh155122 		return err;
840f4b3ec61Sdh155122 
841786c7074Sjojemann 	/*
842786c7074Sjojemann 	 * Copy out the data and update the references and token as needed.
843786c7074Sjojemann 	 */
844f4b3ec61Sdh155122 	switch (ilp->ili_otype)
845f4b3ec61Sdh155122 	{
846f4b3ec61Sdh155122 	case IPFLOOKUPITER_LIST :
847786c7074Sjojemann 		err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo));
848786c7074Sjojemann 		if (err != 0)
849786c7074Sjojemann 			err = EFAULT;
850786c7074Sjojemann 		if (token->ipt_data == NULL) {
851786c7074Sjojemann 			ipf_freetoken(token, ifs);
852786c7074Sjojemann 		} else {
853f4b3ec61Sdh155122 			if (ipo != NULL) {
854f4b3ec61Sdh155122 				WRITE_ENTER(&ifs->ifs_ip_poolrw);
855f4b3ec61Sdh155122 				ip_pool_deref(ipo, ifs);
856f4b3ec61Sdh155122 				RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
857f4b3ec61Sdh155122 			}
858786c7074Sjojemann 			if (nextipo->ipo_next == NULL)
859786c7074Sjojemann 				ipf_freetoken(token, ifs);
860786c7074Sjojemann 		}
861f4b3ec61Sdh155122 		break;
862f4b3ec61Sdh155122 
863f4b3ec61Sdh155122 	case IPFLOOKUPITER_NODE :
864786c7074Sjojemann 		err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
865786c7074Sjojemann 		if (err != 0)
866786c7074Sjojemann 			err = EFAULT;
867786c7074Sjojemann 		if (token->ipt_data == NULL) {
868786c7074Sjojemann 			ipf_freetoken(token, ifs);
869786c7074Sjojemann 		} else {
870f4b3ec61Sdh155122 			if (node != NULL) {
871f4b3ec61Sdh155122 				WRITE_ENTER(&ifs->ifs_ip_poolrw);
872f4b3ec61Sdh155122 				ip_pool_node_deref(node, ifs);
873f4b3ec61Sdh155122 				RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
874f4b3ec61Sdh155122 			}
875786c7074Sjojemann 			if (nextnode->ipn_next == NULL)
876786c7074Sjojemann 				ipf_freetoken(token, ifs);
877786c7074Sjojemann 		}
878f4b3ec61Sdh155122 		break;
879f4b3ec61Sdh155122 	}
880f4b3ec61Sdh155122 
881f4b3ec61Sdh155122 	return err;
882f4b3ec61Sdh155122 }
883f4b3ec61Sdh155122 
884f4b3ec61Sdh155122 
885f4b3ec61Sdh155122 void ip_pool_iterderef(otype, unit, data, ifs)
886f4b3ec61Sdh155122 u_int otype;
887f4b3ec61Sdh155122 int unit;
888f4b3ec61Sdh155122 void *data;
889f4b3ec61Sdh155122 ipf_stack_t *ifs;
890f4b3ec61Sdh155122 {
891f4b3ec61Sdh155122 
892f4b3ec61Sdh155122 	if (data == NULL)
893f4b3ec61Sdh155122 		return;
894f4b3ec61Sdh155122 
895f4b3ec61Sdh155122 	if (unit < 0 || unit > IPL_LOGMAX)
896f4b3ec61Sdh155122 		return;
897f4b3ec61Sdh155122 
898f4b3ec61Sdh155122 	switch (otype)
899f4b3ec61Sdh155122 	{
900f4b3ec61Sdh155122 	case IPFLOOKUPITER_LIST :
901f4b3ec61Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
902f4b3ec61Sdh155122 		ip_pool_deref((ip_pool_t *)data, ifs);
903f4b3ec61Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
904f4b3ec61Sdh155122 		break;
905f4b3ec61Sdh155122 
906f4b3ec61Sdh155122 	case IPFLOOKUPITER_NODE :
907f4b3ec61Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
908f4b3ec61Sdh155122 		ip_pool_node_deref((ip_pool_node_t *)data, ifs);
909f4b3ec61Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
910f4b3ec61Sdh155122 		break;
911f4b3ec61Sdh155122 	default :
912f4b3ec61Sdh155122 		break;
913f4b3ec61Sdh155122 	}
914ab25eeb5Syz155240 }
915ab25eeb5Syz155240 
916ab25eeb5Syz155240 
917ab25eeb5Syz155240 # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
918ab25eeb5Syz155240       !defined(__hpux) && !defined(__sgi))
919ab25eeb5Syz155240 static int
920f4b3ec61Sdh155122 rn_freenode(struct radix_node *n, void *p, ipf_stack_t *ifs)
921ab25eeb5Syz155240 {
922ab25eeb5Syz155240 	struct radix_node_head *rnh = p;
923ab25eeb5Syz155240 	struct radix_node *d;
924ab25eeb5Syz155240 
925ab25eeb5Syz155240 	d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
926ab25eeb5Syz155240 	if (d != NULL) {
927f4b3ec61Sdh155122 		FreeS(d, ifs->ifs_max_keylen + 2 * sizeof (*d));
928ab25eeb5Syz155240 	}
929ab25eeb5Syz155240 	return 0;
930ab25eeb5Syz155240 }
931ab25eeb5Syz155240 
932ab25eeb5Syz155240 
933ab25eeb5Syz155240 void
934ab25eeb5Syz155240 rn_freehead(rnh)
935ab25eeb5Syz155240       struct radix_node_head *rnh;
936ab25eeb5Syz155240 {
937ab25eeb5Syz155240 
938ab25eeb5Syz155240 	(*rnh->rnh_walktree)(rnh, rn_freenode, rnh);
939ab25eeb5Syz155240 
940ab25eeb5Syz155240 	rnh->rnh_addaddr = NULL;
941ab25eeb5Syz155240 	rnh->rnh_deladdr = NULL;
942ab25eeb5Syz155240 	rnh->rnh_matchaddr = NULL;
943ab25eeb5Syz155240 	rnh->rnh_lookup = NULL;
944ab25eeb5Syz155240 	rnh->rnh_walktree = NULL;
945ab25eeb5Syz155240 
946ab25eeb5Syz155240 	Free(rnh);
947ab25eeb5Syz155240 }
948ab25eeb5Syz155240 # endif
949ab25eeb5Syz155240 
950ab25eeb5Syz155240 #endif /* IPFILTER_LOOKUP */
951