12393Syz155240 /* 22393Syz155240 * Copyright (C) 1993-2001, 2003 by Darren Reed. 32393Syz155240 * 42393Syz155240 * See the IPFILTER.LICENCE file for details on licencing. 52393Syz155240 * 6*3448Sdh155122 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 72393Syz155240 * Use is subject to license terms. 82393Syz155240 */ 92393Syz155240 102393Syz155240 #pragma ident "%Z%%M% %I% %E% SMI" 112393Syz155240 122393Syz155240 #if defined(KERNEL) || defined(_KERNEL) 132393Syz155240 # undef KERNEL 142393Syz155240 # undef _KERNEL 152393Syz155240 # define KERNEL 1 162393Syz155240 # define _KERNEL 1 172393Syz155240 #endif 182393Syz155240 #if defined(__osf__) 192393Syz155240 # define _PROTO_NET_H_ 202393Syz155240 #endif 212393Syz155240 #include <sys/errno.h> 222393Syz155240 #include <sys/types.h> 232393Syz155240 #include <sys/param.h> 242393Syz155240 #include <sys/file.h> 252393Syz155240 #if !defined(_KERNEL) && !defined(__KERNEL__) 262393Syz155240 # include <stdio.h> 272393Syz155240 # include <stdlib.h> 282393Syz155240 # include <string.h> 292393Syz155240 # define _KERNEL 302393Syz155240 # ifdef __OpenBSD__ 312393Syz155240 struct file; 322393Syz155240 # endif 332393Syz155240 # include <sys/uio.h> 342393Syz155240 # undef _KERNEL 352393Syz155240 #else 362393Syz155240 # include <sys/systm.h> 372393Syz155240 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) 382393Syz155240 # include <sys/proc.h> 392393Syz155240 # endif 402393Syz155240 #endif 412393Syz155240 #include <sys/time.h> 422393Syz155240 #if !defined(linux) 432393Syz155240 # include <sys/protosw.h> 442393Syz155240 #endif 452393Syz155240 #include <sys/socket.h> 462393Syz155240 #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__)) 472393Syz155240 # include <sys/mbuf.h> 482393Syz155240 #endif 492393Syz155240 #if defined(__SVR4) || defined(__svr4__) 502393Syz155240 # include <sys/filio.h> 512393Syz155240 # include <sys/byteorder.h> 522393Syz155240 # ifdef _KERNEL 532393Syz155240 # include <sys/dditypes.h> 542393Syz155240 # endif 552393Syz155240 # include <sys/stream.h> 562393Syz155240 # include <sys/kmem.h> 572393Syz155240 #endif 582393Syz155240 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 592393Syz155240 # include <sys/malloc.h> 602393Syz155240 #endif 612393Syz155240 622393Syz155240 #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \ 632393Syz155240 defined(__hpux) || defined(__sgi)) 642393Syz155240 # ifdef __osf__ 652393Syz155240 # include <net/radix.h> 662393Syz155240 # endif 672393Syz155240 # include "radix_ipf_local.h" 682393Syz155240 # define _RADIX_H_ 692393Syz155240 #endif 702393Syz155240 #include <net/if.h> 712393Syz155240 #include <netinet/in.h> 722393Syz155240 73*3448Sdh155122 #include "netinet/ipf_stack.h" 742393Syz155240 #include "netinet/ip_compat.h" 752393Syz155240 #include "netinet/ip_fil.h" 762393Syz155240 #include "netinet/ip_pool.h" 772393Syz155240 782393Syz155240 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \ 792393Syz155240 ((BSD >= 198911) && !defined(__osf__) && \ 802393Syz155240 !defined(__hpux) && !defined(__sgi)) 812393Syz155240 static int rn_freenode __P((struct radix_node *, void *)); 822393Syz155240 #endif 832393Syz155240 842393Syz155240 /* END OF INCLUDES */ 852393Syz155240 862393Syz155240 #if !defined(lint) 872393Syz155240 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 882393Syz155240 static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $"; 892393Syz155240 #endif 902393Syz155240 912393Syz155240 #ifdef IPFILTER_LOOKUP 922393Syz155240 932393Syz155240 /* 942393Syz155240 * Binary tree routines from Sedgewick and enhanced to do ranges of addresses. 952393Syz155240 * NOTE: Insertion *MUST* be from greatest range to least for it to work! 962393Syz155240 * These should be replaced, eventually, by something else - most notably a 972393Syz155240 * interval searching method. The important feature is to be able to find 982393Syz155240 * the best match. 992393Syz155240 * 1002393Syz155240 * So why not use a radix tree for this? As the first line implies, it 1012393Syz155240 * has been written to work with a _range_ of addresses. A range is not 1022393Syz155240 * necessarily a match with any given netmask so what we end up dealing 1032393Syz155240 * with is an interval tree. Implementations of these are hard to find 1042393Syz155240 * and the one herein is far from bug free. 1052393Syz155240 * 1062393Syz155240 * Sigh, in the end I became convinced that the bugs the code contained did 1072393Syz155240 * not make it worthwhile not using radix trees. For now the radix tree from 1082393Syz155240 * 4.4 BSD is used, but this is not viewed as a long term solution. 1092393Syz155240 */ 1102393Syz155240 1112393Syz155240 #ifdef TEST_POOL 1122393Syz155240 void treeprint __P((ip_pool_t *)); 1132393Syz155240 1142393Syz155240 int 1152393Syz155240 main(argc, argv) 1162393Syz155240 int argc; 1172393Syz155240 char *argv[]; 1182393Syz155240 { 1192393Syz155240 addrfamily_t a, b; 1202393Syz155240 iplookupop_t op; 1212393Syz155240 ip_pool_t *ipo; 1222393Syz155240 i6addr_t ip; 1232393Syz155240 124*3448Sdh155122 RWLOCK_INIT(&ifs->ifs_ip_poolrw, "poolrw"); 125*3448Sdh155122 ip_pool_init(ifs); 1262393Syz155240 1272393Syz155240 bzero((char *)&a, sizeof(a)); 1282393Syz155240 bzero((char *)&b, sizeof(b)); 1292393Syz155240 bzero((char *)&ip, sizeof(ip)); 1302393Syz155240 bzero((char *)&op, sizeof(op)); 1312393Syz155240 strcpy(op.iplo_name, "0"); 1322393Syz155240 133*3448Sdh155122 if (ip_pool_create(&op, ifs) == 0) 134*3448Sdh155122 ipo = ip_pool_find(0, "0", ifs); 1352393Syz155240 1362393Syz155240 a.adf_addr.in4.s_addr = 0x0a010203; 1372393Syz155240 b.adf_addr.in4.s_addr = 0xffffffff; 138*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 139*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 1402393Syz155240 1412393Syz155240 a.adf_addr.in4.s_addr = 0x0a000000; 1422393Syz155240 b.adf_addr.in4.s_addr = 0xff000000; 143*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs); 144*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs); 1452393Syz155240 1462393Syz155240 a.adf_addr.in4.s_addr = 0x0a010100; 1472393Syz155240 b.adf_addr.in4.s_addr = 0xffffff00; 148*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 149*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 1502393Syz155240 1512393Syz155240 a.adf_addr.in4.s_addr = 0x0a010200; 1522393Syz155240 b.adf_addr.in4.s_addr = 0xffffff00; 153*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs); 154*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs); 1552393Syz155240 1562393Syz155240 a.adf_addr.in4.s_addr = 0x0a010000; 1572393Syz155240 b.adf_addr.in4.s_addr = 0xffff0000; 158*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 159*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 1602393Syz155240 1612393Syz155240 a.adf_addr.in4.s_addr = 0x0a01020f; 1622393Syz155240 b.adf_addr.in4.s_addr = 0xffffffff; 163*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 164*3448Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 1652393Syz155240 #ifdef DEBUG_POOL 1662393Syz155240 treeprint(ipo); 1672393Syz155240 #endif 1682393Syz155240 ip.in4.s_addr = 0x0a00aabb; 1692393Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 170*3448Sdh155122 ip_pool_search(ipo, 4, &ip, ifs)); 1712393Syz155240 1722393Syz155240 ip.in4.s_addr = 0x0a000001; 1732393Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 174*3448Sdh155122 ip_pool_search(ipo, 4, &ip, ifs)); 1752393Syz155240 1762393Syz155240 ip.in4.s_addr = 0x0a000101; 1772393Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 178*3448Sdh155122 ip_pool_search(ipo, 4, &ip, ifs)); 1792393Syz155240 1802393Syz155240 ip.in4.s_addr = 0x0a010001; 1812393Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 182*3448Sdh155122 ip_pool_search(ipo, 4, &ip, ifs)); 1832393Syz155240 1842393Syz155240 ip.in4.s_addr = 0x0a010101; 1852393Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 186*3448Sdh155122 ip_pool_search(ipo, 4, &ip, ifs)); 1872393Syz155240 1882393Syz155240 ip.in4.s_addr = 0x0a010201; 1892393Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 190*3448Sdh155122 ip_pool_search(ipo, 4, &ip, ifs)); 1912393Syz155240 1922393Syz155240 ip.in4.s_addr = 0x0a010203; 1932393Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 194*3448Sdh155122 ip_pool_search(ipo, 4, &ip, ifs)); 1952393Syz155240 1962393Syz155240 ip.in4.s_addr = 0x0a01020f; 1972393Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 198*3448Sdh155122 ip_pool_search(ipo, 4, &ip, ifs)); 1992393Syz155240 2002393Syz155240 ip.in4.s_addr = 0x0b00aabb; 2012393Syz155240 printf("search(%#x) = %d (-1)\n", ip.in4.s_addr, 202*3448Sdh155122 ip_pool_search(ipo, 4, &ip, ifs)); 2032393Syz155240 2042393Syz155240 #ifdef DEBUG_POOL 2052393Syz155240 treeprint(ipo); 2062393Syz155240 #endif 2072393Syz155240 208*3448Sdh155122 ip_pool_fini(ifs); 2092393Syz155240 2102393Syz155240 return 0; 2112393Syz155240 } 2122393Syz155240 2132393Syz155240 2142393Syz155240 void 2152393Syz155240 treeprint(ipo) 2162393Syz155240 ip_pool_t *ipo; 2172393Syz155240 { 2182393Syz155240 ip_pool_node_t *c; 2192393Syz155240 2202393Syz155240 for (c = ipo->ipo_list; c != NULL; c = c->ipn_next) 2212393Syz155240 printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n", 2222393Syz155240 c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr, 2232393Syz155240 c->ipn_mask.adf_addr.in4.s_addr, 2242393Syz155240 c->ipn_info, c->ipn_hits); 2252393Syz155240 } 2262393Syz155240 #endif /* TEST_POOL */ 2272393Syz155240 2282393Syz155240 2292393Syz155240 /* ------------------------------------------------------------------------ */ 2302393Syz155240 /* Function: ip_pool_init */ 2312393Syz155240 /* Returns: int - 0 = success, else error */ 2322393Syz155240 /* */ 2332393Syz155240 /* Initialise the routing table data structures where required. */ 2342393Syz155240 /* ------------------------------------------------------------------------ */ 235*3448Sdh155122 int ip_pool_init(ifs) 236*3448Sdh155122 ipf_stack_t *ifs; 2372393Syz155240 { 2382393Syz155240 239*3448Sdh155122 bzero(&ifs->ifs_ipoolstat, sizeof (ip_pool_stat_t)); 2402393Syz155240 2412535Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10)) 2422393Syz155240 rn_init(); 2432393Syz155240 #endif 2442393Syz155240 return 0; 2452393Syz155240 } 2462393Syz155240 2472393Syz155240 2482393Syz155240 /* ------------------------------------------------------------------------ */ 2492393Syz155240 /* Function: ip_pool_fini */ 2502393Syz155240 /* Returns: int - 0 = success, else error */ 2512393Syz155240 /* Locks: WRITE(ipf_global) */ 2522393Syz155240 /* */ 2532393Syz155240 /* Clean up all the pool data structures allocated and call the cleanup */ 2542393Syz155240 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/ 2552393Syz155240 /* used to delete the pools one by one to ensure they're properly freed up. */ 2562393Syz155240 /* ------------------------------------------------------------------------ */ 257*3448Sdh155122 void ip_pool_fini(ifs) 258*3448Sdh155122 ipf_stack_t *ifs; 2592393Syz155240 { 2602393Syz155240 ip_pool_t *p, *q; 2612393Syz155240 iplookupop_t op; 2622393Syz155240 int i; 2632393Syz155240 264*3448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0); 2652393Syz155240 2662393Syz155240 for (i = 0; i <= IPL_LOGMAX; i++) { 267*3448Sdh155122 for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) { 2682393Syz155240 op.iplo_unit = i; 2692393Syz155240 (void)strncpy(op.iplo_name, p->ipo_name, 2702393Syz155240 sizeof(op.iplo_name)); 2712393Syz155240 q = p->ipo_next; 272*3448Sdh155122 (void) ip_pool_destroy(&op, ifs); 2732393Syz155240 } 2742393Syz155240 } 2752393Syz155240 2762535Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10)) 2772393Syz155240 rn_fini(); 2782393Syz155240 #endif 2792393Syz155240 } 2802393Syz155240 2812393Syz155240 2822393Syz155240 /* ------------------------------------------------------------------------ */ 2832393Syz155240 /* Function: ip_pool_statistics */ 2842393Syz155240 /* Returns: int - 0 = success, else error */ 2852393Syz155240 /* Parameters: op(I) - pointer to lookup operation arguments */ 2862393Syz155240 /* */ 2872393Syz155240 /* Copy the current statistics out into user space, collecting pool list */ 2882393Syz155240 /* pointers as appropriate for later use. */ 2892393Syz155240 /* ------------------------------------------------------------------------ */ 290*3448Sdh155122 int ip_pool_statistics(op, ifs) 2912393Syz155240 iplookupop_t *op; 292*3448Sdh155122 ipf_stack_t *ifs; 2932393Syz155240 { 2942393Syz155240 ip_pool_stat_t stats; 2952393Syz155240 int unit, i, err = 0; 2962393Syz155240 297*3448Sdh155122 if (op->iplo_size != sizeof(ip_pool_stat_t)) 2982393Syz155240 return EINVAL; 2992393Syz155240 300*3448Sdh155122 bcopy((char *)&ifs->ifs_ipoolstat, (char *)&stats, sizeof(stats)); 3012393Syz155240 unit = op->iplo_unit; 3022393Syz155240 if (unit == IPL_LOGALL) { 3032393Syz155240 for (i = 0; i < IPL_LOGSIZE; i++) 304*3448Sdh155122 stats.ipls_list[i] = ifs->ifs_ip_pool_list[i]; 3052393Syz155240 } else if (unit >= 0 && unit < IPL_LOGSIZE) { 3062393Syz155240 if (op->iplo_name[0] != '\0') 3072393Syz155240 stats.ipls_list[unit] = ip_pool_find(unit, 308*3448Sdh155122 op->iplo_name, ifs); 3092393Syz155240 else 310*3448Sdh155122 stats.ipls_list[unit] = ifs->ifs_ip_pool_list[unit]; 3112393Syz155240 } else 3122393Syz155240 err = EINVAL; 3132393Syz155240 if (err == 0) 3142393Syz155240 err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); 3152393Syz155240 return err; 3162393Syz155240 } 3172393Syz155240 3182393Syz155240 3192393Syz155240 3202393Syz155240 /* ------------------------------------------------------------------------ */ 3212393Syz155240 /* Function: ip_pool_find */ 3222393Syz155240 /* Returns: int - 0 = success, else error */ 3232393Syz155240 /* Parameters: ipo(I) - pointer to the pool getting the new node. */ 3242393Syz155240 /* */ 3252393Syz155240 /* Find a matching pool inside the collection of pools for a particular */ 3262393Syz155240 /* device, indicated by the unit number. */ 3272393Syz155240 /* ------------------------------------------------------------------------ */ 328*3448Sdh155122 void *ip_pool_find(unit, name, ifs) 3292393Syz155240 int unit; 3302393Syz155240 char *name; 331*3448Sdh155122 ipf_stack_t *ifs; 3322393Syz155240 { 3332393Syz155240 ip_pool_t *p; 3342393Syz155240 335*3448Sdh155122 for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; p = p->ipo_next) 3362393Syz155240 if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0) 3372393Syz155240 break; 3382393Syz155240 return p; 3392393Syz155240 } 3402393Syz155240 3412393Syz155240 3422393Syz155240 /* ------------------------------------------------------------------------ */ 3432393Syz155240 /* Function: ip_pool_findeq */ 3442393Syz155240 /* Returns: int - 0 = success, else error */ 3452393Syz155240 /* Parameters: ipo(I) - pointer to the pool getting the new node. */ 3462393Syz155240 /* addr(I) - pointer to address information to delete */ 3472393Syz155240 /* mask(I) - */ 3482393Syz155240 /* */ 3492393Syz155240 /* Searches for an exact match of an entry in the pool. */ 3502393Syz155240 /* ------------------------------------------------------------------------ */ 3512393Syz155240 ip_pool_node_t *ip_pool_findeq(ipo, addr, mask) 3522393Syz155240 ip_pool_t *ipo; 3532393Syz155240 addrfamily_t *addr, *mask; 3542393Syz155240 { 3552393Syz155240 struct radix_node *n; 3562393Syz155240 SPL_INT(s); 3572393Syz155240 3582393Syz155240 SPL_NET(s); 3592393Syz155240 n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head); 3602393Syz155240 SPL_X(s); 3612393Syz155240 return (ip_pool_node_t *)n; 3622393Syz155240 } 3632393Syz155240 3642393Syz155240 3652393Syz155240 /* ------------------------------------------------------------------------ */ 3662393Syz155240 /* Function: ip_pool_search */ 3672393Syz155240 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 3682393Syz155240 /* Parameters: tptr(I) - pointer to the pool to search */ 3692393Syz155240 /* version(I) - IP protocol version (4 or 6) */ 3702393Syz155240 /* dptr(I) - pointer to address information */ 3712393Syz155240 /* */ 3722393Syz155240 /* Search the pool for a given address and return a search result. */ 3732393Syz155240 /* ------------------------------------------------------------------------ */ 374*3448Sdh155122 int ip_pool_search(tptr, version, dptr, ifs) 3752393Syz155240 void *tptr; 3762393Syz155240 int version; 3772393Syz155240 void *dptr; 378*3448Sdh155122 ipf_stack_t *ifs; 3792393Syz155240 { 3802393Syz155240 struct radix_node *rn; 3812393Syz155240 ip_pool_node_t *m; 3822393Syz155240 i6addr_t *addr; 3832393Syz155240 addrfamily_t v; 3842393Syz155240 ip_pool_t *ipo; 3852393Syz155240 int rv; 3862393Syz155240 3872393Syz155240 ipo = tptr; 3882393Syz155240 if (ipo == NULL) 3892393Syz155240 return -1; 3902393Syz155240 3912393Syz155240 rv = 1; 3922393Syz155240 m = NULL; 3932393Syz155240 addr = (i6addr_t *)dptr; 3942393Syz155240 bzero(&v, sizeof(v)); 3952393Syz155240 v.adf_len = offsetof(addrfamily_t, adf_addr); 3962393Syz155240 3972393Syz155240 if (version == 4) { 3982393Syz155240 v.adf_len += sizeof(addr->in4); 3992393Syz155240 v.adf_addr.in4 = addr->in4; 4002393Syz155240 #ifdef USE_INET6 4012393Syz155240 } else if (version == 6) { 4022393Syz155240 v.adf_len += sizeof(addr->in6); 4032393Syz155240 v.adf_addr.in6 = addr->in6; 4042393Syz155240 #endif 4052393Syz155240 } else 4062393Syz155240 return -1; 4072393Syz155240 408*3448Sdh155122 READ_ENTER(&ifs->ifs_ip_poolrw); 4092393Syz155240 4102393Syz155240 rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head); 4112393Syz155240 4122393Syz155240 if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) { 4132393Syz155240 m = (ip_pool_node_t *)rn; 4142393Syz155240 ipo->ipo_hits++; 4152393Syz155240 m->ipn_hits++; 4162393Syz155240 rv = m->ipn_info; 4172393Syz155240 } 418*3448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 4192393Syz155240 return rv; 4202393Syz155240 } 4212393Syz155240 4222393Syz155240 4232393Syz155240 /* ------------------------------------------------------------------------ */ 4242393Syz155240 /* Function: ip_pool_insert */ 4252393Syz155240 /* Returns: int - 0 = success, else error */ 4262393Syz155240 /* Parameters: ipo(I) - pointer to the pool getting the new node. */ 4272393Syz155240 /* addr(I) - IPv4/6 address being added as a node */ 4282393Syz155240 /* mask(I) - IPv4/6 netmask to with the node being added */ 4292393Syz155240 /* info(I) - extra information to store in this node. */ 4302393Syz155240 /* Locks: WRITE(ip_poolrw) */ 4312393Syz155240 /* */ 4322393Syz155240 /* Add another node to the pool given by ipo. The three parameters passed */ 4332393Syz155240 /* in (addr, mask, info) shold all be stored in the node. */ 4342393Syz155240 /* ------------------------------------------------------------------------ */ 435*3448Sdh155122 int ip_pool_insert(ipo, addr, mask, info, ifs) 4362393Syz155240 ip_pool_t *ipo; 4372393Syz155240 addrfamily_t *addr, *mask; 4382393Syz155240 int info; 439*3448Sdh155122 ipf_stack_t *ifs; 4402393Syz155240 { 4412393Syz155240 struct radix_node *rn; 4422393Syz155240 ip_pool_node_t *x; 4432393Syz155240 444*3448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 4452393Syz155240 4462393Syz155240 KMALLOC(x, ip_pool_node_t *); 4472393Syz155240 if (x == NULL) { 4482393Syz155240 return ENOMEM; 4492393Syz155240 } 4502393Syz155240 4512393Syz155240 bzero(x, sizeof(*x)); 4522393Syz155240 4532393Syz155240 x->ipn_info = info; 4542393Syz155240 (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name)); 4552393Syz155240 4562393Syz155240 bcopy(addr, &x->ipn_addr, sizeof(*addr)); 4572393Syz155240 x->ipn_addr.adf_len = sizeof(x->ipn_addr); 4582393Syz155240 bcopy(mask, &x->ipn_mask, sizeof(*mask)); 4592393Syz155240 x->ipn_mask.adf_len = sizeof(x->ipn_mask); 4602393Syz155240 4612393Syz155240 rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask, 4622393Syz155240 ipo->ipo_head, x->ipn_nodes); 4632393Syz155240 #ifdef DEBUG_POOL 4642393Syz155240 printf("Added %p at %p\n", x, rn); 4652393Syz155240 #endif 4662393Syz155240 4672393Syz155240 if (rn == NULL) { 4682393Syz155240 KFREE(x); 4692393Syz155240 return ENOMEM; 4702393Syz155240 } 4712393Syz155240 472*3448Sdh155122 x->ipn_ref = 1; 4732393Syz155240 x->ipn_next = ipo->ipo_list; 4742393Syz155240 x->ipn_pnext = &ipo->ipo_list; 4752393Syz155240 if (ipo->ipo_list != NULL) 4762393Syz155240 ipo->ipo_list->ipn_pnext = &x->ipn_next; 4772393Syz155240 ipo->ipo_list = x; 4782393Syz155240 479*3448Sdh155122 ifs->ifs_ipoolstat.ipls_nodes++; 4802393Syz155240 4812393Syz155240 return 0; 4822393Syz155240 } 4832393Syz155240 4842393Syz155240 4852393Syz155240 /* ------------------------------------------------------------------------ */ 4862393Syz155240 /* Function: ip_pool_create */ 4872393Syz155240 /* Returns: int - 0 = success, else error */ 4882393Syz155240 /* Parameters: op(I) - pointer to iplookup struct with call details */ 4892393Syz155240 /* Locks: WRITE(ip_poolrw) */ 4902393Syz155240 /* */ 4912393Syz155240 /* Creates a new group according to the paramters passed in via the */ 4922393Syz155240 /* iplookupop structure. Does not check to see if the group already exists */ 4932393Syz155240 /* when being inserted - assume this has already been done. If the pool is */ 4942393Syz155240 /* marked as being anonymous, give it a new, unique, identifier. Call any */ 4952393Syz155240 /* other functions required to initialise the structure. */ 4962393Syz155240 /* ------------------------------------------------------------------------ */ 497*3448Sdh155122 int ip_pool_create(op, ifs) 4982393Syz155240 iplookupop_t *op; 499*3448Sdh155122 ipf_stack_t *ifs; 5002393Syz155240 { 5012393Syz155240 char name[FR_GROUPLEN]; 5022393Syz155240 int poolnum, unit; 5032393Syz155240 ip_pool_t *h; 5042393Syz155240 505*3448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 5062393Syz155240 5072393Syz155240 KMALLOC(h, ip_pool_t *); 5082393Syz155240 if (h == NULL) 5092393Syz155240 return ENOMEM; 5102393Syz155240 bzero(h, sizeof(*h)); 5112393Syz155240 5122393Syz155240 if (rn_inithead((void **)&h->ipo_head, 5132393Syz155240 offsetof(addrfamily_t, adf_addr) << 3) == 0) { 5142393Syz155240 KFREE(h); 5152393Syz155240 return ENOMEM; 5162393Syz155240 } 5172393Syz155240 5182393Syz155240 unit = op->iplo_unit; 5192393Syz155240 5202393Syz155240 if ((op->iplo_arg & IPOOL_ANON) != 0) { 5212393Syz155240 ip_pool_t *p; 5222393Syz155240 5232393Syz155240 poolnum = IPOOL_ANON; 5242393Syz155240 5252393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL) 5262393Syz155240 (void)SNPRINTF(name, sizeof(name), "%x", poolnum); 5272393Syz155240 #else 5282393Syz155240 (void)sprintf(name, "%x", poolnum); 5292393Syz155240 #endif 5302393Syz155240 531*3448Sdh155122 for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; ) { 5322393Syz155240 if (strncmp(name, p->ipo_name, 5332393Syz155240 sizeof(p->ipo_name)) == 0) { 5342393Syz155240 poolnum++; 5352393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL) 5362393Syz155240 (void)SNPRINTF(name, sizeof(name), "%x", poolnum); 5372393Syz155240 #else 5382393Syz155240 (void)sprintf(name, "%x", poolnum); 5392393Syz155240 #endif 540*3448Sdh155122 p = ifs->ifs_ip_pool_list[unit]; 5412393Syz155240 } else 5422393Syz155240 p = p->ipo_next; 5432393Syz155240 } 5442393Syz155240 5452393Syz155240 (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name)); 5462393Syz155240 } else { 5472393Syz155240 (void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); 5482393Syz155240 } 5492393Syz155240 5502393Syz155240 h->ipo_ref = 1; 5512393Syz155240 h->ipo_list = NULL; 5522393Syz155240 h->ipo_unit = unit; 553*3448Sdh155122 h->ipo_next = ifs->ifs_ip_pool_list[unit]; 554*3448Sdh155122 if (ifs->ifs_ip_pool_list[unit] != NULL) 555*3448Sdh155122 ifs->ifs_ip_pool_list[unit]->ipo_pnext = &h->ipo_next; 556*3448Sdh155122 h->ipo_pnext = &ifs->ifs_ip_pool_list[unit]; 557*3448Sdh155122 ifs->ifs_ip_pool_list[unit] = h; 5582393Syz155240 559*3448Sdh155122 ifs->ifs_ipoolstat.ipls_pools++; 5602393Syz155240 5612393Syz155240 return 0; 5622393Syz155240 } 5632393Syz155240 5642393Syz155240 5652393Syz155240 /* ------------------------------------------------------------------------ */ 5662393Syz155240 /* Function: ip_pool_remove */ 5672393Syz155240 /* Returns: int - 0 = success, else error */ 5682393Syz155240 /* Parameters: ipo(I) - pointer to the pool to remove the node from. */ 5692393Syz155240 /* ipe(I) - address being deleted as a node */ 5702393Syz155240 /* Locks: WRITE(ip_poolrw) */ 5712393Syz155240 /* */ 5722393Syz155240 /* Add another node to the pool given by ipo. The three parameters passed */ 5732393Syz155240 /* in (addr, mask, info) shold all be stored in the node. */ 5742393Syz155240 /* ------------------------------------------------------------------------ */ 575*3448Sdh155122 int ip_pool_remove(ipo, ipe, ifs) 5762393Syz155240 ip_pool_t *ipo; 5772393Syz155240 ip_pool_node_t *ipe; 578*3448Sdh155122 ipf_stack_t *ifs; 5792393Syz155240 { 5802393Syz155240 ip_pool_node_t **ipp, *n; 5812393Syz155240 582*3448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 5832393Syz155240 5842393Syz155240 for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) { 5852393Syz155240 if (ipe == n) { 5862393Syz155240 *n->ipn_pnext = n->ipn_next; 5872393Syz155240 if (n->ipn_next) 5882393Syz155240 n->ipn_next->ipn_pnext = n->ipn_pnext; 5892393Syz155240 break; 5902393Syz155240 } 5912393Syz155240 } 5922393Syz155240 5932393Syz155240 if (n == NULL) 5942393Syz155240 return ENOENT; 5952393Syz155240 5962393Syz155240 ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, 5972393Syz155240 ipo->ipo_head); 5982393Syz155240 KFREE(n); 5992393Syz155240 600*3448Sdh155122 ifs->ifs_ipoolstat.ipls_nodes--; 6012393Syz155240 6022393Syz155240 return 0; 6032393Syz155240 } 6042393Syz155240 6052393Syz155240 6062393Syz155240 /* ------------------------------------------------------------------------ */ 6072393Syz155240 /* Function: ip_pool_destroy */ 6082393Syz155240 /* Returns: int - 0 = success, else error */ 6092393Syz155240 /* Parameters: op(I) - information about the pool to remove */ 6102393Syz155240 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 6112393Syz155240 /* */ 6122393Syz155240 /* Search for a pool using paramters passed in and if it's not otherwise */ 6132393Syz155240 /* busy, free it. */ 6142393Syz155240 /* */ 6152393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ 6162393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking */ 6172393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 6182393Syz155240 /* ------------------------------------------------------------------------ */ 619*3448Sdh155122 int ip_pool_destroy(op, ifs) 6202393Syz155240 iplookupop_t *op; 621*3448Sdh155122 ipf_stack_t *ifs; 6222393Syz155240 { 6232393Syz155240 ip_pool_t *ipo; 6242393Syz155240 625*3448Sdh155122 ipo = ip_pool_find(op->iplo_unit, op->iplo_name, ifs); 6262393Syz155240 if (ipo == NULL) 6272393Syz155240 return ESRCH; 6282393Syz155240 6292393Syz155240 if (ipo->ipo_ref != 1) 6302393Syz155240 return EBUSY; 6312393Syz155240 632*3448Sdh155122 ip_pool_free(ipo, ifs); 6332393Syz155240 return 0; 6342393Syz155240 } 6352393Syz155240 6362393Syz155240 6372393Syz155240 /* ------------------------------------------------------------------------ */ 6382393Syz155240 /* Function: ip_pool_flush */ 6392393Syz155240 /* Returns: int - number of pools deleted */ 6402393Syz155240 /* Parameters: fp(I) - which pool(s) to flush */ 6412393Syz155240 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 6422393Syz155240 /* */ 6432393Syz155240 /* Free all pools associated with the device that matches the unit number */ 6442393Syz155240 /* passed in with operation. */ 6452393Syz155240 /* */ 6462393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ 6472393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking */ 6482393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 6492393Syz155240 /* ------------------------------------------------------------------------ */ 650*3448Sdh155122 int ip_pool_flush(fp, ifs) 6512393Syz155240 iplookupflush_t *fp; 652*3448Sdh155122 ipf_stack_t *ifs; 6532393Syz155240 { 6542393Syz155240 int i, num = 0, unit, err; 6552393Syz155240 ip_pool_t *p, *q; 6562393Syz155240 iplookupop_t op; 6572393Syz155240 6582393Syz155240 unit = fp->iplf_unit; 6592393Syz155240 6602393Syz155240 for (i = 0; i <= IPL_LOGMAX; i++) { 6612393Syz155240 if (unit != IPLT_ALL && i != unit) 6622393Syz155240 continue; 663*3448Sdh155122 for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) { 6642393Syz155240 op.iplo_unit = i; 6652393Syz155240 (void)strncpy(op.iplo_name, p->ipo_name, 6662393Syz155240 sizeof(op.iplo_name)); 6672393Syz155240 q = p->ipo_next; 668*3448Sdh155122 err = ip_pool_destroy(&op, ifs); 6692393Syz155240 if (err == 0) 6702393Syz155240 num++; 6712393Syz155240 else 6722393Syz155240 break; 6732393Syz155240 } 6742393Syz155240 } 6752393Syz155240 return num; 6762393Syz155240 } 6772393Syz155240 6782393Syz155240 6792393Syz155240 /* ------------------------------------------------------------------------ */ 6802393Syz155240 /* Function: ip_pool_free */ 6812393Syz155240 /* Returns: void */ 6822393Syz155240 /* Parameters: ipo(I) - pointer to pool structure */ 6832393Syz155240 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 6842393Syz155240 /* */ 6852393Syz155240 /* Deletes the pool strucutre passed in from the list of pools and deletes */ 6862393Syz155240 /* all of the address information stored in it, including any tree data */ 6872393Syz155240 /* structures also allocated. */ 6882393Syz155240 /* */ 6892393Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ 6902393Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking */ 6912393Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 6922393Syz155240 /* ------------------------------------------------------------------------ */ 693*3448Sdh155122 void ip_pool_free(ipo, ifs) 6942393Syz155240 ip_pool_t *ipo; 695*3448Sdh155122 ipf_stack_t *ifs; 6962393Syz155240 { 6972393Syz155240 ip_pool_node_t *n; 6982393Syz155240 6992393Syz155240 while ((n = ipo->ipo_list) != NULL) { 7002393Syz155240 ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, 7012393Syz155240 ipo->ipo_head); 7022393Syz155240 7032393Syz155240 *n->ipn_pnext = n->ipn_next; 7042393Syz155240 if (n->ipn_next) 7052393Syz155240 n->ipn_next->ipn_pnext = n->ipn_pnext; 7062393Syz155240 7072393Syz155240 KFREE(n); 7082393Syz155240 709*3448Sdh155122 ifs->ifs_ipoolstat.ipls_nodes--; 7102393Syz155240 } 7112393Syz155240 7122393Syz155240 ipo->ipo_list = NULL; 7132393Syz155240 if (ipo->ipo_next != NULL) 7142393Syz155240 ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; 7152393Syz155240 *ipo->ipo_pnext = ipo->ipo_next; 7162393Syz155240 rn_freehead(ipo->ipo_head); 7172393Syz155240 KFREE(ipo); 7182393Syz155240 719*3448Sdh155122 ifs->ifs_ipoolstat.ipls_pools--; 7202393Syz155240 } 7212393Syz155240 7222393Syz155240 7232393Syz155240 /* ------------------------------------------------------------------------ */ 7242393Syz155240 /* Function: ip_pool_deref */ 7252393Syz155240 /* Returns: void */ 7262393Syz155240 /* Parameters: ipo(I) - pointer to pool structure */ 7272393Syz155240 /* Locks: WRITE(ip_poolrw) */ 7282393Syz155240 /* */ 7292393Syz155240 /* Drop the number of known references to this pool structure by one and if */ 7302393Syz155240 /* we arrive at zero known references, free it. */ 7312393Syz155240 /* ------------------------------------------------------------------------ */ 732*3448Sdh155122 void ip_pool_deref(ipo, ifs) 7332393Syz155240 ip_pool_t *ipo; 734*3448Sdh155122 ipf_stack_t *ifs; 7352393Syz155240 { 7362393Syz155240 737*3448Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 7382393Syz155240 7392393Syz155240 ipo->ipo_ref--; 7402393Syz155240 if (ipo->ipo_ref == 0) 741*3448Sdh155122 ip_pool_free(ipo, ifs); 742*3448Sdh155122 } 743*3448Sdh155122 744*3448Sdh155122 745*3448Sdh155122 746*3448Sdh155122 void ip_pool_node_deref(ipn, ifs) 747*3448Sdh155122 ip_pool_node_t *ipn; 748*3448Sdh155122 ipf_stack_t *ifs; 749*3448Sdh155122 { 750*3448Sdh155122 751*3448Sdh155122 ipn->ipn_ref--; 752*3448Sdh155122 753*3448Sdh155122 if (ipn->ipn_ref == 0) { 754*3448Sdh155122 KFREE(ipn); 755*3448Sdh155122 ifs->ifs_ipoolstat.ipls_nodes--; 756*3448Sdh155122 } 757*3448Sdh155122 } 758*3448Sdh155122 759*3448Sdh155122 760*3448Sdh155122 int ip_pool_getnext(token, ilp, ifs) 761*3448Sdh155122 ipftoken_t *token; 762*3448Sdh155122 ipflookupiter_t *ilp; 763*3448Sdh155122 ipf_stack_t *ifs; 764*3448Sdh155122 { 765*3448Sdh155122 ip_pool_node_t *node, zn, *nextnode; 766*3448Sdh155122 ip_pool_t *ipo, zp, *nextipo; 767*3448Sdh155122 int err; 768*3448Sdh155122 769*3448Sdh155122 err = 0; 770*3448Sdh155122 node = NULL; 771*3448Sdh155122 nextnode = NULL; 772*3448Sdh155122 ipo = NULL; 773*3448Sdh155122 nextipo = NULL; 774*3448Sdh155122 775*3448Sdh155122 READ_ENTER(&ifs->ifs_ip_poolrw); 776*3448Sdh155122 777*3448Sdh155122 switch (ilp->ili_otype) 778*3448Sdh155122 { 779*3448Sdh155122 case IPFLOOKUPITER_LIST : 780*3448Sdh155122 ipo = token->ipt_data; 781*3448Sdh155122 if (ipo == NULL) { 782*3448Sdh155122 nextipo = ifs->ifs_ip_pool_list[(int)ilp->ili_unit]; 783*3448Sdh155122 } else { 784*3448Sdh155122 nextipo = ipo->ipo_next; 785*3448Sdh155122 } 786*3448Sdh155122 787*3448Sdh155122 if (nextipo != NULL) { 788*3448Sdh155122 if (nextipo->ipo_next == NULL) 789*3448Sdh155122 token->ipt_alive = 0; 790*3448Sdh155122 else { 791*3448Sdh155122 ATOMIC_INC(nextipo->ipo_ref); 792*3448Sdh155122 } 793*3448Sdh155122 } else { 794*3448Sdh155122 bzero((char *)&zp, sizeof(zp)); 795*3448Sdh155122 nextipo = &zp; 796*3448Sdh155122 } 797*3448Sdh155122 break; 798*3448Sdh155122 799*3448Sdh155122 case IPFLOOKUPITER_NODE : 800*3448Sdh155122 node = token->ipt_data; 801*3448Sdh155122 if (node == NULL) { 802*3448Sdh155122 ipo = ip_pool_find(ilp->ili_unit, ilp->ili_name, ifs); 803*3448Sdh155122 if (ipo == NULL) 804*3448Sdh155122 err = ESRCH; 805*3448Sdh155122 else { 806*3448Sdh155122 nextnode = ipo->ipo_list; 807*3448Sdh155122 ipo = NULL; 808*3448Sdh155122 } 809*3448Sdh155122 } else { 810*3448Sdh155122 nextnode = node->ipn_next; 811*3448Sdh155122 } 812*3448Sdh155122 813*3448Sdh155122 if (nextnode != NULL) { 814*3448Sdh155122 if (nextnode->ipn_next == NULL) 815*3448Sdh155122 token->ipt_alive = 0; 816*3448Sdh155122 else { 817*3448Sdh155122 ATOMIC_INC(nextnode->ipn_ref); 818*3448Sdh155122 } 819*3448Sdh155122 } else { 820*3448Sdh155122 bzero((char *)&zn, sizeof(zn)); 821*3448Sdh155122 nextnode = &zn; 822*3448Sdh155122 } 823*3448Sdh155122 break; 824*3448Sdh155122 default : 825*3448Sdh155122 err = EINVAL; 826*3448Sdh155122 break; 827*3448Sdh155122 } 828*3448Sdh155122 829*3448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 830*3448Sdh155122 831*3448Sdh155122 if (err != 0) 832*3448Sdh155122 return err; 833*3448Sdh155122 834*3448Sdh155122 switch (ilp->ili_otype) 835*3448Sdh155122 { 836*3448Sdh155122 case IPFLOOKUPITER_LIST : 837*3448Sdh155122 if (ipo != NULL) { 838*3448Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 839*3448Sdh155122 ip_pool_deref(ipo, ifs); 840*3448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 841*3448Sdh155122 } 842*3448Sdh155122 token->ipt_data = nextipo; 843*3448Sdh155122 err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); 844*3448Sdh155122 if (err != 0) 845*3448Sdh155122 err = EFAULT; 846*3448Sdh155122 break; 847*3448Sdh155122 848*3448Sdh155122 case IPFLOOKUPITER_NODE : 849*3448Sdh155122 if (node != NULL) { 850*3448Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 851*3448Sdh155122 ip_pool_node_deref(node, ifs); 852*3448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 853*3448Sdh155122 } 854*3448Sdh155122 token->ipt_data = nextnode; 855*3448Sdh155122 err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); 856*3448Sdh155122 if (err != 0) 857*3448Sdh155122 err = EFAULT; 858*3448Sdh155122 break; 859*3448Sdh155122 } 860*3448Sdh155122 861*3448Sdh155122 return err; 862*3448Sdh155122 } 863*3448Sdh155122 864*3448Sdh155122 865*3448Sdh155122 void ip_pool_iterderef(otype, unit, data, ifs) 866*3448Sdh155122 u_int otype; 867*3448Sdh155122 int unit; 868*3448Sdh155122 void *data; 869*3448Sdh155122 ipf_stack_t *ifs; 870*3448Sdh155122 { 871*3448Sdh155122 872*3448Sdh155122 if (data == NULL) 873*3448Sdh155122 return; 874*3448Sdh155122 875*3448Sdh155122 if (unit < 0 || unit > IPL_LOGMAX) 876*3448Sdh155122 return; 877*3448Sdh155122 878*3448Sdh155122 switch (otype) 879*3448Sdh155122 { 880*3448Sdh155122 case IPFLOOKUPITER_LIST : 881*3448Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 882*3448Sdh155122 ip_pool_deref((ip_pool_t *)data, ifs); 883*3448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 884*3448Sdh155122 break; 885*3448Sdh155122 886*3448Sdh155122 case IPFLOOKUPITER_NODE : 887*3448Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 888*3448Sdh155122 ip_pool_node_deref((ip_pool_node_t *)data, ifs); 889*3448Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 890*3448Sdh155122 break; 891*3448Sdh155122 default : 892*3448Sdh155122 break; 893*3448Sdh155122 } 8942393Syz155240 } 8952393Syz155240 8962393Syz155240 8972393Syz155240 # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \ 8982393Syz155240 !defined(__hpux) && !defined(__sgi)) 8992393Syz155240 static int 900*3448Sdh155122 rn_freenode(struct radix_node *n, void *p, ipf_stack_t *ifs) 9012393Syz155240 { 9022393Syz155240 struct radix_node_head *rnh = p; 9032393Syz155240 struct radix_node *d; 9042393Syz155240 9052393Syz155240 d = rnh->rnh_deladdr(n->rn_key, NULL, rnh); 9062393Syz155240 if (d != NULL) { 907*3448Sdh155122 FreeS(d, ifs->ifs_max_keylen + 2 * sizeof (*d)); 9082393Syz155240 } 9092393Syz155240 return 0; 9102393Syz155240 } 9112393Syz155240 9122393Syz155240 9132393Syz155240 void 9142393Syz155240 rn_freehead(rnh) 9152393Syz155240 struct radix_node_head *rnh; 9162393Syz155240 { 9172393Syz155240 9182393Syz155240 (*rnh->rnh_walktree)(rnh, rn_freenode, rnh); 9192393Syz155240 9202393Syz155240 rnh->rnh_addaddr = NULL; 9212393Syz155240 rnh->rnh_deladdr = NULL; 9222393Syz155240 rnh->rnh_matchaddr = NULL; 9232393Syz155240 rnh->rnh_lookup = NULL; 9242393Syz155240 rnh->rnh_walktree = NULL; 9252393Syz155240 9262393Syz155240 Free(rnh); 9272393Syz155240 } 9282393Syz155240 # endif 9292393Syz155240 9302393Syz155240 #endif /* IPFILTER_LOOKUP */ 931