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>
23 #if !defined(_KERNEL) && !defined(__KERNEL__)
34 # include <sys/systm.h>
35 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
36 # include <sys/proc.h>
40 #if defined(_KERNEL) && !defined(SOLARIS2)
41 # include <sys/mbuf.h>
43 #if defined(__SVR4) || defined(__svr4__)
44 # include <sys/byteorder.h>
46 # include <sys/dditypes.h>
48 # include <sys/stream.h>
49 # include <sys/kmem.h>
51 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
52 # include <sys/malloc.h>
55 #if defined(SOLARIS2) && !defined(_KERNEL)
56 # include "radix_ipf.h"
58 #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
59 defined(__hpux) || defined(__sgi))
60 # include "radix_ipf_local.h"
63 #include <sys/socket.h>
65 #include <netinet/in.h>
67 #include "netinet/ip_compat.h"
68 #include "netinet/ip_fil.h"
69 #include "netinet/ip_pool.h"
71 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
72 ((BSD >= 198911) && !defined(__osf__) && \
73 !defined(__hpux) && !defined(__sgi))
74 static int rn_freenode
__P((struct radix_node
*, void *));
80 static const char sccsid
[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
81 static const char rcsid
[] = "@(#)Id: ip_pool.c,v 2.55.2.31 2009/07/18 19:05:39 darrenr Exp";
84 #ifdef IPFILTER_LOOKUP
86 # if !defined(RADIX_NODE_HEAD_LOCK) || !defined(RADIX_NODE_HEAD_UNLOCK) || \
88 # undef RADIX_NODE_HEAD_LOCK
89 # undef RADIX_NODE_HEAD_UNLOCK
90 # define RADIX_NODE_HEAD_LOCK(x) ;
91 # define RADIX_NODE_HEAD_UNLOCK(x) ;
94 static void ip_pool_clearnodes
__P((ip_pool_t
*));
95 static void *ip_pool_exists
__P((int, char *));
97 ip_pool_stat_t ipoolstat
;
98 ipfrwlock_t ip_poolrw
;
100 ip_pool_t
*ip_pool_list
[IPL_LOGSIZE
] = { NULL
, NULL
, NULL
, NULL
,
101 NULL
, NULL
, NULL
, NULL
};
105 void treeprint
__P((ip_pool_t
*));
117 RWLOCK_INIT(&ip_poolrw
, "poolrw");
120 bzero((char *)&a
, sizeof(a
));
121 bzero((char *)&b
, sizeof(b
));
122 bzero((char *)&ip
, sizeof(ip
));
123 bzero((char *)&op
, sizeof(op
));
124 strcpy(op
.iplo_name
, "0");
126 if (ip_pool_create(&op
) == 0)
127 ipo
= ip_pool_exists(0, "0");
129 a
.adf_addr
.in4
.s_addr
= 0x0a010203;
130 b
.adf_addr
.in4
.s_addr
= 0xffffffff;
131 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
132 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
134 a
.adf_addr
.in4
.s_addr
= 0x0a000000;
135 b
.adf_addr
.in4
.s_addr
= 0xff000000;
136 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 0);
137 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 0);
139 a
.adf_addr
.in4
.s_addr
= 0x0a010100;
140 b
.adf_addr
.in4
.s_addr
= 0xffffff00;
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
= 0x0a010200;
145 b
.adf_addr
.in4
.s_addr
= 0xffffff00;
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
= 0x0a010000;
150 b
.adf_addr
.in4
.s_addr
= 0xffff0000;
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
= 0x0a01020f;
155 b
.adf_addr
.in4
.s_addr
= 0xffffffff;
156 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
157 ip_pool_insert(ipo
, &a
.adf_addr
, &b
.adf_addr
, 1);
161 ip
.in4
.s_addr
= 0x0a00aabb;
162 printf("search(%#x) = %d (0)\n", ip
.in4
.s_addr
,
163 ip_pool_search(ipo
, 4, &ip
));
165 ip
.in4
.s_addr
= 0x0a000001;
166 printf("search(%#x) = %d (0)\n", ip
.in4
.s_addr
,
167 ip_pool_search(ipo
, 4, &ip
));
169 ip
.in4
.s_addr
= 0x0a000101;
170 printf("search(%#x) = %d (0)\n", ip
.in4
.s_addr
,
171 ip_pool_search(ipo
, 4, &ip
));
173 ip
.in4
.s_addr
= 0x0a010001;
174 printf("search(%#x) = %d (1)\n", ip
.in4
.s_addr
,
175 ip_pool_search(ipo
, 4, &ip
));
177 ip
.in4
.s_addr
= 0x0a010101;
178 printf("search(%#x) = %d (1)\n", ip
.in4
.s_addr
,
179 ip_pool_search(ipo
, 4, &ip
));
181 ip
.in4
.s_addr
= 0x0a010201;
182 printf("search(%#x) = %d (0)\n", ip
.in4
.s_addr
,
183 ip_pool_search(ipo
, 4, &ip
));
185 ip
.in4
.s_addr
= 0x0a010203;
186 printf("search(%#x) = %d (1)\n", ip
.in4
.s_addr
,
187 ip_pool_search(ipo
, 4, &ip
));
189 ip
.in4
.s_addr
= 0x0a01020f;
190 printf("search(%#x) = %d (1)\n", ip
.in4
.s_addr
,
191 ip_pool_search(ipo
, 4, &ip
));
193 ip
.in4
.s_addr
= 0x0b00aabb;
194 printf("search(%#x) = %d (-1)\n", ip
.in4
.s_addr
,
195 ip_pool_search(ipo
, 4, &ip
));
213 for (c
= ipo
->ipo_list
; c
!= NULL
; c
= c
->ipn_next
)
214 printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
215 c
, c
->ipn_name
, c
->ipn_addr
.adf_addr
.in4
.s_addr
,
216 c
->ipn_mask
.adf_addr
.in4
.s_addr
,
217 c
->ipn_info
, c
->ipn_hits
);
219 #endif /* TEST_POOL */
222 /* ------------------------------------------------------------------------ */
223 /* Function: ip_pool_init */
224 /* Returns: int - 0 = success, else error */
226 /* Initialise the routing table data structures where required. */
227 /* ------------------------------------------------------------------------ */
231 bzero((char *)&ipoolstat
, sizeof(ipoolstat
));
233 #if (!defined(_KERNEL) || !defined(BSD) || (BSD < 199306))
240 /* ------------------------------------------------------------------------ */
241 /* Function: ip_pool_fini */
242 /* Returns: int - 0 = success, else error */
243 /* Locks: WRITE(ipf_global) */
245 /* Clean up all the pool data structures allocated and call the cleanup */
246 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
247 /* used to delete the pools one by one to ensure they're properly freed up. */
248 /* ------------------------------------------------------------------------ */
254 for (i
= 0; i
<= IPL_LOGMAX
; i
++) {
255 for (q
= ip_pool_list
[i
]; (p
= q
) != NULL
; ) {
257 (void) ip_pool_destroy(i
, p
->ipo_name
);
261 #if (!defined(_KERNEL) || !defined(BSD) || (BSD < 199306))
267 /* ------------------------------------------------------------------------ */
268 /* Function: ip_pool_statistics */
269 /* Returns: int - 0 = success, else error */
270 /* Parameters: op(I) - pointer to lookup operation arguments */
272 /* Copy the current statistics out into user space, collecting pool list */
273 /* pointers as appropriate for later use. */
274 /* ------------------------------------------------------------------------ */
275 int ip_pool_statistics(op
)
278 ip_pool_stat_t stats
;
279 int unit
, i
, err
= 0;
281 if (op
->iplo_size
!= sizeof(ipoolstat
))
284 bcopy((char *)&ipoolstat
, (char *)&stats
, sizeof(stats
));
285 unit
= op
->iplo_unit
;
286 if (unit
== IPL_LOGALL
) {
287 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
288 stats
.ipls_list
[i
] = ip_pool_list
[i
];
289 } else if (unit
>= 0 && unit
< IPL_LOGSIZE
) {
290 if (op
->iplo_name
[0] != '\0')
291 stats
.ipls_list
[unit
] = ip_pool_exists(unit
,
294 stats
.ipls_list
[unit
] = ip_pool_list
[unit
];
298 err
= COPYOUT(&stats
, op
->iplo_struct
, sizeof(stats
));
303 /* ------------------------------------------------------------------------ */
304 /* Function: ip_pool_exists */
305 /* Returns: int - 0 = success, else error */
306 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
308 /* Find a matching pool inside the collection of pools for a particular */
309 /* device, indicated by the unit number. */
310 /* ------------------------------------------------------------------------ */
311 static void *ip_pool_exists(unit
, name
)
317 for (p
= ip_pool_list
[unit
]; p
!= NULL
; p
= p
->ipo_next
)
318 if (strncmp(p
->ipo_name
, name
, sizeof(p
->ipo_name
)) == 0)
324 /* ------------------------------------------------------------------------ */
325 /* Function: ip_pool_find */
326 /* Returns: int - 0 = success, else error */
327 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
329 /* Find a matching pool inside the collection of pools for a particular */
330 /* device, indicated by the unit number. If it is marked for deletion then */
331 /* pretend it does not exist. */
332 /* ------------------------------------------------------------------------ */
333 void *ip_pool_find(unit
, name
)
339 p
= ip_pool_exists(unit
, name
);
340 if ((p
!= NULL
) && (p
->ipo_flags
& IPOOL_DELETE
))
347 /* ------------------------------------------------------------------------ */
348 /* Function: ip_pool_findeq */
349 /* Returns: int - 0 = success, else error */
350 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
351 /* addr(I) - pointer to address information to delete */
354 /* Searches for an exact match of an entry in the pool. */
355 /* ------------------------------------------------------------------------ */
356 ip_pool_node_t
*ip_pool_findeq(ipo
, addr
, mask
)
358 addrfamily_t
*addr
, *mask
;
360 struct radix_node
*n
;
364 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
365 n
= ipo
->ipo_head
->rnh_lookup(addr
, mask
, ipo
->ipo_head
);
366 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
368 return (ip_pool_node_t
*)n
;
372 /* ------------------------------------------------------------------------ */
373 /* Function: ip_pool_search */
374 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
375 /* Parameters: tptr(I) - pointer to the pool to search */
376 /* version(I) - IP protocol version (4 or 6) */
377 /* dptr(I) - pointer to address information */
379 /* Search the pool for a given address and return a search result. */
380 /* ------------------------------------------------------------------------ */
381 int ip_pool_search(tptr
, ipversion
, dptr
)
386 struct radix_node
*rn
;
399 addr
= (i6addr_t
*)dptr
;
400 bzero(&v
, sizeof(v
));
401 v
.adf_len
= offsetof(addrfamily_t
, adf_addr
);
403 if (ipversion
== 4) {
404 v
.adf_len
+= sizeof(addr
->in4
);
405 v
.adf_addr
.in4
= addr
->in4
;
407 } else if (ipversion
== 6) {
408 v
.adf_len
+= sizeof(addr
->in6
);
409 v
.adf_addr
.in6
= addr
->in6
;
414 READ_ENTER(&ip_poolrw
);
416 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
417 rn
= ipo
->ipo_head
->rnh_matchaddr(&v
, ipo
->ipo_head
);
418 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
420 if ((rn
!= NULL
) && ((rn
->rn_flags
& RNF_ROOT
) == 0)) {
421 m
= (ip_pool_node_t
*)rn
;
426 RWLOCK_EXIT(&ip_poolrw
);
431 /* ------------------------------------------------------------------------ */
432 /* Function: ip_pool_insert */
433 /* Returns: int - 0 = success, else error */
434 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
435 /* addr(I) - address being added as a node */
436 /* mask(I) - netmask to with the node being added */
437 /* info(I) - extra information to store in this node. */
438 /* Locks: WRITE(ip_poolrw) */
440 /* Add another node to the pool given by ipo. The three parameters passed */
441 /* in (addr, mask, info) shold all be stored in the node. */
442 /* ------------------------------------------------------------------------ */
443 int ip_pool_insert(ipo
, addr
, mask
, info
)
445 i6addr_t
*addr
, *mask
;
448 struct radix_node
*rn
;
451 KMALLOC(x
, ip_pool_node_t
*);
456 bzero(x
, sizeof(*x
));
459 (void)strncpy(x
->ipn_name
, ipo
->ipo_name
, sizeof(x
->ipn_name
));
461 bcopy(addr
, &x
->ipn_addr
.adf_addr
, sizeof(*addr
));
462 x
->ipn_addr
.adf_len
= sizeof(x
->ipn_addr
);
463 bcopy(mask
, &x
->ipn_mask
.adf_addr
, sizeof(*mask
));
464 x
->ipn_mask
.adf_len
= sizeof(x
->ipn_mask
);
466 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
467 rn
= ipo
->ipo_head
->rnh_addaddr(&x
->ipn_addr
, &x
->ipn_mask
,
468 ipo
->ipo_head
, x
->ipn_nodes
);
469 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
471 printf("Added %p at %p\n", x
, rn
);
480 x
->ipn_next
= ipo
->ipo_list
;
481 x
->ipn_pnext
= &ipo
->ipo_list
;
482 if (ipo
->ipo_list
!= NULL
)
483 ipo
->ipo_list
->ipn_pnext
= &x
->ipn_next
;
486 ipoolstat
.ipls_nodes
++;
492 /* ------------------------------------------------------------------------ */
493 /* Function: ip_pool_create */
494 /* Returns: int - 0 = success, else error */
495 /* Parameters: op(I) - pointer to iplookup struct with call details */
496 /* Locks: WRITE(ip_poolrw) */
498 /* Creates a new group according to the paramters passed in via the */
499 /* iplookupop structure. Does not check to see if the group already exists */
500 /* when being inserted - assume this has already been done. If the pool is */
501 /* marked as being anonymous, give it a new, unique, identifier. Call any */
502 /* other functions required to initialise the structure. */
504 /* If the structure is flagged for deletion then reset the flag and return, */
505 /* as this likely means we've tried to free a pool that is in use (flush) */
506 /* and now want to repopulate it with "new" data. */
507 /* ------------------------------------------------------------------------ */
508 int ip_pool_create(op
)
511 char name
[FR_GROUPLEN
];
515 unit
= op
->iplo_unit
;
517 if ((op
->iplo_arg
& LOOKUP_ANON
) == 0) {
518 h
= ip_pool_exists(unit
, op
->iplo_name
);
520 if ((h
->ipo_flags
& IPOOL_DELETE
) == 0)
522 h
->ipo_flags
&= ~IPOOL_DELETE
;
527 KMALLOC(h
, ip_pool_t
*);
530 bzero(h
, sizeof(*h
));
532 if (rn_inithead((void **)&h
->ipo_head
,
533 offsetof(addrfamily_t
, adf_addr
) << 3) == 0) {
538 if ((op
->iplo_arg
& LOOKUP_ANON
) != 0) {
541 h
->ipo_flags
|= IPOOL_ANON
;
542 poolnum
= LOOKUP_ANON
;
544 #if defined(SNPRINTF) && defined(_KERNEL)
545 SNPRINTF(name
, sizeof(name
), "%x", poolnum
);
547 (void)sprintf(name
, "%x", poolnum
);
550 for (p
= ip_pool_list
[unit
]; p
!= NULL
; ) {
551 if (strncmp(name
, p
->ipo_name
,
552 sizeof(p
->ipo_name
)) == 0) {
554 #if defined(SNPRINTF) && defined(_KERNEL)
555 SNPRINTF(name
, sizeof(name
), "%x", poolnum
);
557 (void)sprintf(name
, "%x", poolnum
);
559 p
= ip_pool_list
[unit
];
564 (void)strncpy(h
->ipo_name
, name
, sizeof(h
->ipo_name
));
565 (void)strncpy(op
->iplo_name
, name
, sizeof(op
->iplo_name
));
567 (void)strncpy(h
->ipo_name
, op
->iplo_name
, sizeof(h
->ipo_name
));
573 h
->ipo_next
= ip_pool_list
[unit
];
574 if (ip_pool_list
[unit
] != NULL
)
575 ip_pool_list
[unit
]->ipo_pnext
= &h
->ipo_next
;
576 h
->ipo_pnext
= &ip_pool_list
[unit
];
577 ip_pool_list
[unit
] = h
;
579 ipoolstat
.ipls_pools
++;
585 /* ------------------------------------------------------------------------ */
586 /* Function: ip_pool_remove */
587 /* Returns: int - 0 = success, else error */
588 /* Parameters: ipo(I) - pointer to the pool to remove the node from. */
589 /* ipe(I) - address being deleted as a node */
590 /* Locks: WRITE(ip_poolrw) */
592 /* Remove a node from the pool given by ipo. */
593 /* ------------------------------------------------------------------------ */
594 int ip_pool_remove(ipo
, ipe
)
599 if (ipe
->ipn_pnext
!= NULL
)
600 *ipe
->ipn_pnext
= ipe
->ipn_next
;
601 if (ipe
->ipn_next
!= NULL
)
602 ipe
->ipn_next
->ipn_pnext
= ipe
->ipn_pnext
;
604 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
605 ipo
->ipo_head
->rnh_deladdr(&ipe
->ipn_addr
, &ipe
->ipn_mask
,
607 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
609 ip_pool_node_deref(ipe
);
615 /* ------------------------------------------------------------------------ */
616 /* Function: ip_pool_destroy */
617 /* Returns: int - 0 = success, else error */
618 /* Parameters: op(I) - information about the pool to remove */
619 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
621 /* Search for a pool using paramters passed in and if it's not otherwise */
622 /* busy, free it. If it is busy, clear all of its nodes, mark it for being */
623 /* deleted and return an error saying it is busy. */
625 /* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
626 /* may not be initialised, we can't use an ASSERT to enforce the locking */
627 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
628 /* ------------------------------------------------------------------------ */
629 int ip_pool_destroy(unit
, name
)
635 ipo
= ip_pool_exists(unit
, name
);
639 if (ipo
->ipo_ref
!= 1) {
640 ip_pool_clearnodes(ipo
);
641 ipo
->ipo_flags
|= IPOOL_DELETE
;
650 /* ------------------------------------------------------------------------ */
651 /* Function: ip_pool_flush */
652 /* Returns: int - number of pools deleted */
653 /* Parameters: fp(I) - which pool(s) to flush */
654 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
656 /* Free all pools associated with the device that matches the unit number */
657 /* passed in with operation. */
659 /* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
660 /* may not be initialised, we can't use an ASSERT to enforce the locking */
661 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
662 /* ------------------------------------------------------------------------ */
663 int ip_pool_flush(fp
)
666 int i
, num
= 0, unit
, err
;
670 unit
= fp
->iplf_unit
;
672 for (i
= 0; i
<= IPL_LOGMAX
; i
++) {
673 if (unit
!= IPLT_ALL
&& i
!= unit
)
675 for (q
= ip_pool_list
[i
]; (p
= q
) != NULL
; ) {
677 (void)strncpy(op
.iplo_name
, p
->ipo_name
,
678 sizeof(op
.iplo_name
));
680 err
= ip_pool_destroy(op
.iplo_unit
, op
.iplo_name
);
691 /* ------------------------------------------------------------------------ */
692 /* Function: ip_pool_free */
694 /* Parameters: ipo(I) - pointer to pool structure */
695 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
697 /* Deletes the pool strucutre passed in from the list of pools and deletes */
698 /* all of the address information stored in it, including any tree data */
699 /* structures also allocated. */
701 /* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
702 /* may not be initialised, we can't use an ASSERT to enforce the locking */
703 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
704 /* ------------------------------------------------------------------------ */
705 void ip_pool_free(ipo
)
709 ip_pool_clearnodes(ipo
);
711 if (ipo
->ipo_next
!= NULL
)
712 ipo
->ipo_next
->ipo_pnext
= ipo
->ipo_pnext
;
713 *ipo
->ipo_pnext
= ipo
->ipo_next
;
714 rn_freehead(ipo
->ipo_head
);
717 ipoolstat
.ipls_pools
--;
721 /* ------------------------------------------------------------------------ */
722 /* Function: ip_pool_clearnodes */
724 /* Parameters: ipo(I) - pointer to pool structure */
725 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
727 /* Deletes all nodes stored in a pool structure. */
728 /* ------------------------------------------------------------------------ */
729 static void ip_pool_clearnodes(ipo
)
734 RADIX_NODE_HEAD_LOCK(ipo
->ipo_head
);
735 while ((n
= ipo
->ipo_list
) != NULL
) {
736 ipo
->ipo_head
->rnh_deladdr(&n
->ipn_addr
, &n
->ipn_mask
,
739 *n
->ipn_pnext
= n
->ipn_next
;
741 n
->ipn_next
->ipn_pnext
= n
->ipn_pnext
;
745 ipoolstat
.ipls_nodes
--;
747 RADIX_NODE_HEAD_UNLOCK(ipo
->ipo_head
);
749 ipo
->ipo_list
= NULL
;
753 /* ------------------------------------------------------------------------ */
754 /* Function: ip_pool_deref */
756 /* Parameters: ipo(I) - pointer to pool structure */
757 /* Locks: WRITE(ip_poolrw) */
759 /* Drop the number of known references to this pool structure by one and if */
760 /* we arrive at zero known references, free it. */
761 /* ------------------------------------------------------------------------ */
762 void ip_pool_deref(ipo
)
768 if (ipo
->ipo_ref
== 0)
771 else if ((ipo
->ipo_ref
== 1) && (ipo
->ipo_flags
& IPOOL_DELETE
))
772 ip_pool_destroy(ipo
->ipo_unit
, ipo
->ipo_name
);
776 /* ------------------------------------------------------------------------ */
777 /* Function: ip_pool_node_deref */
779 /* Parameters: ipn(I) - pointer to pool structure */
780 /* Locks: WRITE(ip_poolrw) */
782 /* Drop a reference to the pool node passed in and if we're the last, free */
783 /* it all up and adjust the stats accordingly. */
784 /* ------------------------------------------------------------------------ */
785 void ip_pool_node_deref(ipn
)
791 if (ipn
->ipn_ref
== 0) {
793 ipoolstat
.ipls_nodes
--;
798 /* ------------------------------------------------------------------------ */
799 /* Function: ip_pool_getnext */
801 /* Parameters: token(I) - pointer to pool structure */
802 /* ilp(IO) - pointer to pool iterating structure */
804 /* ------------------------------------------------------------------------ */
805 int ip_pool_getnext(token
, ilp
)
807 ipflookupiter_t
*ilp
;
809 ip_pool_node_t
*node
, zn
, *nextnode
;
810 ip_pool_t
*ipo
, zp
, *nextipo
;
819 READ_ENTER(&ip_poolrw
);
822 * Get "previous" entry from token. Find next entry to process,
823 * and add reference to it and update the token.
825 switch (ilp
->ili_otype
)
827 case IPFLOOKUPITER_LIST
:
828 ipo
= token
->ipt_data
;
830 nextipo
= ip_pool_list
[(int)ilp
->ili_unit
];
832 nextipo
= ipo
->ipo_next
;
835 if (nextipo
!= NULL
) {
836 ATOMIC_INC(nextipo
->ipo_ref
);
837 token
->ipt_data
= nextipo
;
839 bzero((char *)&zp
, sizeof(zp
));
841 token
->ipt_data
= NULL
;
845 case IPFLOOKUPITER_NODE
:
846 node
= token
->ipt_data
;
848 ipo
= ip_pool_exists(ilp
->ili_unit
, ilp
->ili_name
);
852 nextnode
= ipo
->ipo_list
;
856 nextnode
= node
->ipn_next
;
859 if (nextnode
!= NULL
) {
860 ATOMIC_INC(nextnode
->ipn_ref
);
861 token
->ipt_data
= nextnode
;
863 bzero((char *)&zn
, sizeof(zn
));
865 token
->ipt_data
= NULL
;
875 * Now that we have ref, it's save to give up lock.
877 RWLOCK_EXIT(&ip_poolrw
);
883 * Copy out the data and update the references and token as needed.
885 switch (ilp
->ili_otype
)
887 case IPFLOOKUPITER_LIST
:
888 err
= COPYOUT(nextipo
, ilp
->ili_data
, sizeof(*nextipo
));
891 if (token
->ipt_data
!= NULL
) {
893 WRITE_ENTER(&ip_poolrw
);
895 RWLOCK_EXIT(&ip_poolrw
);
897 if (nextipo
->ipo_next
== NULL
)
898 token
->ipt_data
= NULL
;
902 case IPFLOOKUPITER_NODE
:
903 err
= COPYOUT(nextnode
, ilp
->ili_data
, sizeof(*nextnode
));
906 if (token
->ipt_data
!= NULL
) {
908 WRITE_ENTER(&ip_poolrw
);
909 ip_pool_node_deref(node
);
910 RWLOCK_EXIT(&ip_poolrw
);
912 if (nextnode
->ipn_next
== NULL
)
913 token
->ipt_data
= NULL
;
922 /* ------------------------------------------------------------------------ */
923 /* Function: ip_pool_iterderef */
925 /* Parameters: ipn(I) - pointer to pool structure */
926 /* Locks: WRITE(ip_poolrw) */
928 /* ------------------------------------------------------------------------ */
929 void ip_pool_iterderef(otype
, unit
, data
)
938 if (unit
< 0 || unit
> IPL_LOGMAX
)
943 case IPFLOOKUPITER_LIST
:
944 WRITE_ENTER(&ip_poolrw
);
945 ip_pool_deref((ip_pool_t
*)data
);
946 RWLOCK_EXIT(&ip_poolrw
);
949 case IPFLOOKUPITER_NODE
:
950 WRITE_ENTER(&ip_poolrw
);
951 ip_pool_node_deref((ip_pool_node_t
*)data
);
952 RWLOCK_EXIT(&ip_poolrw
);
960 # if defined(_KERNEL) && (defined(BSD) && (BSD >= 198911) && \
961 !defined(__osf__) && !defined(__hpux) && !defined(__sgi))
963 rn_freenode(struct radix_node
*n
, void *p
)
965 struct radix_node_head
*rnh
= p
;
966 struct radix_node
*d
;
968 d
= rnh
->rnh_deladdr(n
->rn_key
, NULL
, rnh
);
970 FreeS(d
, max_keylen
+ 2 * sizeof (*d
));
978 struct radix_node_head
*rnh
;
981 RADIX_NODE_HEAD_LOCK(rnh
);
982 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ > 499002000)
983 rn_walktree(rnh
, rn_freenode
, rnh
);
985 (*rnh
->rnh_walktree
)(rnh
, rn_freenode
, rnh
);
988 rnh
->rnh_addaddr
= NULL
;
989 rnh
->rnh_deladdr
= NULL
;
990 rnh
->rnh_matchaddr
= NULL
;
991 rnh
->rnh_lookup
= NULL
;
992 RADIX_NODE_HEAD_UNLOCK(rnh
);
997 #endif /* IPFILTER_LOOKUP */