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
main(argc,argv)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
treeprint(ipo)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 /* ------------------------------------------------------------------------ */
ip_pool_init(ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_fini(ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_statistics(op,ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_find(unit,name,ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_findeq(ipo,addr,mask)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 /* ------------------------------------------------------------------------ */
ip_pool_search(tptr,version,dptr,fin,ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_insert(ipo,addr,mask,info,ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_create(op,ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_remove(ipo,ipe,ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_destroy(op,ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_flush(fp,ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_free(ipo,ifs)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 /* ------------------------------------------------------------------------ */
ip_pool_deref(ipo,ifs)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
ip_pool_node_deref(ipn,ifs)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
ip_pool_getnext(token,ilp,ifs)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
ip_pool_iterderef(otype,unit,data,ifs)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
rn_freenode(struct radix_node * n,void * p,ipf_stack_t * ifs)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
rn_freehead(rnh)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