12393Syz155240 /*
22393Syz155240 * Copyright (C) 1993-2001, 2003 by Darren Reed.
32393Syz155240 *
42393Syz155240 * See the IPFILTER.LICENCE file for details on licencing.
52393Syz155240 *
6*12255SJohn.Ojemann@Oracle.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
72393Syz155240 */
82393Syz155240
92393Syz155240 #if defined(KERNEL) || defined(_KERNEL)
102393Syz155240 # undef KERNEL
112393Syz155240 # undef _KERNEL
122393Syz155240 # define KERNEL 1
132393Syz155240 # define _KERNEL 1
142393Syz155240 #endif
152393Syz155240 #if defined(__osf__)
162393Syz155240 # define _PROTO_NET_H_
172393Syz155240 #endif
182393Syz155240 #include <sys/errno.h>
192393Syz155240 #include <sys/types.h>
202393Syz155240 #include <sys/param.h>
212393Syz155240 #include <sys/file.h>
222393Syz155240 #if !defined(_KERNEL) && !defined(__KERNEL__)
232393Syz155240 # include <stdio.h>
242393Syz155240 # include <stdlib.h>
252393Syz155240 # include <string.h>
262393Syz155240 # define _KERNEL
272393Syz155240 # ifdef __OpenBSD__
282393Syz155240 struct file;
292393Syz155240 # endif
302393Syz155240 # include <sys/uio.h>
312393Syz155240 # undef _KERNEL
322393Syz155240 #else
332393Syz155240 # include <sys/systm.h>
342393Syz155240 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
352393Syz155240 # include <sys/proc.h>
362393Syz155240 # endif
372393Syz155240 #endif
382393Syz155240 #include <sys/time.h>
392393Syz155240 #if !defined(linux)
402393Syz155240 # include <sys/protosw.h>
412393Syz155240 #endif
422393Syz155240 #include <sys/socket.h>
432393Syz155240 #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
442393Syz155240 # include <sys/mbuf.h>
452393Syz155240 #endif
462393Syz155240 #if defined(__SVR4) || defined(__svr4__)
472393Syz155240 # include <sys/filio.h>
482393Syz155240 # include <sys/byteorder.h>
492393Syz155240 # ifdef _KERNEL
502393Syz155240 # include <sys/dditypes.h>
512393Syz155240 # endif
522393Syz155240 # include <sys/stream.h>
532393Syz155240 # include <sys/kmem.h>
542393Syz155240 #endif
552393Syz155240 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
562393Syz155240 # include <sys/malloc.h>
572393Syz155240 #endif
582393Syz155240
592393Syz155240 #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
602393Syz155240 defined(__hpux) || defined(__sgi))
612393Syz155240 # ifdef __osf__
622393Syz155240 # include <net/radix.h>
632393Syz155240 # endif
642393Syz155240 # include "radix_ipf_local.h"
652393Syz155240 # define _RADIX_H_
662393Syz155240 #endif
672393Syz155240 #include <net/if.h>
682393Syz155240 #include <netinet/in.h>
692393Syz155240
703448Sdh155122 #include "netinet/ipf_stack.h"
712393Syz155240 #include "netinet/ip_compat.h"
722393Syz155240 #include "netinet/ip_fil.h"
732393Syz155240 #include "netinet/ip_pool.h"
742393Syz155240
752393Syz155240 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
762393Syz155240 ((BSD >= 198911) && !defined(__osf__) && \
772393Syz155240 !defined(__hpux) && !defined(__sgi))
782393Syz155240 static int rn_freenode __P((struct radix_node *, void *));
792393Syz155240 #endif
802393Syz155240
812393Syz155240 /* END OF INCLUDES */
822393Syz155240
832393Syz155240 #if !defined(lint)
842393Syz155240 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
852393Syz155240 static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $";
862393Syz155240 #endif
872393Syz155240
882393Syz155240 #ifdef IPFILTER_LOOKUP
892393Syz155240
902393Syz155240 /*
912393Syz155240 * Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
922393Syz155240 * NOTE: Insertion *MUST* be from greatest range to least for it to work!
932393Syz155240 * These should be replaced, eventually, by something else - most notably a
942393Syz155240 * interval searching method. The important feature is to be able to find
952393Syz155240 * the best match.
962393Syz155240 *
972393Syz155240 * So why not use a radix tree for this? As the first line implies, it
982393Syz155240 * has been written to work with a _range_ of addresses. A range is not
992393Syz155240 * necessarily a match with any given netmask so what we end up dealing
1002393Syz155240 * with is an interval tree. Implementations of these are hard to find
1012393Syz155240 * and the one herein is far from bug free.
1022393Syz155240 *
1032393Syz155240 * Sigh, in the end I became convinced that the bugs the code contained did
1042393Syz155240 * not make it worthwhile not using radix trees. For now the radix tree from
1052393Syz155240 * 4.4 BSD is used, but this is not viewed as a long term solution.
1062393Syz155240 */
1072393Syz155240
1082393Syz155240 #ifdef TEST_POOL
1092393Syz155240 void treeprint __P((ip_pool_t *));
1102393Syz155240
1112393Syz155240 int
main(argc,argv)1122393Syz155240 main(argc, argv)
1132393Syz155240 int argc;
1142393Syz155240 char *argv[];
1152393Syz155240 {
1162393Syz155240 addrfamily_t a, b;
1172393Syz155240 iplookupop_t op;
1182393Syz155240 ip_pool_t *ipo;
1192393Syz155240 i6addr_t ip;
120*12255SJohn.Ojemann@Oracle.COM fr_info_t fin;
1212393Syz155240
1223448Sdh155122 RWLOCK_INIT(&ifs->ifs_ip_poolrw, "poolrw");
1233448Sdh155122 ip_pool_init(ifs);
1242393Syz155240
1252393Syz155240 bzero((char *)&a, sizeof(a));
1262393Syz155240 bzero((char *)&b, sizeof(b));
1272393Syz155240 bzero((char *)&ip, sizeof(ip));
1282393Syz155240 bzero((char *)&op, sizeof(op));
1292393Syz155240 strcpy(op.iplo_name, "0");
1302393Syz155240
1313448Sdh155122 if (ip_pool_create(&op, ifs) == 0)
1323448Sdh155122 ipo = ip_pool_find(0, "0", ifs);
1332393Syz155240
1342393Syz155240 a.adf_addr.in4.s_addr = 0x0a010203;
1352393Syz155240 b.adf_addr.in4.s_addr = 0xffffffff;
1363448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs);
1373448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs);
1382393Syz155240
1392393Syz155240 a.adf_addr.in4.s_addr = 0x0a000000;
1402393Syz155240 b.adf_addr.in4.s_addr = 0xff000000;
1413448Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs);
1423448Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs);
1432393Syz155240
1442393Syz155240 a.adf_addr.in4.s_addr = 0x0a010100;
1452393Syz155240 b.adf_addr.in4.s_addr = 0xffffff00;
1463448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs);
1473448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs);
1482393Syz155240
1492393Syz155240 a.adf_addr.in4.s_addr = 0x0a010200;
1502393Syz155240 b.adf_addr.in4.s_addr = 0xffffff00;
1513448Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs);
1523448Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs);
1532393Syz155240
1542393Syz155240 a.adf_addr.in4.s_addr = 0x0a010000;
1552393Syz155240 b.adf_addr.in4.s_addr = 0xffff0000;
1563448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs);
1573448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs);
1582393Syz155240
1592393Syz155240 a.adf_addr.in4.s_addr = 0x0a01020f;
1602393Syz155240 b.adf_addr.in4.s_addr = 0xffffffff;
1613448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs);
1623448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs);
1632393Syz155240 #ifdef DEBUG_POOL
1642393Syz155240 treeprint(ipo);
1652393Syz155240 #endif
166*12255SJohn.Ojemann@Oracle.COM fin.fin_plen = 20;
1672393Syz155240 ip.in4.s_addr = 0x0a00aabb;
1682393Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
169*12255SJohn.Ojemann@Oracle.COM ip_pool_search(ipo, 4, &ip, &fin, ifs));
1702393Syz155240
1712393Syz155240 ip.in4.s_addr = 0x0a000001;
1722393Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
173*12255SJohn.Ojemann@Oracle.COM ip_pool_search(ipo, 4, &ip, &fin, ifs));
1742393Syz155240
1752393Syz155240 ip.in4.s_addr = 0x0a000101;
1762393Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
177*12255SJohn.Ojemann@Oracle.COM ip_pool_search(ipo, 4, &ip, &fin, ifs));
1782393Syz155240
1792393Syz155240 ip.in4.s_addr = 0x0a010001;
1802393Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
181*12255SJohn.Ojemann@Oracle.COM ip_pool_search(ipo, 4, &ip, &fin, ifs));
1822393Syz155240
1832393Syz155240 ip.in4.s_addr = 0x0a010101;
1842393Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
185*12255SJohn.Ojemann@Oracle.COM ip_pool_search(ipo, 4, &ip, &fin, ifs));
1862393Syz155240
1872393Syz155240 ip.in4.s_addr = 0x0a010201;
1882393Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
189*12255SJohn.Ojemann@Oracle.COM ip_pool_search(ipo, 4, &ip, &fin, ifs));
1902393Syz155240
1912393Syz155240 ip.in4.s_addr = 0x0a010203;
1922393Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
193*12255SJohn.Ojemann@Oracle.COM ip_pool_search(ipo, 4, &ip, &fin, ifs));
1942393Syz155240
1952393Syz155240 ip.in4.s_addr = 0x0a01020f;
1962393Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
197*12255SJohn.Ojemann@Oracle.COM ip_pool_search(ipo, 4, &ip, &fin, ifs));
1982393Syz155240
1992393Syz155240 ip.in4.s_addr = 0x0b00aabb;
2002393Syz155240 printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
201*12255SJohn.Ojemann@Oracle.COM ip_pool_search(ipo, 4, &ip, &fin, ifs));
2022393Syz155240
2032393Syz155240 #ifdef DEBUG_POOL
2042393Syz155240 treeprint(ipo);
2052393Syz155240 #endif
2062393Syz155240
2073448Sdh155122 ip_pool_fini(ifs);
2082393Syz155240
2092393Syz155240 return 0;
2102393Syz155240 }
2112393Syz155240
2122393Syz155240
2132393Syz155240 void
treeprint(ipo)2142393Syz155240 treeprint(ipo)
2152393Syz155240 ip_pool_t *ipo;
2162393Syz155240 {
2172393Syz155240 ip_pool_node_t *c;
2182393Syz155240
2192393Syz155240 for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
2202393Syz155240 printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
2212393Syz155240 c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
2222393Syz155240 c->ipn_mask.adf_addr.in4.s_addr,
2232393Syz155240 c->ipn_info, c->ipn_hits);
2242393Syz155240 }
2252393Syz155240 #endif /* TEST_POOL */
2262393Syz155240
2272393Syz155240
2282393Syz155240 /* ------------------------------------------------------------------------ */
2292393Syz155240 /* Function: ip_pool_init */
2302393Syz155240 /* Returns: int - 0 = success, else error */
2312393Syz155240 /* */
2322393Syz155240 /* Initialise the routing table data structures where required. */
2332393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_init(ifs)2343448Sdh155122 int ip_pool_init(ifs)
2353448Sdh155122 ipf_stack_t *ifs;
2362393Syz155240 {
2372393Syz155240
2383448Sdh155122 bzero(&ifs->ifs_ipoolstat, sizeof (ip_pool_stat_t));
2392393Syz155240
2402535Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
2412393Syz155240 rn_init();
2422393Syz155240 #endif
2432393Syz155240 return 0;
2442393Syz155240 }
2452393Syz155240
2462393Syz155240
2472393Syz155240 /* ------------------------------------------------------------------------ */
2482393Syz155240 /* Function: ip_pool_fini */
2492393Syz155240 /* Returns: int - 0 = success, else error */
2502393Syz155240 /* Locks: WRITE(ipf_global) */
2512393Syz155240 /* */
2522393Syz155240 /* Clean up all the pool data structures allocated and call the cleanup */
2532393Syz155240 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
2542393Syz155240 /* used to delete the pools one by one to ensure they're properly freed up. */
2552393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_fini(ifs)2563448Sdh155122 void ip_pool_fini(ifs)
2573448Sdh155122 ipf_stack_t *ifs;
2582393Syz155240 {
2592393Syz155240 ip_pool_t *p, *q;
2602393Syz155240 iplookupop_t op;
2612393Syz155240 int i;
2622393Syz155240
2633448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0);
2642393Syz155240
2652393Syz155240 for (i = 0; i <= IPL_LOGMAX; i++) {
2663448Sdh155122 for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) {
2672393Syz155240 op.iplo_unit = i;
2682393Syz155240 (void)strncpy(op.iplo_name, p->ipo_name,
2692393Syz155240 sizeof(op.iplo_name));
2702393Syz155240 q = p->ipo_next;
2713448Sdh155122 (void) ip_pool_destroy(&op, ifs);
2722393Syz155240 }
2732393Syz155240 }
2742393Syz155240
2752535Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10))
2762393Syz155240 rn_fini();
2772393Syz155240 #endif
2782393Syz155240 }
2792393Syz155240
2802393Syz155240
2812393Syz155240 /* ------------------------------------------------------------------------ */
2822393Syz155240 /* Function: ip_pool_statistics */
2832393Syz155240 /* Returns: int - 0 = success, else error */
2842393Syz155240 /* Parameters: op(I) - pointer to lookup operation arguments */
2852393Syz155240 /* */
2862393Syz155240 /* Copy the current statistics out into user space, collecting pool list */
2872393Syz155240 /* pointers as appropriate for later use. */
2882393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_statistics(op,ifs)2893448Sdh155122 int ip_pool_statistics(op, ifs)
2902393Syz155240 iplookupop_t *op;
2913448Sdh155122 ipf_stack_t *ifs;
2922393Syz155240 {
2932393Syz155240 ip_pool_stat_t stats;
2942393Syz155240 int unit, i, err = 0;
2952393Syz155240
2963448Sdh155122 if (op->iplo_size != sizeof(ip_pool_stat_t))
2972393Syz155240 return EINVAL;
2982393Syz155240
2993448Sdh155122 bcopy((char *)&ifs->ifs_ipoolstat, (char *)&stats, sizeof(stats));
3002393Syz155240 unit = op->iplo_unit;
3012393Syz155240 if (unit == IPL_LOGALL) {
3022393Syz155240 for (i = 0; i < IPL_LOGSIZE; i++)
3033448Sdh155122 stats.ipls_list[i] = ifs->ifs_ip_pool_list[i];
3042393Syz155240 } else if (unit >= 0 && unit < IPL_LOGSIZE) {
3052393Syz155240 if (op->iplo_name[0] != '\0')
3062393Syz155240 stats.ipls_list[unit] = ip_pool_find(unit,
3073448Sdh155122 op->iplo_name, ifs);
3082393Syz155240 else
3093448Sdh155122 stats.ipls_list[unit] = ifs->ifs_ip_pool_list[unit];
3102393Syz155240 } else
3112393Syz155240 err = EINVAL;
3122393Syz155240 if (err == 0)
3132393Syz155240 err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
3142393Syz155240 return err;
3152393Syz155240 }
3162393Syz155240
3172393Syz155240
3182393Syz155240
3192393Syz155240 /* ------------------------------------------------------------------------ */
3202393Syz155240 /* Function: ip_pool_find */
3212393Syz155240 /* Returns: int - 0 = success, else error */
3222393Syz155240 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
3232393Syz155240 /* */
3242393Syz155240 /* Find a matching pool inside the collection of pools for a particular */
3252393Syz155240 /* device, indicated by the unit number. */
3262393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_find(unit,name,ifs)3273448Sdh155122 void *ip_pool_find(unit, name, ifs)
3282393Syz155240 int unit;
3292393Syz155240 char *name;
3303448Sdh155122 ipf_stack_t *ifs;
3312393Syz155240 {
3322393Syz155240 ip_pool_t *p;
3332393Syz155240
3343448Sdh155122 for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; p = p->ipo_next)
3352393Syz155240 if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
3362393Syz155240 break;
3372393Syz155240 return p;
3382393Syz155240 }
3392393Syz155240
3402393Syz155240
3412393Syz155240 /* ------------------------------------------------------------------------ */
3422393Syz155240 /* Function: ip_pool_findeq */
3432393Syz155240 /* Returns: int - 0 = success, else error */
3442393Syz155240 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
3452393Syz155240 /* addr(I) - pointer to address information to delete */
3462393Syz155240 /* mask(I) - */
3472393Syz155240 /* */
3482393Syz155240 /* Searches for an exact match of an entry in the pool. */
3492393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_findeq(ipo,addr,mask)3502393Syz155240 ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
3512393Syz155240 ip_pool_t *ipo;
3522393Syz155240 addrfamily_t *addr, *mask;
3532393Syz155240 {
3542393Syz155240 struct radix_node *n;
3552393Syz155240 SPL_INT(s);
3562393Syz155240
3572393Syz155240 SPL_NET(s);
3582393Syz155240 n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
3592393Syz155240 SPL_X(s);
3602393Syz155240 return (ip_pool_node_t *)n;
3612393Syz155240 }
3622393Syz155240
3632393Syz155240
3642393Syz155240 /* ------------------------------------------------------------------------ */
3652393Syz155240 /* Function: ip_pool_search */
3662393Syz155240 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
3672393Syz155240 /* Parameters: tptr(I) - pointer to the pool to search */
3682393Syz155240 /* version(I) - IP protocol version (4 or 6) */
3692393Syz155240 /* dptr(I) - pointer to address information */
370*12255SJohn.Ojemann@Oracle.COM /* fin - pointer to packet information */
371*12255SJohn.Ojemann@Oracle.COM /* ifs - ipf stack instance */
3722393Syz155240 /* */
3732393Syz155240 /* Search the pool for a given address and return a search result. */
3742393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_search(tptr,version,dptr,fin,ifs)375*12255SJohn.Ojemann@Oracle.COM int ip_pool_search(tptr, version, dptr, fin, ifs)
3762393Syz155240 void *tptr;
3772393Syz155240 int version;
3782393Syz155240 void *dptr;
379*12255SJohn.Ojemann@Oracle.COM fr_info_t *fin;
3803448Sdh155122 ipf_stack_t *ifs;
3812393Syz155240 {
3822393Syz155240 struct radix_node *rn;
3832393Syz155240 ip_pool_node_t *m;
3842393Syz155240 i6addr_t *addr;
3852393Syz155240 addrfamily_t v;
3862393Syz155240 ip_pool_t *ipo;
3872393Syz155240 int rv;
3882393Syz155240
3892393Syz155240 ipo = tptr;
3902393Syz155240 if (ipo == NULL)
3912393Syz155240 return -1;
3922393Syz155240
3932393Syz155240 rv = 1;
3942393Syz155240 m = NULL;
3952393Syz155240 addr = (i6addr_t *)dptr;
3962393Syz155240 bzero(&v, sizeof(v));
3972393Syz155240 v.adf_len = offsetof(addrfamily_t, adf_addr);
3982393Syz155240
3992393Syz155240 if (version == 4) {
4002393Syz155240 v.adf_len += sizeof(addr->in4);
4012393Syz155240 v.adf_addr.in4 = addr->in4;
4022393Syz155240 #ifdef USE_INET6
4032393Syz155240 } else if (version == 6) {
4042393Syz155240 v.adf_len += sizeof(addr->in6);
4052393Syz155240 v.adf_addr.in6 = addr->in6;
4062393Syz155240 #endif
4072393Syz155240 } else
4082393Syz155240 return -1;
4092393Syz155240
4103448Sdh155122 READ_ENTER(&ifs->ifs_ip_poolrw);
4112393Syz155240
4122393Syz155240 rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
4132393Syz155240
4142393Syz155240 if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
4152393Syz155240 m = (ip_pool_node_t *)rn;
4162393Syz155240 ipo->ipo_hits++;
4172393Syz155240 m->ipn_hits++;
418*12255SJohn.Ojemann@Oracle.COM m->ipn_bytes += fin->fin_plen;
4192393Syz155240 rv = m->ipn_info;
4202393Syz155240 }
4213448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
4222393Syz155240 return rv;
4232393Syz155240 }
4242393Syz155240
4252393Syz155240
4262393Syz155240 /* ------------------------------------------------------------------------ */
4272393Syz155240 /* Function: ip_pool_insert */
4282393Syz155240 /* Returns: int - 0 = success, else error */
4292393Syz155240 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
4302393Syz155240 /* addr(I) - IPv4/6 address being added as a node */
4312393Syz155240 /* mask(I) - IPv4/6 netmask to with the node being added */
4322393Syz155240 /* info(I) - extra information to store in this node. */
4332393Syz155240 /* Locks: WRITE(ip_poolrw) */
4342393Syz155240 /* */
4352393Syz155240 /* Add another node to the pool given by ipo. The three parameters passed */
4362393Syz155240 /* in (addr, mask, info) shold all be stored in the node. */
4372393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_insert(ipo,addr,mask,info,ifs)4383448Sdh155122 int ip_pool_insert(ipo, addr, mask, info, ifs)
4392393Syz155240 ip_pool_t *ipo;
4402393Syz155240 addrfamily_t *addr, *mask;
4412393Syz155240 int info;
4423448Sdh155122 ipf_stack_t *ifs;
4432393Syz155240 {
4442393Syz155240 struct radix_node *rn;
4452393Syz155240 ip_pool_node_t *x;
4462393Syz155240
4473448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
4482393Syz155240
4492393Syz155240 KMALLOC(x, ip_pool_node_t *);
4502393Syz155240 if (x == NULL) {
4512393Syz155240 return ENOMEM;
4522393Syz155240 }
4532393Syz155240
4542393Syz155240 bzero(x, sizeof(*x));
4552393Syz155240
4562393Syz155240 x->ipn_info = info;
4572393Syz155240 (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
4582393Syz155240
4592393Syz155240 bcopy(addr, &x->ipn_addr, sizeof(*addr));
4602393Syz155240 x->ipn_addr.adf_len = sizeof(x->ipn_addr);
4612393Syz155240 bcopy(mask, &x->ipn_mask, sizeof(*mask));
4622393Syz155240 x->ipn_mask.adf_len = sizeof(x->ipn_mask);
4632393Syz155240
4642393Syz155240 rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
4652393Syz155240 ipo->ipo_head, x->ipn_nodes);
4662393Syz155240 #ifdef DEBUG_POOL
4672393Syz155240 printf("Added %p at %p\n", x, rn);
4682393Syz155240 #endif
4692393Syz155240
4702393Syz155240 if (rn == NULL) {
4712393Syz155240 KFREE(x);
4722393Syz155240 return ENOMEM;
4732393Syz155240 }
4742393Syz155240
4753448Sdh155122 x->ipn_ref = 1;
4762393Syz155240 x->ipn_next = ipo->ipo_list;
4772393Syz155240 x->ipn_pnext = &ipo->ipo_list;
4782393Syz155240 if (ipo->ipo_list != NULL)
4792393Syz155240 ipo->ipo_list->ipn_pnext = &x->ipn_next;
4802393Syz155240 ipo->ipo_list = x;
4812393Syz155240
4823448Sdh155122 ifs->ifs_ipoolstat.ipls_nodes++;
4832393Syz155240
4842393Syz155240 return 0;
4852393Syz155240 }
4862393Syz155240
4872393Syz155240
4882393Syz155240 /* ------------------------------------------------------------------------ */
4892393Syz155240 /* Function: ip_pool_create */
4902393Syz155240 /* Returns: int - 0 = success, else error */
4912393Syz155240 /* Parameters: op(I) - pointer to iplookup struct with call details */
4922393Syz155240 /* Locks: WRITE(ip_poolrw) */
4932393Syz155240 /* */
4942393Syz155240 /* Creates a new group according to the paramters passed in via the */
4952393Syz155240 /* iplookupop structure. Does not check to see if the group already exists */
4962393Syz155240 /* when being inserted - assume this has already been done. If the pool is */
4972393Syz155240 /* marked as being anonymous, give it a new, unique, identifier. Call any */
4982393Syz155240 /* other functions required to initialise the structure. */
4992393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_create(op,ifs)5003448Sdh155122 int ip_pool_create(op, ifs)
5012393Syz155240 iplookupop_t *op;
5023448Sdh155122 ipf_stack_t *ifs;
5032393Syz155240 {
5042393Syz155240 char name[FR_GROUPLEN];
5052393Syz155240 int poolnum, unit;
5062393Syz155240 ip_pool_t *h;
5072393Syz155240
5083448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
5092393Syz155240
5102393Syz155240 KMALLOC(h, ip_pool_t *);
5112393Syz155240 if (h == NULL)
5122393Syz155240 return ENOMEM;
5132393Syz155240 bzero(h, sizeof(*h));
5142393Syz155240
5152393Syz155240 if (rn_inithead((void **)&h->ipo_head,
5162393Syz155240 offsetof(addrfamily_t, adf_addr) << 3) == 0) {
5172393Syz155240 KFREE(h);
5182393Syz155240 return ENOMEM;
5192393Syz155240 }
5202393Syz155240
5212393Syz155240 unit = op->iplo_unit;
5222393Syz155240
5232393Syz155240 if ((op->iplo_arg & IPOOL_ANON) != 0) {
5242393Syz155240 ip_pool_t *p;
5252393Syz155240
5262393Syz155240 poolnum = IPOOL_ANON;
5272393Syz155240
5282393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL)
5292393Syz155240 (void)SNPRINTF(name, sizeof(name), "%x", poolnum);
5302393Syz155240 #else
5312393Syz155240 (void)sprintf(name, "%x", poolnum);
5322393Syz155240 #endif
5332393Syz155240
5343448Sdh155122 for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; ) {
5352393Syz155240 if (strncmp(name, p->ipo_name,
5362393Syz155240 sizeof(p->ipo_name)) == 0) {
5372393Syz155240 poolnum++;
5382393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL)
5392393Syz155240 (void)SNPRINTF(name, sizeof(name), "%x", poolnum);
5402393Syz155240 #else
5412393Syz155240 (void)sprintf(name, "%x", poolnum);
5422393Syz155240 #endif
5433448Sdh155122 p = ifs->ifs_ip_pool_list[unit];
5442393Syz155240 } else
5452393Syz155240 p = p->ipo_next;
5462393Syz155240 }
5472393Syz155240
5482393Syz155240 (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
5492393Syz155240 } else {
5502393Syz155240 (void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
5512393Syz155240 }
5522393Syz155240
5532393Syz155240 h->ipo_ref = 1;
5542393Syz155240 h->ipo_list = NULL;
5552393Syz155240 h->ipo_unit = unit;
5563448Sdh155122 h->ipo_next = ifs->ifs_ip_pool_list[unit];
5573448Sdh155122 if (ifs->ifs_ip_pool_list[unit] != NULL)
5583448Sdh155122 ifs->ifs_ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
5593448Sdh155122 h->ipo_pnext = &ifs->ifs_ip_pool_list[unit];
5603448Sdh155122 ifs->ifs_ip_pool_list[unit] = h;
5612393Syz155240
5623448Sdh155122 ifs->ifs_ipoolstat.ipls_pools++;
5632393Syz155240
5642393Syz155240 return 0;
5652393Syz155240 }
5662393Syz155240
5672393Syz155240
5682393Syz155240 /* ------------------------------------------------------------------------ */
5692393Syz155240 /* Function: ip_pool_remove */
5702393Syz155240 /* Returns: int - 0 = success, else error */
5712393Syz155240 /* Parameters: ipo(I) - pointer to the pool to remove the node from. */
5722393Syz155240 /* ipe(I) - address being deleted as a node */
5732393Syz155240 /* Locks: WRITE(ip_poolrw) */
5742393Syz155240 /* */
5752393Syz155240 /* Add another node to the pool given by ipo. The three parameters passed */
5762393Syz155240 /* in (addr, mask, info) shold all be stored in the node. */
5772393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_remove(ipo,ipe,ifs)5783448Sdh155122 int ip_pool_remove(ipo, ipe, ifs)
5792393Syz155240 ip_pool_t *ipo;
5802393Syz155240 ip_pool_node_t *ipe;
5813448Sdh155122 ipf_stack_t *ifs;
5822393Syz155240 {
5832393Syz155240 ip_pool_node_t **ipp, *n;
5842393Syz155240
5853448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
5862393Syz155240
5872393Syz155240 for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) {
5882393Syz155240 if (ipe == n) {
5892393Syz155240 *n->ipn_pnext = n->ipn_next;
5902393Syz155240 if (n->ipn_next)
5912393Syz155240 n->ipn_next->ipn_pnext = n->ipn_pnext;
5922393Syz155240 break;
5932393Syz155240 }
5942393Syz155240 }
5952393Syz155240
5962393Syz155240 if (n == NULL)
5972393Syz155240 return ENOENT;
5982393Syz155240
5992393Syz155240 ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
6002393Syz155240 ipo->ipo_head);
6012393Syz155240 KFREE(n);
6022393Syz155240
6033448Sdh155122 ifs->ifs_ipoolstat.ipls_nodes--;
6042393Syz155240
6052393Syz155240 return 0;
6062393Syz155240 }
6072393Syz155240
6082393Syz155240
6092393Syz155240 /* ------------------------------------------------------------------------ */
6102393Syz155240 /* Function: ip_pool_destroy */
6112393Syz155240 /* Returns: int - 0 = success, else error */
6122393Syz155240 /* Parameters: op(I) - information about the pool to remove */
6132393Syz155240 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
6142393Syz155240 /* */
6152393Syz155240 /* Search for a pool using paramters passed in and if it's not otherwise */
6162393Syz155240 /* busy, free it. */
6172393Syz155240 /* */
6182393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6192393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking */
6202393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
6212393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_destroy(op,ifs)6223448Sdh155122 int ip_pool_destroy(op, ifs)
6232393Syz155240 iplookupop_t *op;
6243448Sdh155122 ipf_stack_t *ifs;
6252393Syz155240 {
6262393Syz155240 ip_pool_t *ipo;
6272393Syz155240
6283448Sdh155122 ipo = ip_pool_find(op->iplo_unit, op->iplo_name, ifs);
6292393Syz155240 if (ipo == NULL)
6302393Syz155240 return ESRCH;
6312393Syz155240
6322393Syz155240 if (ipo->ipo_ref != 1)
6332393Syz155240 return EBUSY;
6342393Syz155240
6353448Sdh155122 ip_pool_free(ipo, ifs);
6362393Syz155240 return 0;
6372393Syz155240 }
6382393Syz155240
6392393Syz155240
6402393Syz155240 /* ------------------------------------------------------------------------ */
6412393Syz155240 /* Function: ip_pool_flush */
6422393Syz155240 /* Returns: int - number of pools deleted */
6432393Syz155240 /* Parameters: fp(I) - which pool(s) to flush */
6442393Syz155240 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
6452393Syz155240 /* */
6462393Syz155240 /* Free all pools associated with the device that matches the unit number */
6472393Syz155240 /* passed in with operation. */
6482393Syz155240 /* */
6492393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6502393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking */
6512393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
6522393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_flush(fp,ifs)6533448Sdh155122 int ip_pool_flush(fp, ifs)
6542393Syz155240 iplookupflush_t *fp;
6553448Sdh155122 ipf_stack_t *ifs;
6562393Syz155240 {
6572393Syz155240 int i, num = 0, unit, err;
6582393Syz155240 ip_pool_t *p, *q;
6592393Syz155240 iplookupop_t op;
6602393Syz155240
6612393Syz155240 unit = fp->iplf_unit;
6622393Syz155240
6632393Syz155240 for (i = 0; i <= IPL_LOGMAX; i++) {
6642393Syz155240 if (unit != IPLT_ALL && i != unit)
6652393Syz155240 continue;
6663448Sdh155122 for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) {
6672393Syz155240 op.iplo_unit = i;
6682393Syz155240 (void)strncpy(op.iplo_name, p->ipo_name,
6692393Syz155240 sizeof(op.iplo_name));
6702393Syz155240 q = p->ipo_next;
6713448Sdh155122 err = ip_pool_destroy(&op, ifs);
6722393Syz155240 if (err == 0)
6732393Syz155240 num++;
6742393Syz155240 else
6752393Syz155240 break;
6762393Syz155240 }
6772393Syz155240 }
6782393Syz155240 return num;
6792393Syz155240 }
6802393Syz155240
6812393Syz155240
6822393Syz155240 /* ------------------------------------------------------------------------ */
6832393Syz155240 /* Function: ip_pool_free */
6842393Syz155240 /* Returns: void */
6852393Syz155240 /* Parameters: ipo(I) - pointer to pool structure */
6862393Syz155240 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
6872393Syz155240 /* */
6882393Syz155240 /* Deletes the pool strucutre passed in from the list of pools and deletes */
6892393Syz155240 /* all of the address information stored in it, including any tree data */
6902393Syz155240 /* structures also allocated. */
6912393Syz155240 /* */
6922393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
6932393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking */
6942393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
6952393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_free(ipo,ifs)6963448Sdh155122 void ip_pool_free(ipo, ifs)
6972393Syz155240 ip_pool_t *ipo;
6983448Sdh155122 ipf_stack_t *ifs;
6992393Syz155240 {
7002393Syz155240 ip_pool_node_t *n;
7012393Syz155240
7022393Syz155240 while ((n = ipo->ipo_list) != NULL) {
7032393Syz155240 ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
7042393Syz155240 ipo->ipo_head);
7052393Syz155240
7062393Syz155240 *n->ipn_pnext = n->ipn_next;
7072393Syz155240 if (n->ipn_next)
7082393Syz155240 n->ipn_next->ipn_pnext = n->ipn_pnext;
7092393Syz155240
7102393Syz155240 KFREE(n);
7112393Syz155240
7123448Sdh155122 ifs->ifs_ipoolstat.ipls_nodes--;
7132393Syz155240 }
7142393Syz155240
7152393Syz155240 ipo->ipo_list = NULL;
7162393Syz155240 if (ipo->ipo_next != NULL)
7172393Syz155240 ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
7182393Syz155240 *ipo->ipo_pnext = ipo->ipo_next;
7192393Syz155240 rn_freehead(ipo->ipo_head);
7202393Syz155240 KFREE(ipo);
7212393Syz155240
7223448Sdh155122 ifs->ifs_ipoolstat.ipls_pools--;
7232393Syz155240 }
7242393Syz155240
7252393Syz155240
7262393Syz155240 /* ------------------------------------------------------------------------ */
7272393Syz155240 /* Function: ip_pool_deref */
7282393Syz155240 /* Returns: void */
7292393Syz155240 /* Parameters: ipo(I) - pointer to pool structure */
7302393Syz155240 /* Locks: WRITE(ip_poolrw) */
7312393Syz155240 /* */
7322393Syz155240 /* Drop the number of known references to this pool structure by one and if */
7332393Syz155240 /* we arrive at zero known references, free it. */
7342393Syz155240 /* ------------------------------------------------------------------------ */
ip_pool_deref(ipo,ifs)7353448Sdh155122 void ip_pool_deref(ipo, ifs)
7362393Syz155240 ip_pool_t *ipo;
7373448Sdh155122 ipf_stack_t *ifs;
7382393Syz155240 {
7392393Syz155240
7403448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0);
7412393Syz155240
7422393Syz155240 ipo->ipo_ref--;
7432393Syz155240 if (ipo->ipo_ref == 0)
7443448Sdh155122 ip_pool_free(ipo, ifs);
7453448Sdh155122 }
7463448Sdh155122
7473448Sdh155122
7483448Sdh155122
ip_pool_node_deref(ipn,ifs)7493448Sdh155122 void ip_pool_node_deref(ipn, ifs)
7503448Sdh155122 ip_pool_node_t *ipn;
7513448Sdh155122 ipf_stack_t *ifs;
7523448Sdh155122 {
7533448Sdh155122
7543448Sdh155122 ipn->ipn_ref--;
7553448Sdh155122
7563448Sdh155122 if (ipn->ipn_ref == 0) {
7573448Sdh155122 KFREE(ipn);
7583448Sdh155122 ifs->ifs_ipoolstat.ipls_nodes--;
7593448Sdh155122 }
7603448Sdh155122 }
7613448Sdh155122
7623448Sdh155122
ip_pool_getnext(token,ilp,ifs)7633448Sdh155122 int ip_pool_getnext(token, ilp, ifs)
7643448Sdh155122 ipftoken_t *token;
7653448Sdh155122 ipflookupiter_t *ilp;
7663448Sdh155122 ipf_stack_t *ifs;
7673448Sdh155122 {
7683448Sdh155122 ip_pool_node_t *node, zn, *nextnode;
7693448Sdh155122 ip_pool_t *ipo, zp, *nextipo;
7703448Sdh155122 int err;
7713448Sdh155122
7723448Sdh155122 err = 0;
7733448Sdh155122 node = NULL;
7743448Sdh155122 nextnode = NULL;
7753448Sdh155122 ipo = NULL;
7763448Sdh155122 nextipo = NULL;
7773448Sdh155122
7783448Sdh155122 READ_ENTER(&ifs->ifs_ip_poolrw);
7793448Sdh155122
7806518Sjojemann /*
7816518Sjojemann * Get "previous" entry from the token and find the next entry.
7826518Sjojemann *
7836518Sjojemann * If we found an entry, add a reference to it and update the token.
7846518Sjojemann * Otherwise, zero out data to be returned and NULL out token.
7856518Sjojemann */
7863448Sdh155122 switch (ilp->ili_otype)
7873448Sdh155122 {
7883448Sdh155122 case IPFLOOKUPITER_LIST :
7893448Sdh155122 ipo = token->ipt_data;
7903448Sdh155122 if (ipo == NULL) {
7913448Sdh155122 nextipo = ifs->ifs_ip_pool_list[(int)ilp->ili_unit];
7923448Sdh155122 } else {
7933448Sdh155122 nextipo = ipo->ipo_next;
7943448Sdh155122 }
7953448Sdh155122 if (nextipo != NULL) {
7966518Sjojemann ATOMIC_INC(nextipo->ipo_ref);
7976518Sjojemann token->ipt_data = nextipo;
7983448Sdh155122 } else {
7993448Sdh155122 bzero((char *)&zp, sizeof(zp));
8003448Sdh155122 nextipo = &zp;
8016518Sjojemann token->ipt_data = NULL;
8023448Sdh155122 }
8033448Sdh155122 break;
8043448Sdh155122
8053448Sdh155122 case IPFLOOKUPITER_NODE :
8063448Sdh155122 node = token->ipt_data;
8073448Sdh155122 if (node == NULL) {
8083448Sdh155122 ipo = ip_pool_find(ilp->ili_unit, ilp->ili_name, ifs);
8093448Sdh155122 if (ipo == NULL)
8103448Sdh155122 err = ESRCH;
8113448Sdh155122 else {
8123448Sdh155122 nextnode = ipo->ipo_list;
8133448Sdh155122 ipo = NULL;
8143448Sdh155122 }
8153448Sdh155122 } else {
8163448Sdh155122 nextnode = node->ipn_next;
8173448Sdh155122 }
8183448Sdh155122 if (nextnode != NULL) {
8196518Sjojemann ATOMIC_INC(nextnode->ipn_ref);
8206518Sjojemann token->ipt_data = nextnode;
8213448Sdh155122 } else {
8223448Sdh155122 bzero((char *)&zn, sizeof(zn));
8233448Sdh155122 nextnode = &zn;
8246518Sjojemann token->ipt_data = NULL;
8253448Sdh155122 }
8263448Sdh155122 break;
8276518Sjojemann
8283448Sdh155122 default :
8293448Sdh155122 err = EINVAL;
8303448Sdh155122 break;
8313448Sdh155122 }
8323448Sdh155122
8336518Sjojemann /*
8346518Sjojemann * Now that we have ref, it's save to give up lock.
8356518Sjojemann */
8363448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
8373448Sdh155122
8383448Sdh155122 if (err != 0)
8393448Sdh155122 return err;
8403448Sdh155122
8416518Sjojemann /*
8426518Sjojemann * Copy out the data and update the references and token as needed.
8436518Sjojemann */
8443448Sdh155122 switch (ilp->ili_otype)
8453448Sdh155122 {
8463448Sdh155122 case IPFLOOKUPITER_LIST :
8473448Sdh155122 err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo));
8483448Sdh155122 if (err != 0)
8493448Sdh155122 err = EFAULT;
8506518Sjojemann if (token->ipt_data == NULL) {
8516518Sjojemann ipf_freetoken(token, ifs);
8526518Sjojemann } else {
8536518Sjojemann if (ipo != NULL) {
8546518Sjojemann WRITE_ENTER(&ifs->ifs_ip_poolrw);
8556518Sjojemann ip_pool_deref(ipo, ifs);
8566518Sjojemann RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
8576518Sjojemann }
8586518Sjojemann if (nextipo->ipo_next == NULL)
8596518Sjojemann ipf_freetoken(token, ifs);
8606518Sjojemann }
8613448Sdh155122 break;
8623448Sdh155122
8633448Sdh155122 case IPFLOOKUPITER_NODE :
8643448Sdh155122 err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
8653448Sdh155122 if (err != 0)
8663448Sdh155122 err = EFAULT;
8676518Sjojemann if (token->ipt_data == NULL) {
8686518Sjojemann ipf_freetoken(token, ifs);
8696518Sjojemann } else {
8706518Sjojemann if (node != NULL) {
8716518Sjojemann WRITE_ENTER(&ifs->ifs_ip_poolrw);
8726518Sjojemann ip_pool_node_deref(node, ifs);
8736518Sjojemann RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
8746518Sjojemann }
8756518Sjojemann if (nextnode->ipn_next == NULL)
8766518Sjojemann ipf_freetoken(token, ifs);
8776518Sjojemann }
8783448Sdh155122 break;
8793448Sdh155122 }
8803448Sdh155122
8813448Sdh155122 return err;
8823448Sdh155122 }
8833448Sdh155122
8843448Sdh155122
ip_pool_iterderef(otype,unit,data,ifs)8853448Sdh155122 void ip_pool_iterderef(otype, unit, data, ifs)
8863448Sdh155122 u_int otype;
8873448Sdh155122 int unit;
8883448Sdh155122 void *data;
8893448Sdh155122 ipf_stack_t *ifs;
8903448Sdh155122 {
8913448Sdh155122
8923448Sdh155122 if (data == NULL)
8933448Sdh155122 return;
8943448Sdh155122
8953448Sdh155122 if (unit < 0 || unit > IPL_LOGMAX)
8963448Sdh155122 return;
8973448Sdh155122
8983448Sdh155122 switch (otype)
8993448Sdh155122 {
9003448Sdh155122 case IPFLOOKUPITER_LIST :
9013448Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw);
9023448Sdh155122 ip_pool_deref((ip_pool_t *)data, ifs);
9033448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
9043448Sdh155122 break;
9053448Sdh155122
9063448Sdh155122 case IPFLOOKUPITER_NODE :
9073448Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw);
9083448Sdh155122 ip_pool_node_deref((ip_pool_node_t *)data, ifs);
9093448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
9103448Sdh155122 break;
9113448Sdh155122 default :
9123448Sdh155122 break;
9133448Sdh155122 }
9142393Syz155240 }
9152393Syz155240
9162393Syz155240
9172393Syz155240 # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
9182393Syz155240 !defined(__hpux) && !defined(__sgi))
9192393Syz155240 static int
rn_freenode(struct radix_node * n,void * p,ipf_stack_t * ifs)9203448Sdh155122 rn_freenode(struct radix_node *n, void *p, ipf_stack_t *ifs)
9212393Syz155240 {
9222393Syz155240 struct radix_node_head *rnh = p;
9232393Syz155240 struct radix_node *d;
9242393Syz155240
9252393Syz155240 d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
9262393Syz155240 if (d != NULL) {
9273448Sdh155122 FreeS(d, ifs->ifs_max_keylen + 2 * sizeof (*d));
9282393Syz155240 }
9292393Syz155240 return 0;
9302393Syz155240 }
9312393Syz155240
9322393Syz155240
9332393Syz155240 void
rn_freehead(rnh)9342393Syz155240 rn_freehead(rnh)
9352393Syz155240 struct radix_node_head *rnh;
9362393Syz155240 {
9372393Syz155240
9382393Syz155240 (*rnh->rnh_walktree)(rnh, rn_freenode, rnh);
9392393Syz155240
9402393Syz155240 rnh->rnh_addaddr = NULL;
9412393Syz155240 rnh->rnh_deladdr = NULL;
9422393Syz155240 rnh->rnh_matchaddr = NULL;
9432393Syz155240 rnh->rnh_lookup = NULL;
9442393Syz155240 rnh->rnh_walktree = NULL;
9452393Syz155240
9462393Syz155240 Free(rnh);
9472393Syz155240 }
9482393Syz155240 # endif
9492393Syz155240
9502393Syz155240 #endif /* IPFILTER_LOOKUP */
951