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