17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (C) 1993-2001, 2003 by Darren Reed. 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * See the IPFILTER.LICENCE file for details on licencing. 57c478bd9Sstevel@tonic-gate * 6*f4b3ec61Sdh * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 77c478bd9Sstevel@tonic-gate * Use is subject to license terms. 87c478bd9Sstevel@tonic-gate */ 97c478bd9Sstevel@tonic-gate 107c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 117c478bd9Sstevel@tonic-gate 127c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL) 137c478bd9Sstevel@tonic-gate # undef KERNEL 147c478bd9Sstevel@tonic-gate # undef _KERNEL 157c478bd9Sstevel@tonic-gate # define KERNEL 1 167c478bd9Sstevel@tonic-gate # define _KERNEL 1 177c478bd9Sstevel@tonic-gate #endif 18ab25eeb5Syz #if defined(__osf__) 19ab25eeb5Syz # define _PROTO_NET_H_ 20ab25eeb5Syz #endif 217c478bd9Sstevel@tonic-gate #include <sys/errno.h> 227c478bd9Sstevel@tonic-gate #include <sys/types.h> 237c478bd9Sstevel@tonic-gate #include <sys/param.h> 247c478bd9Sstevel@tonic-gate #include <sys/file.h> 257c478bd9Sstevel@tonic-gate #if !defined(_KERNEL) && !defined(__KERNEL__) 267c478bd9Sstevel@tonic-gate # include <stdio.h> 277c478bd9Sstevel@tonic-gate # include <stdlib.h> 287c478bd9Sstevel@tonic-gate # include <string.h> 297c478bd9Sstevel@tonic-gate # define _KERNEL 307c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__ 317c478bd9Sstevel@tonic-gate struct file; 327c478bd9Sstevel@tonic-gate # endif 337c478bd9Sstevel@tonic-gate # include <sys/uio.h> 347c478bd9Sstevel@tonic-gate # undef _KERNEL 357c478bd9Sstevel@tonic-gate #else 367c478bd9Sstevel@tonic-gate # include <sys/systm.h> 377c478bd9Sstevel@tonic-gate # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) 387c478bd9Sstevel@tonic-gate # include <sys/proc.h> 397c478bd9Sstevel@tonic-gate # endif 407c478bd9Sstevel@tonic-gate #endif 417c478bd9Sstevel@tonic-gate #include <sys/time.h> 427c478bd9Sstevel@tonic-gate #if !defined(linux) 437c478bd9Sstevel@tonic-gate # include <sys/protosw.h> 447c478bd9Sstevel@tonic-gate #endif 457c478bd9Sstevel@tonic-gate #include <sys/socket.h> 467c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__)) 477c478bd9Sstevel@tonic-gate # include <sys/mbuf.h> 487c478bd9Sstevel@tonic-gate #endif 497c478bd9Sstevel@tonic-gate #if defined(__SVR4) || defined(__svr4__) 507c478bd9Sstevel@tonic-gate # include <sys/filio.h> 517c478bd9Sstevel@tonic-gate # include <sys/byteorder.h> 527c478bd9Sstevel@tonic-gate # ifdef _KERNEL 537c478bd9Sstevel@tonic-gate # include <sys/dditypes.h> 547c478bd9Sstevel@tonic-gate # endif 557c478bd9Sstevel@tonic-gate # include <sys/stream.h> 567c478bd9Sstevel@tonic-gate # include <sys/kmem.h> 577c478bd9Sstevel@tonic-gate #endif 587c478bd9Sstevel@tonic-gate #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 597c478bd9Sstevel@tonic-gate # include <sys/malloc.h> 607c478bd9Sstevel@tonic-gate #endif 617c478bd9Sstevel@tonic-gate 62ab25eeb5Syz #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \ 63ab25eeb5Syz defined(__hpux) || defined(__sgi)) 64ab25eeb5Syz # ifdef __osf__ 65ab25eeb5Syz # include <net/radix.h> 66ab25eeb5Syz # endif 67ab25eeb5Syz # include "radix_ipf_local.h" 68ab25eeb5Syz # define _RADIX_H_ 69ab25eeb5Syz #endif 707c478bd9Sstevel@tonic-gate #include <net/if.h> 717c478bd9Sstevel@tonic-gate #include <netinet/in.h> 727c478bd9Sstevel@tonic-gate 73*f4b3ec61Sdh #include "netinet/ipf_stack.h" 747c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h" 757c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h" 767c478bd9Sstevel@tonic-gate #include "netinet/ip_pool.h" 77ab25eeb5Syz 78ab25eeb5Syz #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \ 79ab25eeb5Syz ((BSD >= 198911) && !defined(__osf__) && \ 80ab25eeb5Syz !defined(__hpux) && !defined(__sgi)) 81ab25eeb5Syz static int rn_freenode __P((struct radix_node *, void *)); 827c478bd9Sstevel@tonic-gate #endif 83ab25eeb5Syz 847c478bd9Sstevel@tonic-gate /* END OF INCLUDES */ 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate #if !defined(lint) 877c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 88ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $"; 897c478bd9Sstevel@tonic-gate #endif 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* 947c478bd9Sstevel@tonic-gate * Binary tree routines from Sedgewick and enhanced to do ranges of addresses. 957c478bd9Sstevel@tonic-gate * NOTE: Insertion *MUST* be from greatest range to least for it to work! 967c478bd9Sstevel@tonic-gate * These should be replaced, eventually, by something else - most notably a 977c478bd9Sstevel@tonic-gate * interval searching method. The important feature is to be able to find 987c478bd9Sstevel@tonic-gate * the best match. 997c478bd9Sstevel@tonic-gate * 1007c478bd9Sstevel@tonic-gate * So why not use a radix tree for this? As the first line implies, it 1017c478bd9Sstevel@tonic-gate * has been written to work with a _range_ of addresses. A range is not 1027c478bd9Sstevel@tonic-gate * necessarily a match with any given netmask so what we end up dealing 1037c478bd9Sstevel@tonic-gate * with is an interval tree. Implementations of these are hard to find 1047c478bd9Sstevel@tonic-gate * and the one herein is far from bug free. 1057c478bd9Sstevel@tonic-gate * 1067c478bd9Sstevel@tonic-gate * Sigh, in the end I became convinced that the bugs the code contained did 1077c478bd9Sstevel@tonic-gate * not make it worthwhile not using radix trees. For now the radix tree from 1087c478bd9Sstevel@tonic-gate * 4.4 BSD is used, but this is not viewed as a long term solution. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate #ifdef TEST_POOL 1127c478bd9Sstevel@tonic-gate void treeprint __P((ip_pool_t *)); 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate int 1157c478bd9Sstevel@tonic-gate main(argc, argv) 1167c478bd9Sstevel@tonic-gate int argc; 1177c478bd9Sstevel@tonic-gate char *argv[]; 1187c478bd9Sstevel@tonic-gate { 1197c478bd9Sstevel@tonic-gate addrfamily_t a, b; 1207c478bd9Sstevel@tonic-gate iplookupop_t op; 1217c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 1227c478bd9Sstevel@tonic-gate i6addr_t ip; 1237c478bd9Sstevel@tonic-gate 124*f4b3ec61Sdh RWLOCK_INIT(&ifs->ifs_ip_poolrw, "poolrw"); 125*f4b3ec61Sdh ip_pool_init(ifs); 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate bzero((char *)&a, sizeof(a)); 1287c478bd9Sstevel@tonic-gate bzero((char *)&b, sizeof(b)); 1297c478bd9Sstevel@tonic-gate bzero((char *)&ip, sizeof(ip)); 1307c478bd9Sstevel@tonic-gate bzero((char *)&op, sizeof(op)); 1317c478bd9Sstevel@tonic-gate strcpy(op.iplo_name, "0"); 1327c478bd9Sstevel@tonic-gate 133*f4b3ec61Sdh if (ip_pool_create(&op, ifs) == 0) 134*f4b3ec61Sdh ipo = ip_pool_find(0, "0", ifs); 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate a.adf_addr.in4.s_addr = 0x0a010203; 1377c478bd9Sstevel@tonic-gate b.adf_addr.in4.s_addr = 0xffffffff; 138*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 1, ifs); 139*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 1, ifs); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate a.adf_addr.in4.s_addr = 0x0a000000; 1427c478bd9Sstevel@tonic-gate b.adf_addr.in4.s_addr = 0xff000000; 143*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 0, ifs); 144*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 0, ifs); 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate a.adf_addr.in4.s_addr = 0x0a010100; 1477c478bd9Sstevel@tonic-gate b.adf_addr.in4.s_addr = 0xffffff00; 148*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 1, ifs); 149*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 1, ifs); 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate a.adf_addr.in4.s_addr = 0x0a010200; 1527c478bd9Sstevel@tonic-gate b.adf_addr.in4.s_addr = 0xffffff00; 153*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 0, ifs); 154*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 0, ifs); 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate a.adf_addr.in4.s_addr = 0x0a010000; 1577c478bd9Sstevel@tonic-gate b.adf_addr.in4.s_addr = 0xffff0000; 158*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 1, ifs); 159*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 1, ifs); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate a.adf_addr.in4.s_addr = 0x0a01020f; 1627c478bd9Sstevel@tonic-gate b.adf_addr.in4.s_addr = 0xffffffff; 163*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 1, ifs); 164*f4b3ec61Sdh ip_pool_insert(ipo, &a, &b, 1, ifs); 1657c478bd9Sstevel@tonic-gate #ifdef DEBUG_POOL 1667c478bd9Sstevel@tonic-gate treeprint(ipo); 1677c478bd9Sstevel@tonic-gate #endif 1687c478bd9Sstevel@tonic-gate ip.in4.s_addr = 0x0a00aabb; 1697c478bd9Sstevel@tonic-gate printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 170*f4b3ec61Sdh ip_pool_search(ipo, 4, &ip, ifs)); 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate ip.in4.s_addr = 0x0a000001; 1737c478bd9Sstevel@tonic-gate printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 174*f4b3ec61Sdh ip_pool_search(ipo, 4, &ip, ifs)); 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate ip.in4.s_addr = 0x0a000101; 1777c478bd9Sstevel@tonic-gate printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 178*f4b3ec61Sdh ip_pool_search(ipo, 4, &ip, ifs)); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate ip.in4.s_addr = 0x0a010001; 1817c478bd9Sstevel@tonic-gate printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 182*f4b3ec61Sdh ip_pool_search(ipo, 4, &ip, ifs)); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate ip.in4.s_addr = 0x0a010101; 1857c478bd9Sstevel@tonic-gate printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 186*f4b3ec61Sdh ip_pool_search(ipo, 4, &ip, ifs)); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate ip.in4.s_addr = 0x0a010201; 1897c478bd9Sstevel@tonic-gate printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 190*f4b3ec61Sdh ip_pool_search(ipo, 4, &ip, ifs)); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate ip.in4.s_addr = 0x0a010203; 1937c478bd9Sstevel@tonic-gate printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 194*f4b3ec61Sdh ip_pool_search(ipo, 4, &ip, ifs)); 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate ip.in4.s_addr = 0x0a01020f; 1977c478bd9Sstevel@tonic-gate printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 198*f4b3ec61Sdh ip_pool_search(ipo, 4, &ip, ifs)); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate ip.in4.s_addr = 0x0b00aabb; 2017c478bd9Sstevel@tonic-gate printf("search(%#x) = %d (-1)\n", ip.in4.s_addr, 202*f4b3ec61Sdh ip_pool_search(ipo, 4, &ip, ifs)); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate #ifdef DEBUG_POOL 2057c478bd9Sstevel@tonic-gate treeprint(ipo); 2067c478bd9Sstevel@tonic-gate #endif 2077c478bd9Sstevel@tonic-gate 208*f4b3ec61Sdh ip_pool_fini(ifs); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate return 0; 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate void 2157c478bd9Sstevel@tonic-gate treeprint(ipo) 2167c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 2177c478bd9Sstevel@tonic-gate { 2187c478bd9Sstevel@tonic-gate ip_pool_node_t *c; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate for (c = ipo->ipo_list; c != NULL; c = c->ipn_next) 2217c478bd9Sstevel@tonic-gate printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n", 2227c478bd9Sstevel@tonic-gate c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr, 2237c478bd9Sstevel@tonic-gate c->ipn_mask.adf_addr.in4.s_addr, 2247c478bd9Sstevel@tonic-gate c->ipn_info, c->ipn_hits); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate #endif /* TEST_POOL */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 2307c478bd9Sstevel@tonic-gate /* Function: ip_pool_init */ 2317c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 2327c478bd9Sstevel@tonic-gate /* */ 2337c478bd9Sstevel@tonic-gate /* Initialise the routing table data structures where required. */ 2347c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 235*f4b3ec61Sdh int ip_pool_init(ifs) 236*f4b3ec61Sdh ipf_stack_t *ifs; 2377c478bd9Sstevel@tonic-gate { 238ab25eeb5Syz 239*f4b3ec61Sdh bzero(&ifs->ifs_ipoolstat, sizeof (ip_pool_stat_t)); 2407c478bd9Sstevel@tonic-gate 241c793af95Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10)) 2427c478bd9Sstevel@tonic-gate rn_init(); 2437c478bd9Sstevel@tonic-gate #endif 2447c478bd9Sstevel@tonic-gate return 0; 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 2497c478bd9Sstevel@tonic-gate /* Function: ip_pool_fini */ 2507c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 2517c478bd9Sstevel@tonic-gate /* Locks: WRITE(ipf_global) */ 2527c478bd9Sstevel@tonic-gate /* */ 2537c478bd9Sstevel@tonic-gate /* Clean up all the pool data structures allocated and call the cleanup */ 2547c478bd9Sstevel@tonic-gate /* function for the radix tree that supports the pools. ip_pool_destroy() is*/ 2557c478bd9Sstevel@tonic-gate /* used to delete the pools one by one to ensure they're properly freed up. */ 2567c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 257*f4b3ec61Sdh void ip_pool_fini(ifs) 258*f4b3ec61Sdh ipf_stack_t *ifs; 2597c478bd9Sstevel@tonic-gate { 2607c478bd9Sstevel@tonic-gate ip_pool_t *p, *q; 2617c478bd9Sstevel@tonic-gate iplookupop_t op; 2627c478bd9Sstevel@tonic-gate int i; 2637c478bd9Sstevel@tonic-gate 264*f4b3ec61Sdh ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate for (i = 0; i <= IPL_LOGMAX; i++) { 267*f4b3ec61Sdh for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) { 2687c478bd9Sstevel@tonic-gate op.iplo_unit = i; 2697c478bd9Sstevel@tonic-gate (void)strncpy(op.iplo_name, p->ipo_name, 2707c478bd9Sstevel@tonic-gate sizeof(op.iplo_name)); 2717c478bd9Sstevel@tonic-gate q = p->ipo_next; 272*f4b3ec61Sdh (void) ip_pool_destroy(&op, ifs); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 276c793af95Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10)) 2777c478bd9Sstevel@tonic-gate rn_fini(); 2787c478bd9Sstevel@tonic-gate #endif 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 281ab25eeb5Syz 2827663b816Sml /* ------------------------------------------------------------------------ */ 2837663b816Sml /* Function: ip_pool_statistics */ 2847663b816Sml /* Returns: int - 0 = success, else error */ 2857663b816Sml /* Parameters: op(I) - pointer to lookup operation arguments */ 2867663b816Sml /* */ 2877663b816Sml /* Copy the current statistics out into user space, collecting pool list */ 2887663b816Sml /* pointers as appropriate for later use. */ 2897663b816Sml /* ------------------------------------------------------------------------ */ 290*f4b3ec61Sdh int ip_pool_statistics(op, ifs) 2917663b816Sml iplookupop_t *op; 292*f4b3ec61Sdh ipf_stack_t *ifs; 2937663b816Sml { 2947663b816Sml ip_pool_stat_t stats; 2957663b816Sml int unit, i, err = 0; 2967663b816Sml 297*f4b3ec61Sdh if (op->iplo_size != sizeof(ip_pool_stat_t)) 2987663b816Sml return EINVAL; 2997663b816Sml 300*f4b3ec61Sdh bcopy((char *)&ifs->ifs_ipoolstat, (char *)&stats, sizeof(stats)); 3017663b816Sml unit = op->iplo_unit; 3027663b816Sml if (unit == IPL_LOGALL) { 3037663b816Sml for (i = 0; i < IPL_LOGSIZE; i++) 304*f4b3ec61Sdh stats.ipls_list[i] = ifs->ifs_ip_pool_list[i]; 3057663b816Sml } else if (unit >= 0 && unit < IPL_LOGSIZE) { 306ab25eeb5Syz if (op->iplo_name[0] != '\0') 307ab25eeb5Syz stats.ipls_list[unit] = ip_pool_find(unit, 308*f4b3ec61Sdh op->iplo_name, ifs); 309ab25eeb5Syz else 310*f4b3ec61Sdh stats.ipls_list[unit] = ifs->ifs_ip_pool_list[unit]; 3117663b816Sml } else 3127663b816Sml err = EINVAL; 3137663b816Sml if (err == 0) 3147663b816Sml err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); 3157663b816Sml return err; 3167663b816Sml } 3177663b816Sml 3187c478bd9Sstevel@tonic-gate 319ab25eeb5Syz 3207c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 3217c478bd9Sstevel@tonic-gate /* Function: ip_pool_find */ 3227c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 3237c478bd9Sstevel@tonic-gate /* Parameters: ipo(I) - pointer to the pool getting the new node. */ 3247c478bd9Sstevel@tonic-gate /* */ 3257c478bd9Sstevel@tonic-gate /* Find a matching pool inside the collection of pools for a particular */ 3267c478bd9Sstevel@tonic-gate /* device, indicated by the unit number. */ 3277c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 328*f4b3ec61Sdh void *ip_pool_find(unit, name, ifs) 3297c478bd9Sstevel@tonic-gate int unit; 3307c478bd9Sstevel@tonic-gate char *name; 331*f4b3ec61Sdh ipf_stack_t *ifs; 3327c478bd9Sstevel@tonic-gate { 3337c478bd9Sstevel@tonic-gate ip_pool_t *p; 3347c478bd9Sstevel@tonic-gate 335*f4b3ec61Sdh for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; p = p->ipo_next) 336ab25eeb5Syz if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0) 3377c478bd9Sstevel@tonic-gate break; 3387c478bd9Sstevel@tonic-gate return p; 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 3437c478bd9Sstevel@tonic-gate /* Function: ip_pool_findeq */ 3447c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 3457c478bd9Sstevel@tonic-gate /* Parameters: ipo(I) - pointer to the pool getting the new node. */ 346ab25eeb5Syz /* addr(I) - pointer to address information to delete */ 3477c478bd9Sstevel@tonic-gate /* mask(I) - */ 3487c478bd9Sstevel@tonic-gate /* */ 3497c478bd9Sstevel@tonic-gate /* Searches for an exact match of an entry in the pool. */ 3507c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 3517c478bd9Sstevel@tonic-gate ip_pool_node_t *ip_pool_findeq(ipo, addr, mask) 3527c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 3537663b816Sml addrfamily_t *addr, *mask; 3547c478bd9Sstevel@tonic-gate { 3557c478bd9Sstevel@tonic-gate struct radix_node *n; 356ab25eeb5Syz SPL_INT(s); 3577c478bd9Sstevel@tonic-gate 358ab25eeb5Syz SPL_NET(s); 3597c478bd9Sstevel@tonic-gate n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head); 360ab25eeb5Syz SPL_X(s); 3617c478bd9Sstevel@tonic-gate return (ip_pool_node_t *)n; 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 3667c478bd9Sstevel@tonic-gate /* Function: ip_pool_search */ 367ab25eeb5Syz /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 3687c478bd9Sstevel@tonic-gate /* Parameters: tptr(I) - pointer to the pool to search */ 3697c478bd9Sstevel@tonic-gate /* version(I) - IP protocol version (4 or 6) */ 3707c478bd9Sstevel@tonic-gate /* dptr(I) - pointer to address information */ 3717c478bd9Sstevel@tonic-gate /* */ 3727c478bd9Sstevel@tonic-gate /* Search the pool for a given address and return a search result. */ 3737c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 374*f4b3ec61Sdh int ip_pool_search(tptr, version, dptr, ifs) 3757c478bd9Sstevel@tonic-gate void *tptr; 3767c478bd9Sstevel@tonic-gate int version; 3777c478bd9Sstevel@tonic-gate void *dptr; 378*f4b3ec61Sdh ipf_stack_t *ifs; 3797c478bd9Sstevel@tonic-gate { 3807c478bd9Sstevel@tonic-gate struct radix_node *rn; 3817c478bd9Sstevel@tonic-gate ip_pool_node_t *m; 3827c478bd9Sstevel@tonic-gate i6addr_t *addr; 3837c478bd9Sstevel@tonic-gate addrfamily_t v; 3847c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 3857c478bd9Sstevel@tonic-gate int rv; 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate ipo = tptr; 3887c478bd9Sstevel@tonic-gate if (ipo == NULL) 3897c478bd9Sstevel@tonic-gate return -1; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate rv = 1; 3927c478bd9Sstevel@tonic-gate m = NULL; 3937c478bd9Sstevel@tonic-gate addr = (i6addr_t *)dptr; 3947c478bd9Sstevel@tonic-gate bzero(&v, sizeof(v)); 3957c478bd9Sstevel@tonic-gate v.adf_len = offsetof(addrfamily_t, adf_addr); 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate if (version == 4) { 3987c478bd9Sstevel@tonic-gate v.adf_len += sizeof(addr->in4); 3997c478bd9Sstevel@tonic-gate v.adf_addr.in4 = addr->in4; 4007c478bd9Sstevel@tonic-gate #ifdef USE_INET6 4017c478bd9Sstevel@tonic-gate } else if (version == 6) { 4027c478bd9Sstevel@tonic-gate v.adf_len += sizeof(addr->in6); 4037c478bd9Sstevel@tonic-gate v.adf_addr.in6 = addr->in6; 4047c478bd9Sstevel@tonic-gate #endif 4057c478bd9Sstevel@tonic-gate } else 4067c478bd9Sstevel@tonic-gate return -1; 4077c478bd9Sstevel@tonic-gate 408*f4b3ec61Sdh READ_ENTER(&ifs->ifs_ip_poolrw); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) { 4137c478bd9Sstevel@tonic-gate m = (ip_pool_node_t *)rn; 4147c478bd9Sstevel@tonic-gate ipo->ipo_hits++; 4157c478bd9Sstevel@tonic-gate m->ipn_hits++; 4167c478bd9Sstevel@tonic-gate rv = m->ipn_info; 4177c478bd9Sstevel@tonic-gate } 418*f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 4197c478bd9Sstevel@tonic-gate return rv; 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 4247c478bd9Sstevel@tonic-gate /* Function: ip_pool_insert */ 4257c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 4267c478bd9Sstevel@tonic-gate /* Parameters: ipo(I) - pointer to the pool getting the new node. */ 4277663b816Sml /* addr(I) - IPv4/6 address being added as a node */ 4287663b816Sml /* mask(I) - IPv4/6 netmask to with the node being added */ 4297c478bd9Sstevel@tonic-gate /* info(I) - extra information to store in this node. */ 4307c478bd9Sstevel@tonic-gate /* Locks: WRITE(ip_poolrw) */ 4317c478bd9Sstevel@tonic-gate /* */ 4327c478bd9Sstevel@tonic-gate /* Add another node to the pool given by ipo. The three parameters passed */ 4337c478bd9Sstevel@tonic-gate /* in (addr, mask, info) shold all be stored in the node. */ 4347c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 435*f4b3ec61Sdh int ip_pool_insert(ipo, addr, mask, info, ifs) 4367c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 4377663b816Sml addrfamily_t *addr, *mask; 4387c478bd9Sstevel@tonic-gate int info; 439*f4b3ec61Sdh ipf_stack_t *ifs; 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate struct radix_node *rn; 4427c478bd9Sstevel@tonic-gate ip_pool_node_t *x; 4437c478bd9Sstevel@tonic-gate 444*f4b3ec61Sdh ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate KMALLOC(x, ip_pool_node_t *); 4477c478bd9Sstevel@tonic-gate if (x == NULL) { 4487c478bd9Sstevel@tonic-gate return ENOMEM; 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate bzero(x, sizeof(*x)); 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate x->ipn_info = info; 4547c478bd9Sstevel@tonic-gate (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name)); 4557c478bd9Sstevel@tonic-gate 4567663b816Sml bcopy(addr, &x->ipn_addr, sizeof(*addr)); 4577c478bd9Sstevel@tonic-gate x->ipn_addr.adf_len = sizeof(x->ipn_addr); 4587663b816Sml bcopy(mask, &x->ipn_mask, sizeof(*mask)); 4597c478bd9Sstevel@tonic-gate x->ipn_mask.adf_len = sizeof(x->ipn_mask); 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask, 4627c478bd9Sstevel@tonic-gate ipo->ipo_head, x->ipn_nodes); 4637c478bd9Sstevel@tonic-gate #ifdef DEBUG_POOL 4647c478bd9Sstevel@tonic-gate printf("Added %p at %p\n", x, rn); 4657c478bd9Sstevel@tonic-gate #endif 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate if (rn == NULL) { 4687c478bd9Sstevel@tonic-gate KFREE(x); 4697c478bd9Sstevel@tonic-gate return ENOMEM; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate 472*f4b3ec61Sdh x->ipn_ref = 1; 4737c478bd9Sstevel@tonic-gate x->ipn_next = ipo->ipo_list; 4747c478bd9Sstevel@tonic-gate x->ipn_pnext = &ipo->ipo_list; 4757c478bd9Sstevel@tonic-gate if (ipo->ipo_list != NULL) 4767c478bd9Sstevel@tonic-gate ipo->ipo_list->ipn_pnext = &x->ipn_next; 4777c478bd9Sstevel@tonic-gate ipo->ipo_list = x; 4787c478bd9Sstevel@tonic-gate 479*f4b3ec61Sdh ifs->ifs_ipoolstat.ipls_nodes++; 48008254dd3Syz 4817c478bd9Sstevel@tonic-gate return 0; 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 4867c478bd9Sstevel@tonic-gate /* Function: ip_pool_create */ 4877c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 4887c478bd9Sstevel@tonic-gate /* Parameters: op(I) - pointer to iplookup struct with call details */ 4897c478bd9Sstevel@tonic-gate /* Locks: WRITE(ip_poolrw) */ 4907c478bd9Sstevel@tonic-gate /* */ 4917c478bd9Sstevel@tonic-gate /* Creates a new group according to the paramters passed in via the */ 4927c478bd9Sstevel@tonic-gate /* iplookupop structure. Does not check to see if the group already exists */ 4937c478bd9Sstevel@tonic-gate /* when being inserted - assume this has already been done. If the pool is */ 4947c478bd9Sstevel@tonic-gate /* marked as being anonymous, give it a new, unique, identifier. Call any */ 4957c478bd9Sstevel@tonic-gate /* other functions required to initialise the structure. */ 4967c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 497*f4b3ec61Sdh int ip_pool_create(op, ifs) 4987c478bd9Sstevel@tonic-gate iplookupop_t *op; 499*f4b3ec61Sdh ipf_stack_t *ifs; 5007c478bd9Sstevel@tonic-gate { 5017c478bd9Sstevel@tonic-gate char name[FR_GROUPLEN]; 5027c478bd9Sstevel@tonic-gate int poolnum, unit; 5037c478bd9Sstevel@tonic-gate ip_pool_t *h; 5047c478bd9Sstevel@tonic-gate 505*f4b3ec61Sdh ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate KMALLOC(h, ip_pool_t *); 5087c478bd9Sstevel@tonic-gate if (h == NULL) 5097c478bd9Sstevel@tonic-gate return ENOMEM; 5107c478bd9Sstevel@tonic-gate bzero(h, sizeof(*h)); 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (rn_inithead((void **)&h->ipo_head, 5137c478bd9Sstevel@tonic-gate offsetof(addrfamily_t, adf_addr) << 3) == 0) { 5147c478bd9Sstevel@tonic-gate KFREE(h); 5157c478bd9Sstevel@tonic-gate return ENOMEM; 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate unit = op->iplo_unit; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if ((op->iplo_arg & IPOOL_ANON) != 0) { 5217c478bd9Sstevel@tonic-gate ip_pool_t *p; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate poolnum = IPOOL_ANON; 524ab25eeb5Syz 525ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL) 526ab25eeb5Syz (void)SNPRINTF(name, sizeof(name), "%x", poolnum); 527ab25eeb5Syz #else 5287c478bd9Sstevel@tonic-gate (void)sprintf(name, "%x", poolnum); 529ab25eeb5Syz #endif 530ab25eeb5Syz 531*f4b3ec61Sdh for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; ) { 532ab25eeb5Syz if (strncmp(name, p->ipo_name, 533ab25eeb5Syz sizeof(p->ipo_name)) == 0) { 5347c478bd9Sstevel@tonic-gate poolnum++; 535ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL) 536ab25eeb5Syz (void)SNPRINTF(name, sizeof(name), "%x", poolnum); 537ab25eeb5Syz #else 5387c478bd9Sstevel@tonic-gate (void)sprintf(name, "%x", poolnum); 539ab25eeb5Syz #endif 540*f4b3ec61Sdh p = ifs->ifs_ip_pool_list[unit]; 5417c478bd9Sstevel@tonic-gate } else 5427c478bd9Sstevel@tonic-gate p = p->ipo_next; 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name)); 5467c478bd9Sstevel@tonic-gate } else { 5477c478bd9Sstevel@tonic-gate (void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate h->ipo_ref = 1; 5517c478bd9Sstevel@tonic-gate h->ipo_list = NULL; 5527c478bd9Sstevel@tonic-gate h->ipo_unit = unit; 553*f4b3ec61Sdh h->ipo_next = ifs->ifs_ip_pool_list[unit]; 554*f4b3ec61Sdh if (ifs->ifs_ip_pool_list[unit] != NULL) 555*f4b3ec61Sdh ifs->ifs_ip_pool_list[unit]->ipo_pnext = &h->ipo_next; 556*f4b3ec61Sdh h->ipo_pnext = &ifs->ifs_ip_pool_list[unit]; 557*f4b3ec61Sdh ifs->ifs_ip_pool_list[unit] = h; 55808254dd3Syz 559*f4b3ec61Sdh ifs->ifs_ipoolstat.ipls_pools++; 56008254dd3Syz 5617c478bd9Sstevel@tonic-gate return 0; 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 5667c478bd9Sstevel@tonic-gate /* Function: ip_pool_remove */ 5677c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 5687c478bd9Sstevel@tonic-gate /* Parameters: ipo(I) - pointer to the pool to remove the node from. */ 5697c478bd9Sstevel@tonic-gate /* ipe(I) - address being deleted as a node */ 5707c478bd9Sstevel@tonic-gate /* Locks: WRITE(ip_poolrw) */ 5717c478bd9Sstevel@tonic-gate /* */ 5727c478bd9Sstevel@tonic-gate /* Add another node to the pool given by ipo. The three parameters passed */ 5737c478bd9Sstevel@tonic-gate /* in (addr, mask, info) shold all be stored in the node. */ 5747c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 575*f4b3ec61Sdh int ip_pool_remove(ipo, ipe, ifs) 5767c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 5777c478bd9Sstevel@tonic-gate ip_pool_node_t *ipe; 578*f4b3ec61Sdh ipf_stack_t *ifs; 5797c478bd9Sstevel@tonic-gate { 5807c478bd9Sstevel@tonic-gate ip_pool_node_t **ipp, *n; 5817c478bd9Sstevel@tonic-gate 582*f4b3ec61Sdh ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) { 5857c478bd9Sstevel@tonic-gate if (ipe == n) { 5867c478bd9Sstevel@tonic-gate *n->ipn_pnext = n->ipn_next; 5877c478bd9Sstevel@tonic-gate if (n->ipn_next) 5887c478bd9Sstevel@tonic-gate n->ipn_next->ipn_pnext = n->ipn_pnext; 5897c478bd9Sstevel@tonic-gate break; 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate if (n == NULL) 5947c478bd9Sstevel@tonic-gate return ENOENT; 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, 5977c478bd9Sstevel@tonic-gate ipo->ipo_head); 5987c478bd9Sstevel@tonic-gate KFREE(n); 59908254dd3Syz 600*f4b3ec61Sdh ifs->ifs_ipoolstat.ipls_nodes--; 60108254dd3Syz 6027c478bd9Sstevel@tonic-gate return 0; 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 6077c478bd9Sstevel@tonic-gate /* Function: ip_pool_destroy */ 6087c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 6097c478bd9Sstevel@tonic-gate /* Parameters: op(I) - information about the pool to remove */ 6107c478bd9Sstevel@tonic-gate /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 6117c478bd9Sstevel@tonic-gate /* */ 6127c478bd9Sstevel@tonic-gate /* Search for a pool using paramters passed in and if it's not otherwise */ 6137c478bd9Sstevel@tonic-gate /* busy, free it. */ 6147c478bd9Sstevel@tonic-gate /* */ 6157c478bd9Sstevel@tonic-gate /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ 6167c478bd9Sstevel@tonic-gate /* may not be initialised, we can't use an ASSERT to enforce the locking */ 6177c478bd9Sstevel@tonic-gate /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 6187c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 619*f4b3ec61Sdh int ip_pool_destroy(op, ifs) 6207c478bd9Sstevel@tonic-gate iplookupop_t *op; 621*f4b3ec61Sdh ipf_stack_t *ifs; 6227c478bd9Sstevel@tonic-gate { 6237c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 6247c478bd9Sstevel@tonic-gate 625*f4b3ec61Sdh ipo = ip_pool_find(op->iplo_unit, op->iplo_name, ifs); 6267c478bd9Sstevel@tonic-gate if (ipo == NULL) 6277c478bd9Sstevel@tonic-gate return ESRCH; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate if (ipo->ipo_ref != 1) 6307c478bd9Sstevel@tonic-gate return EBUSY; 6317c478bd9Sstevel@tonic-gate 632*f4b3ec61Sdh ip_pool_free(ipo, ifs); 6337c478bd9Sstevel@tonic-gate return 0; 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate 637ab25eeb5Syz /* ------------------------------------------------------------------------ */ 638ab25eeb5Syz /* Function: ip_pool_flush */ 639ab25eeb5Syz /* Returns: int - number of pools deleted */ 640ab25eeb5Syz /* Parameters: fp(I) - which pool(s) to flush */ 641ab25eeb5Syz /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 642ab25eeb5Syz /* */ 643ab25eeb5Syz /* Free all pools associated with the device that matches the unit number */ 644ab25eeb5Syz /* passed in with operation. */ 645ab25eeb5Syz /* */ 646ab25eeb5Syz /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ 647ab25eeb5Syz /* may not be initialised, we can't use an ASSERT to enforce the locking */ 648ab25eeb5Syz /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 649ab25eeb5Syz /* ------------------------------------------------------------------------ */ 650*f4b3ec61Sdh int ip_pool_flush(fp, ifs) 651ab25eeb5Syz iplookupflush_t *fp; 652*f4b3ec61Sdh ipf_stack_t *ifs; 653ab25eeb5Syz { 654ab25eeb5Syz int i, num = 0, unit, err; 655ab25eeb5Syz ip_pool_t *p, *q; 656ab25eeb5Syz iplookupop_t op; 657ab25eeb5Syz 658ab25eeb5Syz unit = fp->iplf_unit; 659ab25eeb5Syz 660ab25eeb5Syz for (i = 0; i <= IPL_LOGMAX; i++) { 661ab25eeb5Syz if (unit != IPLT_ALL && i != unit) 662ab25eeb5Syz continue; 663*f4b3ec61Sdh for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) { 664ab25eeb5Syz op.iplo_unit = i; 665ab25eeb5Syz (void)strncpy(op.iplo_name, p->ipo_name, 666ab25eeb5Syz sizeof(op.iplo_name)); 667ab25eeb5Syz q = p->ipo_next; 668*f4b3ec61Sdh err = ip_pool_destroy(&op, ifs); 669ab25eeb5Syz if (err == 0) 670ab25eeb5Syz num++; 671ab25eeb5Syz else 672ab25eeb5Syz break; 673ab25eeb5Syz } 674ab25eeb5Syz } 675ab25eeb5Syz return num; 676ab25eeb5Syz } 677ab25eeb5Syz 678ab25eeb5Syz 6797c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 6807c478bd9Sstevel@tonic-gate /* Function: ip_pool_free */ 6817c478bd9Sstevel@tonic-gate /* Returns: void */ 6827c478bd9Sstevel@tonic-gate /* Parameters: ipo(I) - pointer to pool structure */ 6837c478bd9Sstevel@tonic-gate /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 6847c478bd9Sstevel@tonic-gate /* */ 6857c478bd9Sstevel@tonic-gate /* Deletes the pool strucutre passed in from the list of pools and deletes */ 6867c478bd9Sstevel@tonic-gate /* all of the address information stored in it, including any tree data */ 6877c478bd9Sstevel@tonic-gate /* structures also allocated. */ 6887c478bd9Sstevel@tonic-gate /* */ 6897c478bd9Sstevel@tonic-gate /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ 6907c478bd9Sstevel@tonic-gate /* may not be initialised, we can't use an ASSERT to enforce the locking */ 6917c478bd9Sstevel@tonic-gate /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 6927c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 693*f4b3ec61Sdh void ip_pool_free(ipo, ifs) 6947c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 695*f4b3ec61Sdh ipf_stack_t *ifs; 6967c478bd9Sstevel@tonic-gate { 6977c478bd9Sstevel@tonic-gate ip_pool_node_t *n; 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate while ((n = ipo->ipo_list) != NULL) { 7007c478bd9Sstevel@tonic-gate ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, 7017c478bd9Sstevel@tonic-gate ipo->ipo_head); 702ab25eeb5Syz 7037c478bd9Sstevel@tonic-gate *n->ipn_pnext = n->ipn_next; 7047c478bd9Sstevel@tonic-gate if (n->ipn_next) 7057c478bd9Sstevel@tonic-gate n->ipn_next->ipn_pnext = n->ipn_pnext; 706ab25eeb5Syz 7077c478bd9Sstevel@tonic-gate KFREE(n); 70808254dd3Syz 709*f4b3ec61Sdh ifs->ifs_ipoolstat.ipls_nodes--; 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate ipo->ipo_list = NULL; 7137c478bd9Sstevel@tonic-gate if (ipo->ipo_next != NULL) 7147c478bd9Sstevel@tonic-gate ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; 7157c478bd9Sstevel@tonic-gate *ipo->ipo_pnext = ipo->ipo_next; 7167c478bd9Sstevel@tonic-gate rn_freehead(ipo->ipo_head); 7177c478bd9Sstevel@tonic-gate KFREE(ipo); 71808254dd3Syz 719*f4b3ec61Sdh ifs->ifs_ipoolstat.ipls_pools--; 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 7247c478bd9Sstevel@tonic-gate /* Function: ip_pool_deref */ 7257c478bd9Sstevel@tonic-gate /* Returns: void */ 7267c478bd9Sstevel@tonic-gate /* Parameters: ipo(I) - pointer to pool structure */ 7277c478bd9Sstevel@tonic-gate /* Locks: WRITE(ip_poolrw) */ 7287c478bd9Sstevel@tonic-gate /* */ 7297c478bd9Sstevel@tonic-gate /* Drop the number of known references to this pool structure by one and if */ 7307c478bd9Sstevel@tonic-gate /* we arrive at zero known references, free it. */ 7317c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 732*f4b3ec61Sdh void ip_pool_deref(ipo, ifs) 7337c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 734*f4b3ec61Sdh ipf_stack_t *ifs; 7357c478bd9Sstevel@tonic-gate { 7367c478bd9Sstevel@tonic-gate 737*f4b3ec61Sdh ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate ipo->ipo_ref--; 7407c478bd9Sstevel@tonic-gate if (ipo->ipo_ref == 0) 741*f4b3ec61Sdh ip_pool_free(ipo, ifs); 742*f4b3ec61Sdh } 743*f4b3ec61Sdh 744*f4b3ec61Sdh 745*f4b3ec61Sdh 746*f4b3ec61Sdh void ip_pool_node_deref(ipn, ifs) 747*f4b3ec61Sdh ip_pool_node_t *ipn; 748*f4b3ec61Sdh ipf_stack_t *ifs; 749*f4b3ec61Sdh { 750*f4b3ec61Sdh 751*f4b3ec61Sdh ipn->ipn_ref--; 752*f4b3ec61Sdh 753*f4b3ec61Sdh if (ipn->ipn_ref == 0) { 754*f4b3ec61Sdh KFREE(ipn); 755*f4b3ec61Sdh ifs->ifs_ipoolstat.ipls_nodes--; 756*f4b3ec61Sdh } 757*f4b3ec61Sdh } 758*f4b3ec61Sdh 759*f4b3ec61Sdh 760*f4b3ec61Sdh int ip_pool_getnext(token, ilp, ifs) 761*f4b3ec61Sdh ipftoken_t *token; 762*f4b3ec61Sdh ipflookupiter_t *ilp; 763*f4b3ec61Sdh ipf_stack_t *ifs; 764*f4b3ec61Sdh { 765*f4b3ec61Sdh ip_pool_node_t *node, zn, *nextnode; 766*f4b3ec61Sdh ip_pool_t *ipo, zp, *nextipo; 767*f4b3ec61Sdh int err; 768*f4b3ec61Sdh 769*f4b3ec61Sdh err = 0; 770*f4b3ec61Sdh node = NULL; 771*f4b3ec61Sdh nextnode = NULL; 772*f4b3ec61Sdh ipo = NULL; 773*f4b3ec61Sdh nextipo = NULL; 774*f4b3ec61Sdh 775*f4b3ec61Sdh READ_ENTER(&ifs->ifs_ip_poolrw); 776*f4b3ec61Sdh 777*f4b3ec61Sdh switch (ilp->ili_otype) 778*f4b3ec61Sdh { 779*f4b3ec61Sdh case IPFLOOKUPITER_LIST : 780*f4b3ec61Sdh ipo = token->ipt_data; 781*f4b3ec61Sdh if (ipo == NULL) { 782*f4b3ec61Sdh nextipo = ifs->ifs_ip_pool_list[(int)ilp->ili_unit]; 783*f4b3ec61Sdh } else { 784*f4b3ec61Sdh nextipo = ipo->ipo_next; 785*f4b3ec61Sdh } 786*f4b3ec61Sdh 787*f4b3ec61Sdh if (nextipo != NULL) { 788*f4b3ec61Sdh if (nextipo->ipo_next == NULL) 789*f4b3ec61Sdh token->ipt_alive = 0; 790*f4b3ec61Sdh else { 791*f4b3ec61Sdh ATOMIC_INC(nextipo->ipo_ref); 792*f4b3ec61Sdh } 793*f4b3ec61Sdh } else { 794*f4b3ec61Sdh bzero((char *)&zp, sizeof(zp)); 795*f4b3ec61Sdh nextipo = &zp; 796*f4b3ec61Sdh } 797*f4b3ec61Sdh break; 798*f4b3ec61Sdh 799*f4b3ec61Sdh case IPFLOOKUPITER_NODE : 800*f4b3ec61Sdh node = token->ipt_data; 801*f4b3ec61Sdh if (node == NULL) { 802*f4b3ec61Sdh ipo = ip_pool_find(ilp->ili_unit, ilp->ili_name, ifs); 803*f4b3ec61Sdh if (ipo == NULL) 804*f4b3ec61Sdh err = ESRCH; 805*f4b3ec61Sdh else { 806*f4b3ec61Sdh nextnode = ipo->ipo_list; 807*f4b3ec61Sdh ipo = NULL; 808*f4b3ec61Sdh } 809*f4b3ec61Sdh } else { 810*f4b3ec61Sdh nextnode = node->ipn_next; 811*f4b3ec61Sdh } 812*f4b3ec61Sdh 813*f4b3ec61Sdh if (nextnode != NULL) { 814*f4b3ec61Sdh if (nextnode->ipn_next == NULL) 815*f4b3ec61Sdh token->ipt_alive = 0; 816*f4b3ec61Sdh else { 817*f4b3ec61Sdh ATOMIC_INC(nextnode->ipn_ref); 818*f4b3ec61Sdh } 819*f4b3ec61Sdh } else { 820*f4b3ec61Sdh bzero((char *)&zn, sizeof(zn)); 821*f4b3ec61Sdh nextnode = &zn; 822*f4b3ec61Sdh } 823*f4b3ec61Sdh break; 824*f4b3ec61Sdh default : 825*f4b3ec61Sdh err = EINVAL; 826*f4b3ec61Sdh break; 827*f4b3ec61Sdh } 828*f4b3ec61Sdh 829*f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 830*f4b3ec61Sdh 831*f4b3ec61Sdh if (err != 0) 832*f4b3ec61Sdh return err; 833*f4b3ec61Sdh 834*f4b3ec61Sdh switch (ilp->ili_otype) 835*f4b3ec61Sdh { 836*f4b3ec61Sdh case IPFLOOKUPITER_LIST : 837*f4b3ec61Sdh if (ipo != NULL) { 838*f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 839*f4b3ec61Sdh ip_pool_deref(ipo, ifs); 840*f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 841*f4b3ec61Sdh } 842*f4b3ec61Sdh token->ipt_data = nextipo; 843*f4b3ec61Sdh err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); 844*f4b3ec61Sdh if (err != 0) 845*f4b3ec61Sdh err = EFAULT; 846*f4b3ec61Sdh break; 847*f4b3ec61Sdh 848*f4b3ec61Sdh case IPFLOOKUPITER_NODE : 849*f4b3ec61Sdh if (node != NULL) { 850*f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 851*f4b3ec61Sdh ip_pool_node_deref(node, ifs); 852*f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 853*f4b3ec61Sdh } 854*f4b3ec61Sdh token->ipt_data = nextnode; 855*f4b3ec61Sdh err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); 856*f4b3ec61Sdh if (err != 0) 857*f4b3ec61Sdh err = EFAULT; 858*f4b3ec61Sdh break; 859*f4b3ec61Sdh } 860*f4b3ec61Sdh 861*f4b3ec61Sdh return err; 862*f4b3ec61Sdh } 863*f4b3ec61Sdh 864*f4b3ec61Sdh 865*f4b3ec61Sdh void ip_pool_iterderef(otype, unit, data, ifs) 866*f4b3ec61Sdh u_int otype; 867*f4b3ec61Sdh int unit; 868*f4b3ec61Sdh void *data; 869*f4b3ec61Sdh ipf_stack_t *ifs; 870*f4b3ec61Sdh { 871*f4b3ec61Sdh 872*f4b3ec61Sdh if (data == NULL) 873*f4b3ec61Sdh return; 874*f4b3ec61Sdh 875*f4b3ec61Sdh if (unit < 0 || unit > IPL_LOGMAX) 876*f4b3ec61Sdh return; 877*f4b3ec61Sdh 878*f4b3ec61Sdh switch (otype) 879*f4b3ec61Sdh { 880*f4b3ec61Sdh case IPFLOOKUPITER_LIST : 881*f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 882*f4b3ec61Sdh ip_pool_deref((ip_pool_t *)data, ifs); 883*f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 884*f4b3ec61Sdh break; 885*f4b3ec61Sdh 886*f4b3ec61Sdh case IPFLOOKUPITER_NODE : 887*f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 888*f4b3ec61Sdh ip_pool_node_deref((ip_pool_node_t *)data, ifs); 889*f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 890*f4b3ec61Sdh break; 891*f4b3ec61Sdh default : 892*f4b3ec61Sdh break; 893*f4b3ec61Sdh } 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate 897ab25eeb5Syz # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \ 898ab25eeb5Syz !defined(__hpux) && !defined(__sgi)) 8997c478bd9Sstevel@tonic-gate static int 900*f4b3ec61Sdh rn_freenode(struct radix_node *n, void *p, ipf_stack_t *ifs) 9017c478bd9Sstevel@tonic-gate { 9027c478bd9Sstevel@tonic-gate struct radix_node_head *rnh = p; 9037c478bd9Sstevel@tonic-gate struct radix_node *d; 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate d = rnh->rnh_deladdr(n->rn_key, NULL, rnh); 9067c478bd9Sstevel@tonic-gate if (d != NULL) { 907*f4b3ec61Sdh FreeS(d, ifs->ifs_max_keylen + 2 * sizeof (*d)); 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate return 0; 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate void 9147c478bd9Sstevel@tonic-gate rn_freehead(rnh) 9157c478bd9Sstevel@tonic-gate struct radix_node_head *rnh; 9167c478bd9Sstevel@tonic-gate { 9177c478bd9Sstevel@tonic-gate 918ab25eeb5Syz (*rnh->rnh_walktree)(rnh, rn_freenode, rnh); 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate rnh->rnh_addaddr = NULL; 9217c478bd9Sstevel@tonic-gate rnh->rnh_deladdr = NULL; 9227c478bd9Sstevel@tonic-gate rnh->rnh_matchaddr = NULL; 9237c478bd9Sstevel@tonic-gate rnh->rnh_lookup = NULL; 9247c478bd9Sstevel@tonic-gate rnh->rnh_walktree = NULL; 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate Free(rnh); 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate # endif 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOOKUP */ 931