4 * Copyright (C) 1993-2001, 2003 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
8 * Copyright 2008 Sun Microsystems, Inc.
10 #if defined(KERNEL) || defined(_KERNEL)
17 # define _PROTO_NET_H_
19 #include <sys/errno.h>
20 #include <sys/types.h>
21 #include <sys/param.h>
22 #if defined(__NetBSD__)
23 # if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL)
24 # include "opt_ipfilter.h"
28 #if !defined(_KERNEL) && !defined(__KERNEL__)
39 # include <sys/systm.h>
40 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
41 # include <sys/proc.h>
45 #if defined(_KERNEL) && !defined(SOLARIS2)
46 # include <sys/mbuf.h>
48 #if defined(__SVR4) || defined(__svr4__)
49 # include <sys/byteorder.h>
51 # include <sys/dditypes.h>
53 # include <sys/stream.h>
54 # include <sys/kmem.h>
56 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
57 # include <sys/malloc.h>
60 #if defined(SOLARIS2) && !defined(_KERNEL)
61 # include "radix_ipf.h"
63 #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
64 defined(__hpux) || defined(__sgi))
65 # include "radix_ipf_local.h"
68 #include <sys/socket.h>
70 #include <netinet/in.h>
72 #include "netinet/ip_compat.h"
73 #include "netinet/ip_fil.h"
74 #include "netinet/ip_pool.h"
76 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
77 ((BSD >= 198911) && !defined(__osf__) && \
78 !defined(__hpux) && !defined(__sgi))
79 static int rn_freenode
__P((struct radix_node
*, void *));
85 #if defined(__NetBSD__)
86 #include <sys/cdefs.h>
87 __KERNEL_RCSID(0, "$NetBSD$");
89 static const char sccsid
[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
90 static const char rcsid
[] = "@(#)Id: ip_pool.c,v 2.55.2.31 2009/07/18 19:05:39 darrenr Exp";
94 #ifdef IPFILTER_LOOKUP
96 # if !defined(RADIX_NODE_HEAD_LOCK) || !defined(RADIX_NODE_HEAD_UNLOCK) || \
98 # undef RADIX_NODE_HEAD_LOCK
99 # undef RADIX_NODE_HEAD_UNLOCK
100 # define RADIX_NODE_HEAD_LOCK(x) ;
101 # define RADIX_NODE_HEAD_UNLOCK(x) ;
104 static void ip_pool_clearnodes
__P((ip_pool_t
*));
105 static void *ip_pool_exists
__P((int, char *));
107 ip_pool_stat_t ipoolstat
;
108 ipfrwlock_t ip_poolrw
;
110 ip_pool_t
*ip_pool_list
[IPL_LOGSIZE
] = { NULL
, NULL
, NULL
, NULL
,
111 NULL
, NULL
, NULL
, NULL
};
115 void treeprint
__P((ip_pool_t
*));
127 RWLOCK_INIT(&ip_poolrw
, "poolrw");
130 bzero((char *)&a
, sizeof(a
));
131 bzero((char *)&b
, sizeof(b
));
132 bzero((char *)&ip
, sizeof(ip
));
133 bzero((char *)&op
, sizeof(op
));
134 strlcpy(op
.iplo_name
, "0", sizeof(op
.iplo_name
));
136 if (ip_pool_create(&op
) == 0)
137 ipo
= ip_pool_exists(0, "0");
139 a
.adf_addr
.in4
.s_addr
= 0x0a010203;
140 b
.adf_addr
.in4
.s_addr
= 0xffffffff;
141 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
142 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
144 a
.adf_addr
.in4
.s_addr
= 0x0a000000;
145 b
.adf_addr
.in4
.s_addr
= 0xff000000;
146 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 0);
147 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 0);
149 a
.adf_addr
.in4
.s_addr
= 0x0a010100;
150 b
.adf_addr
.in4
.s_addr
= 0xffffff00;
151 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
152 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
154 a
.adf_addr
.in4
.s_addr
= 0x0a010200;
155 b
.adf_addr
.in4
.s_addr
= 0xffffff00;
156 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 0);
157 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 0);
159 a
.adf_addr
.in4
.s_addr
= 0x0a010000;
160 b
.adf_addr
.in4
.s_addr
= 0xffff0000;
161 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
162 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
164 a
.adf_addr
.in4
.s_addr
= 0x0a01020f;
165 b
.adf_addr
.in4
.s_addr
= 0xffffffff;
166 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
167 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
171 ip
.in4
.s_addr
= 0x0a00aabb;
172 printf("search(%#x) = %d (0)\n", ip
.in4
.s_addr
,
173 ip_pool_search(ipo
, 4, &ip
));
175 ip
.in4
.s_addr
= 0x0a000001;
176 printf("search(%#x) = %d (0)\n", ip
.in4
.s_addr
,
177 ip_pool_search(ipo
, 4, &ip
));
179 ip
.in4
.s_addr
= 0x0a000101;
180 printf("search(%#x) = %d (0)\n", ip
.in4
.s_addr
,
181 ip_pool_search(ipo
, 4, &ip
));
183 ip
.in4
.s_addr
= 0x0a010001;
184 printf("search(%#x) = %d (1)\n", ip
.in4
.s_addr
,
185 ip_pool_search(ipo
, 4, &ip
));
187 ip
.in4
.s_addr
= 0x0a010101;
188 printf("search(%#x) = %d (1)\n", ip
.in4
.s_addr
,
189 ip_pool_search(ipo
, 4, &ip
));
191 ip
.in4
.s_addr
= 0x0a010201;
192 printf("search(%#x) = %d (0)\n", ip
.in4
.s_addr
,
193 ip_pool_search(ipo
, 4, &ip
));
195 ip
.in4
.s_addr
= 0x0a010203;
196 printf("search(%#x) = %d (1)\n", ip
.in4
.s_addr
,
197 ip_pool_search(ipo
, 4, &ip
));
199 ip
.in4
.s_addr
= 0x0a01020f;
200 printf("search(%#x) = %d (1)\n", ip
.in4
.s_addr
,
201 ip_pool_search(ipo
, 4, &ip
));
203 ip
.in4
.s_addr
= 0x0b00aabb;
204 printf("search(%#x) = %d (-1)\n", ip
.in4
.s_addr
,
205 ip_pool_search(ipo
, 4, &ip
));
223 for (c
= ipo
->ipo_list
; c
!= NULL
; c
= c
->ipn_next
)
224 printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
225 c
, c
->ipn_name
, c
->ipn_addr
.adf_addr
.in4
.s_addr
,
226 c
->ipn_mask
.adf_addr
.in4
.s_addr
,
227 c
->ipn_info
, c
->ipn_hits
);
229 #endif /* TEST_POOL */
232 /* ------------------------------------------------------------------------ */
233 /* Function: ip_pool_init */
234 /* Returns: int - 0 = success, else error */
236 /* Initialise the routing table data structures where required. */
237 /* ------------------------------------------------------------------------ */
241 bzero((char *)&ipoolstat
, sizeof(ipoolstat
));
243 #if (!defined(_KERNEL) || !defined(BSD) || (BSD < 199306))
250 /* ------------------------------------------------------------------------ */
251 /* Function: ip_pool_fini */
252 /* Returns: int - 0 = success, else error */
253 /* Locks: WRITE(ipf_global) */
255 /* Clean up all the pool data structures allocated and call the cleanup */
256 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
257 /* used to delete the pools one by one to ensure they're properly freed up. */
258 /* ------------------------------------------------------------------------ */
264 for (i
= 0; i
<= IPL_LOGMAX
; i
++) {
265 for (q
= ip_pool_list
[i
]; (p
= q
) != NULL
; ) {
267 (void) ip_pool_destroy(i
, p
->ipo_name
);
271 #if (!defined(_KERNEL) || !defined(BSD) || (BSD < 199306))
277 /* ------------------------------------------------------------------------ */
278 /* Function: ip_pool_statistics */
279 /* Returns: int - 0 = success, else error */
280 /* Parameters: op(I) - pointer to lookup operation arguments */
282 /* Copy the current statistics out into user space, collecting pool list */
283 /* pointers as appropriate for later use. */
284 /* ------------------------------------------------------------------------ */
285 int ip_pool_statistics(op
)
288 ip_pool_stat_t stats
;
289 int unit
, i
, err
= 0;
291 if (op
->iplo_size
!= sizeof(ipoolstat
))
294 bcopy((char *)&ipoolstat
, (char *)&stats
, sizeof(stats
));
295 unit
= op
->iplo_unit
;
296 if (unit
== IPL_LOGALL
) {
297 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
298 stats
.ipls_list
[i
] = ip_pool_list
[i
];
299 } else if (unit
>= 0 && unit
< IPL_LOGSIZE
) {
300 if (op
->iplo_name
[0] != '\0')
301 stats
.ipls_list
[unit
] = ip_pool_exists(unit
,
304 stats
.ipls_list
[unit
] = ip_pool_list
[unit
];
308 err
= COPYOUT(&stats
, op
->iplo_struct
, sizeof(stats
));
313 /* ------------------------------------------------------------------------ */
314 /* Function: ip_pool_exists */
315 /* Returns: int - 0 = success, else error */
316 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
318 /* Find a matching pool inside the collection of pools for a particular */
319 /* device, indicated by the unit number. */
320 /* ------------------------------------------------------------------------ */
321 static void *ip_pool_exists(unit
, name
)
327 for (p
= ip_pool_list
[unit
]; p
!= NULL
; p
= p
->ipo_next
)
328 if (strncmp(p
->ipo_name
, name
, sizeof(p
->ipo_name
)) == 0)
334 /* ------------------------------------------------------------------------ */
335 /* Function: ip_pool_find */
336 /* Returns: int - 0 = success, else error */
337 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
339 /* Find a matching pool inside the collection of pools for a particular */
340 /* device, indicated by the unit number. If it is marked for deletion then */
341 /* pretend it does not exist. */
342 /* ------------------------------------------------------------------------ */
343 void *ip_pool_find(unit
, name
)
349 p
= ip_pool_exists(unit
, name
);
350 if ((p
!= NULL
) && (p
->ipo_flags
& IPOOL_DELETE
))
357 /* ------------------------------------------------------------------------ */
358 /* Function: ip_pool_findeq */
359 /* Returns: int - 0 = success, else error */
360 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
361 /* addr(I) - pointer to address information to delete */
364 /* Searches for an exact match of an entry in the pool. */
365 /* ------------------------------------------------------------------------ */
366 ip_pool_node_t
*ip_pool_findeq(ipo
, addr
, mask
)
368 addrfamily_t
*addr
, *mask
;
370 struct radix_node
*n
;
374 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
375 n
= ipo
->ipo_head
->rnh_lookup(addr
, mask
, ipo
->ipo_head
);
376 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
378 return (ip_pool_node_t
*)n
;
382 /* ------------------------------------------------------------------------ */
383 /* Function: ip_pool_search */
384 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
385 /* Parameters: tptr(I) - pointer to the pool to search */
386 /* ipversion(I) - IP protocol version (4 or 6) */
387 /* dptr(I) - pointer to address information */
389 /* Search the pool for a given address and return a search result. */
390 /* ------------------------------------------------------------------------ */
391 int ip_pool_search(tptr
, ipversion
, dptr
)
396 struct radix_node
*rn
;
409 addr
= (i6addr_t
*)dptr
;
410 bzero(&v
, sizeof(v
));
411 v
.adf_len
= offsetof(addrfamily_t
, adf_addr
);
413 if (ipversion
== 4) {
414 v
.adf_len
+= sizeof(addr
->in4
);
415 v
.adf_addr
.in4
= addr
->in4
;
417 } else if (ipversion
== 6) {
418 v
.adf_len
+= sizeof(addr
->in6
);
419 v
.adf_addr
.in6
= addr
->in6
;
424 READ_ENTER(&ip_poolrw
);
426 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
427 rn
= ipo
->ipo_head
->rnh_matchaddr(&v
, ipo
->ipo_head
);
428 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
430 if ((rn
!= NULL
) && ((rn
->rn_flags
& RNF_ROOT
) == 0)) {
431 m
= (ip_pool_node_t
*)rn
;
436 RWLOCK_EXIT(&ip_poolrw
);
441 /* ------------------------------------------------------------------------ */
442 /* Function: ip_pool_insert */
443 /* Returns: int - 0 = success, else error */
444 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
445 /* addr(I) - address being added as a node */
446 /* mask(I) - netmask to with the node being added */
447 /* info(I) - extra information to store in this node. */
448 /* Locks: WRITE(ip_poolrw) */
450 /* Add another node to the pool given by ipo. The three parameters passed */
451 /* in (addr, mask, info) shold all be stored in the node. */
452 /* ------------------------------------------------------------------------ */
453 int ip_pool_insert(ipo
, addr
, mask
, info
)
455 i6addr_t
*addr
, *mask
;
458 struct radix_node
*rn
;
461 KMALLOC(x
, ip_pool_node_t
*);
466 bzero(x
, sizeof(*x
));
469 (void)strncpy(x
->ipn_name
, ipo
->ipo_name
, sizeof(x
->ipn_name
));
471 bcopy(addr
, &x
->ipn_addr
.adf_addr
, sizeof(*addr
));
472 x
->ipn_addr
.adf_len
= sizeof(x
->ipn_addr
);
473 bcopy(mask
, &x
->ipn_mask
.adf_addr
, sizeof(*mask
));
474 x
->ipn_mask
.adf_len
= sizeof(x
->ipn_mask
);
476 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
477 rn
= ipo
->ipo_head
->rnh_addaddr(&x
->ipn_addr
, &x
->ipn_mask
,
478 ipo
->ipo_head
, x
->ipn_nodes
);
479 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
481 printf("Added %p at %p\n", x
, rn
);
490 x
->ipn_next
= ipo
->ipo_list
;
491 x
->ipn_pnext
= &ipo
->ipo_list
;
492 if (ipo
->ipo_list
!= NULL
)
493 ipo
->ipo_list
->ipn_pnext
= &x
->ipn_next
;
496 ipoolstat
.ipls_nodes
++;
502 /* ------------------------------------------------------------------------ */
503 /* Function: ip_pool_create */
504 /* Returns: int - 0 = success, else error */
505 /* Parameters: op(I) - pointer to iplookup struct with call details */
506 /* Locks: WRITE(ip_poolrw) */
508 /* Creates a new group according to the paramters passed in via the */
509 /* iplookupop structure. Does not check to see if the group already exists */
510 /* when being inserted - assume this has already been done. If the pool is */
511 /* marked as being anonymous, give it a new, unique, identifier. Call any */
512 /* other functions required to initialise the structure. */
514 /* If the structure is flagged for deletion then reset the flag and return, */
515 /* as this likely means we've tried to free a pool that is in use (flush) */
516 /* and now want to repopulate it with "new" data. */
517 /* ------------------------------------------------------------------------ */
518 int ip_pool_create(op
)
521 char name
[FR_GROUPLEN
];
525 unit
= op
->iplo_unit
;
527 if ((op
->iplo_arg
& LOOKUP_ANON
) == 0) {
528 h
= ip_pool_exists(unit
, op
->iplo_name
);
530 if ((h
->ipo_flags
& IPOOL_DELETE
) == 0)
532 h
->ipo_flags
&= ~IPOOL_DELETE
;
537 KMALLOC(h
, ip_pool_t
*);
540 bzero(h
, sizeof(*h
));
542 if (rn_inithead((void **)&h
->ipo_head
,
543 offsetof(addrfamily_t
, adf_addr
) << 3) == 0) {
548 if ((op
->iplo_arg
& LOOKUP_ANON
) != 0) {
551 h
->ipo_flags
|= IPOOL_ANON
;
552 poolnum
= LOOKUP_ANON
;
554 #if defined(SNPRINTF) && defined(_KERNEL)
555 SNPRINTF(name
, sizeof(name
), "%x", poolnum
);
557 (void)sprintf(name
, "%x", poolnum
);
560 for (p
= ip_pool_list
[unit
]; p
!= NULL
; ) {
561 if (strncmp(name
, p
->ipo_name
,
562 sizeof(p
->ipo_name
)) == 0) {
564 #if defined(SNPRINTF) && defined(_KERNEL)
565 SNPRINTF(name
, sizeof(name
), "%x", poolnum
);
567 (void)sprintf(name
, "%x", poolnum
);
569 p
= ip_pool_list
[unit
];
574 (void)strncpy(h
->ipo_name
, name
, sizeof(h
->ipo_name
));
575 (void)strncpy(op
->iplo_name
, name
, sizeof(op
->iplo_name
));
577 (void)strncpy(h
->ipo_name
, op
->iplo_name
, sizeof(h
->ipo_name
));
583 h
->ipo_next
= ip_pool_list
[unit
];
584 if (ip_pool_list
[unit
] != NULL
)
585 ip_pool_list
[unit
]->ipo_pnext
= &h
->ipo_next
;
586 h
->ipo_pnext
= &ip_pool_list
[unit
];
587 ip_pool_list
[unit
] = h
;
589 ipoolstat
.ipls_pools
++;
595 /* ------------------------------------------------------------------------ */
596 /* Function: ip_pool_remove */
597 /* Returns: int - 0 = success, else error */
598 /* Parameters: ipo(I) - pointer to the pool to remove the node from. */
599 /* ipe(I) - address being deleted as a node */
600 /* Locks: WRITE(ip_poolrw) */
602 /* Remove a node from the pool given by ipo. */
603 /* ------------------------------------------------------------------------ */
604 int ip_pool_remove(ipo
, ipe
)
609 if (ipe
->ipn_pnext
!= NULL
)
610 *ipe
->ipn_pnext
= ipe
->ipn_next
;
611 if (ipe
->ipn_next
!= NULL
)
612 ipe
->ipn_next
->ipn_pnext
= ipe
->ipn_pnext
;
614 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
615 ipo
->ipo_head
->rnh_deladdr(&ipe
->ipn_addr
, &ipe
->ipn_mask
,
617 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
619 ip_pool_node_deref(ipe
);
625 /* ------------------------------------------------------------------------ */
626 /* Function: ip_pool_destroy */
627 /* Returns: int - 0 = success, else error */
628 /* Parameters: op(I) - information about the pool to remove */
629 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
631 /* Search for a pool using paramters passed in and if it's not otherwise */
632 /* busy, free it. If it is busy, clear all of its nodes, mark it for being */
633 /* deleted and return an error saying it is busy. */
635 /* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
636 /* may not be initialised, we can't use an ASSERT to enforce the locking */
637 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
638 /* ------------------------------------------------------------------------ */
639 int ip_pool_destroy(unit
, name
)
645 ipo
= ip_pool_exists(unit
, name
);
649 if (ipo
->ipo_ref
!= 1) {
650 ip_pool_clearnodes(ipo
);
651 ipo
->ipo_flags
|= IPOOL_DELETE
;
660 /* ------------------------------------------------------------------------ */
661 /* Function: ip_pool_flush */
662 /* Returns: int - number of pools deleted */
663 /* Parameters: fp(I) - which pool(s) to flush */
664 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
666 /* Free all pools associated with the device that matches the unit number */
667 /* passed in with operation. */
669 /* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
670 /* may not be initialised, we can't use an ASSERT to enforce the locking */
671 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
672 /* ------------------------------------------------------------------------ */
673 int ip_pool_flush(fp
)
676 int i
, num
= 0, unit
, err
;
680 unit
= fp
->iplf_unit
;
682 for (i
= 0; i
<= IPL_LOGMAX
; i
++) {
683 if (unit
!= IPLT_ALL
&& i
!= unit
)
685 for (q
= ip_pool_list
[i
]; (p
= q
) != NULL
; ) {
687 (void)strncpy(op
.iplo_name
, p
->ipo_name
,
688 sizeof(op
.iplo_name
));
690 err
= ip_pool_destroy(op
.iplo_unit
, op
.iplo_name
);
701 /* ------------------------------------------------------------------------ */
702 /* Function: ip_pool_free */
704 /* Parameters: ipo(I) - pointer to pool structure */
705 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
707 /* Deletes the pool strucutre passed in from the list of pools and deletes */
708 /* all of the address information stored in it, including any tree data */
709 /* structures also allocated. */
711 /* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
712 /* may not be initialised, we can't use an ASSERT to enforce the locking */
713 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
714 /* ------------------------------------------------------------------------ */
715 void ip_pool_free(ipo
)
719 ip_pool_clearnodes(ipo
);
721 if (ipo
->ipo_next
!= NULL
)
722 ipo
->ipo_next
->ipo_pnext
= ipo
->ipo_pnext
;
723 *ipo
->ipo_pnext
= ipo
->ipo_next
;
724 rn_freehead(ipo
->ipo_head
);
727 ipoolstat
.ipls_pools
--;
731 /* ------------------------------------------------------------------------ */
732 /* Function: ip_pool_clearnodes */
734 /* Parameters: ipo(I) - pointer to pool structure */
735 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
737 /* Deletes all nodes stored in a pool structure. */
738 /* ------------------------------------------------------------------------ */
739 static void ip_pool_clearnodes(ipo
)
744 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
745 while ((n
= ipo
->ipo_list
) != NULL
) {
746 ipo
->ipo_head
->rnh_deladdr(&n
->ipn_addr
, &n
->ipn_mask
,
749 *n
->ipn_pnext
= n
->ipn_next
;
751 n
->ipn_next
->ipn_pnext
= n
->ipn_pnext
;
755 ipoolstat
.ipls_nodes
--;
757 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
759 ipo
->ipo_list
= NULL
;
763 /* ------------------------------------------------------------------------ */
764 /* Function: ip_pool_deref */
766 /* Parameters: ipo(I) - pointer to pool structure */
767 /* Locks: WRITE(ip_poolrw) */
769 /* Drop the number of known references to this pool structure by one and if */
770 /* we arrive at zero known references, free it. */
771 /* ------------------------------------------------------------------------ */
772 void ip_pool_deref(ipo
)
778 if (ipo
->ipo_ref
== 0)
781 else if ((ipo
->ipo_ref
== 1) && (ipo
->ipo_flags
& IPOOL_DELETE
))
782 ip_pool_destroy(ipo
->ipo_unit
, ipo
->ipo_name
);
786 /* ------------------------------------------------------------------------ */
787 /* Function: ip_pool_node_deref */
789 /* Parameters: ipn(I) - pointer to pool structure */
790 /* Locks: WRITE(ip_poolrw) */
792 /* Drop a reference to the pool node passed in and if we're the last, free */
793 /* it all up and adjust the stats accordingly. */
794 /* ------------------------------------------------------------------------ */
795 void ip_pool_node_deref(ipn
)
801 if (ipn
->ipn_ref
== 0) {
803 ipoolstat
.ipls_nodes
--;
808 /* ------------------------------------------------------------------------ */
809 /* Function: ip_pool_getnext */
811 /* Parameters: token(I) - pointer to pool structure */
812 /* ilp(IO) - pointer to pool iterating structure */
814 /* ------------------------------------------------------------------------ */
815 int ip_pool_getnext(token
, ilp
)
817 ipflookupiter_t
*ilp
;
819 ip_pool_node_t
*node
, zn
, *nextnode
;
820 ip_pool_t
*ipo
, zp
, *nextipo
;
829 READ_ENTER(&ip_poolrw
);
832 * Get "previous" entry from token. Find next entry to process,
833 * and add reference to it and update the token.
835 switch (ilp
->ili_otype
)
837 case IPFLOOKUPITER_LIST
:
838 ipo
= token
->ipt_data
;
840 nextipo
= ip_pool_list
[(int)ilp
->ili_unit
];
842 nextipo
= ipo
->ipo_next
;
845 if (nextipo
!= NULL
) {
846 ATOMIC_INC(nextipo
->ipo_ref
);
847 token
->ipt_data
= nextipo
;
849 bzero((char *)&zp
, sizeof(zp
));
851 token
->ipt_data
= NULL
;
855 case IPFLOOKUPITER_NODE
:
856 node
= token
->ipt_data
;
858 ipo
= ip_pool_exists(ilp
->ili_unit
, ilp
->ili_name
);
862 nextnode
= ipo
->ipo_list
;
866 nextnode
= node
->ipn_next
;
869 if (nextnode
!= NULL
) {
870 ATOMIC_INC(nextnode
->ipn_ref
);
871 token
->ipt_data
= nextnode
;
873 bzero((char *)&zn
, sizeof(zn
));
875 token
->ipt_data
= NULL
;
885 * Now that we have ref, it's save to give up lock.
887 RWLOCK_EXIT(&ip_poolrw
);
893 * Copy out the data and update the references and token as needed.
895 switch (ilp
->ili_otype
)
897 case IPFLOOKUPITER_LIST
:
898 err
= COPYOUT(nextipo
, ilp
->ili_data
, sizeof(*nextipo
));
901 if (token
->ipt_data
!= NULL
) {
903 WRITE_ENTER(&ip_poolrw
);
905 RWLOCK_EXIT(&ip_poolrw
);
907 if (nextipo
->ipo_next
== NULL
)
908 token
->ipt_data
= NULL
;
912 case IPFLOOKUPITER_NODE
:
913 err
= COPYOUT(nextnode
, ilp
->ili_data
, sizeof(*nextnode
));
916 if (token
->ipt_data
!= NULL
) {
918 WRITE_ENTER(&ip_poolrw
);
919 ip_pool_node_deref(node
);
920 RWLOCK_EXIT(&ip_poolrw
);
922 if (nextnode
->ipn_next
== NULL
)
923 token
->ipt_data
= NULL
;
932 /* ------------------------------------------------------------------------ */
933 /* Function: ip_pool_iterderef */
935 /* Parameters: ipn(I) - pointer to pool structure */
936 /* Locks: WRITE(ip_poolrw) */
938 /* ------------------------------------------------------------------------ */
939 void ip_pool_iterderef(otype
, unit
, data
)
948 if (unit
< 0 || unit
> IPL_LOGMAX
)
953 case IPFLOOKUPITER_LIST
:
954 WRITE_ENTER(&ip_poolrw
);
955 ip_pool_deref((ip_pool_t
*)data
);
956 RWLOCK_EXIT(&ip_poolrw
);
959 case IPFLOOKUPITER_NODE
:
960 WRITE_ENTER(&ip_poolrw
);
961 ip_pool_node_deref((ip_pool_node_t
*)data
);
962 RWLOCK_EXIT(&ip_poolrw
);
970 # if defined(_KERNEL) && (defined(BSD) && (BSD >= 198911) && \
971 !defined(__osf__) && !defined(__hpux) && !defined(__sgi))
973 rn_freenode(struct radix_node
*n
, void *p
)
975 struct radix_node_head
*rnh
= p
;
976 struct radix_node
*d
;
978 d
= rnh
->rnh_deladdr(n
->rn_key
, NULL
, rnh
);
980 FreeS(d
, max_keylen
+ 2 * sizeof (*d
));
988 struct radix_node_head
*rnh
;
991 RADIX_NODE_HEAD_LOCK(rnh
);
992 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ > 499002000)
993 rn_walktree(rnh
, rn_freenode
, rnh
);
995 (*rnh
->rnh_walktree
)(rnh
, rn_freenode
, rnh
);
998 rnh
->rnh_addaddr
= NULL
;
999 rnh
->rnh_deladdr
= NULL
;
1000 rnh
->rnh_matchaddr
= NULL
;
1001 rnh
->rnh_lookup
= NULL
;
1002 RADIX_NODE_HEAD_UNLOCK(rnh
);
1007 #endif /* IPFILTER_LOOKUP */