1ab25eeb5Syz155240 /* 2ab25eeb5Syz155240 * Copyright (C) 1993-2001, 2003 by Darren Reed. 3ab25eeb5Syz155240 * 4ab25eeb5Syz155240 * See the IPFILTER.LICENCE file for details on licencing. 5ab25eeb5Syz155240 * 6*de22af4eSJohn Ojemann * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 7ab25eeb5Syz155240 */ 8ab25eeb5Syz155240 9ab25eeb5Syz155240 #if defined(KERNEL) || defined(_KERNEL) 10ab25eeb5Syz155240 # undef KERNEL 11ab25eeb5Syz155240 # undef _KERNEL 12ab25eeb5Syz155240 # define KERNEL 1 13ab25eeb5Syz155240 # define _KERNEL 1 14ab25eeb5Syz155240 #endif 15ab25eeb5Syz155240 #if defined(__osf__) 16ab25eeb5Syz155240 # define _PROTO_NET_H_ 17ab25eeb5Syz155240 #endif 18ab25eeb5Syz155240 #include <sys/errno.h> 19ab25eeb5Syz155240 #include <sys/types.h> 20ab25eeb5Syz155240 #include <sys/param.h> 21ab25eeb5Syz155240 #include <sys/file.h> 22ab25eeb5Syz155240 #if !defined(_KERNEL) && !defined(__KERNEL__) 23ab25eeb5Syz155240 # include <stdio.h> 24ab25eeb5Syz155240 # include <stdlib.h> 25ab25eeb5Syz155240 # include <string.h> 26ab25eeb5Syz155240 # define _KERNEL 27ab25eeb5Syz155240 # ifdef __OpenBSD__ 28ab25eeb5Syz155240 struct file; 29ab25eeb5Syz155240 # endif 30ab25eeb5Syz155240 # include <sys/uio.h> 31ab25eeb5Syz155240 # undef _KERNEL 32ab25eeb5Syz155240 #else 33ab25eeb5Syz155240 # include <sys/systm.h> 34ab25eeb5Syz155240 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) 35ab25eeb5Syz155240 # include <sys/proc.h> 36ab25eeb5Syz155240 # endif 37ab25eeb5Syz155240 #endif 38ab25eeb5Syz155240 #include <sys/time.h> 39ab25eeb5Syz155240 #if !defined(linux) 40ab25eeb5Syz155240 # include <sys/protosw.h> 41ab25eeb5Syz155240 #endif 42ab25eeb5Syz155240 #include <sys/socket.h> 43ab25eeb5Syz155240 #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__)) 44ab25eeb5Syz155240 # include <sys/mbuf.h> 45ab25eeb5Syz155240 #endif 46ab25eeb5Syz155240 #if defined(__SVR4) || defined(__svr4__) 47ab25eeb5Syz155240 # include <sys/filio.h> 48ab25eeb5Syz155240 # include <sys/byteorder.h> 49ab25eeb5Syz155240 # ifdef _KERNEL 50ab25eeb5Syz155240 # include <sys/dditypes.h> 51ab25eeb5Syz155240 # endif 52ab25eeb5Syz155240 # include <sys/stream.h> 53ab25eeb5Syz155240 # include <sys/kmem.h> 54ab25eeb5Syz155240 #endif 55ab25eeb5Syz155240 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 56ab25eeb5Syz155240 # include <sys/malloc.h> 57ab25eeb5Syz155240 #endif 58ab25eeb5Syz155240 59ab25eeb5Syz155240 #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \ 60ab25eeb5Syz155240 defined(__hpux) || defined(__sgi)) 61ab25eeb5Syz155240 # ifdef __osf__ 62ab25eeb5Syz155240 # include <net/radix.h> 63ab25eeb5Syz155240 # endif 64ab25eeb5Syz155240 # include "radix_ipf_local.h" 65ab25eeb5Syz155240 # define _RADIX_H_ 66ab25eeb5Syz155240 #endif 67ab25eeb5Syz155240 #include <net/if.h> 68ab25eeb5Syz155240 #include <netinet/in.h> 69ab25eeb5Syz155240 70f4b3ec61Sdh155122 #include "netinet/ipf_stack.h" 71ab25eeb5Syz155240 #include "netinet/ip_compat.h" 72ab25eeb5Syz155240 #include "netinet/ip_fil.h" 73ab25eeb5Syz155240 #include "netinet/ip_pool.h" 74ab25eeb5Syz155240 75ab25eeb5Syz155240 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \ 76ab25eeb5Syz155240 ((BSD >= 198911) && !defined(__osf__) && \ 77ab25eeb5Syz155240 !defined(__hpux) && !defined(__sgi)) 78ab25eeb5Syz155240 static int rn_freenode __P((struct radix_node *, void *)); 79ab25eeb5Syz155240 #endif 80ab25eeb5Syz155240 81ab25eeb5Syz155240 /* END OF INCLUDES */ 82ab25eeb5Syz155240 83ab25eeb5Syz155240 #if !defined(lint) 84ab25eeb5Syz155240 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 85ab25eeb5Syz155240 static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $"; 86ab25eeb5Syz155240 #endif 87ab25eeb5Syz155240 88ab25eeb5Syz155240 #ifdef IPFILTER_LOOKUP 89ab25eeb5Syz155240 90ab25eeb5Syz155240 /* 91ab25eeb5Syz155240 * Binary tree routines from Sedgewick and enhanced to do ranges of addresses. 92ab25eeb5Syz155240 * NOTE: Insertion *MUST* be from greatest range to least for it to work! 93ab25eeb5Syz155240 * These should be replaced, eventually, by something else - most notably a 94ab25eeb5Syz155240 * interval searching method. The important feature is to be able to find 95ab25eeb5Syz155240 * the best match. 96ab25eeb5Syz155240 * 97ab25eeb5Syz155240 * So why not use a radix tree for this? As the first line implies, it 98ab25eeb5Syz155240 * has been written to work with a _range_ of addresses. A range is not 99ab25eeb5Syz155240 * necessarily a match with any given netmask so what we end up dealing 100ab25eeb5Syz155240 * with is an interval tree. Implementations of these are hard to find 101ab25eeb5Syz155240 * and the one herein is far from bug free. 102ab25eeb5Syz155240 * 103ab25eeb5Syz155240 * Sigh, in the end I became convinced that the bugs the code contained did 104ab25eeb5Syz155240 * not make it worthwhile not using radix trees. For now the radix tree from 105ab25eeb5Syz155240 * 4.4 BSD is used, but this is not viewed as a long term solution. 106ab25eeb5Syz155240 */ 107ab25eeb5Syz155240 108ab25eeb5Syz155240 #ifdef TEST_POOL 109ab25eeb5Syz155240 void treeprint __P((ip_pool_t *)); 110ab25eeb5Syz155240 111ab25eeb5Syz155240 int 112ab25eeb5Syz155240 main(argc, argv) 113ab25eeb5Syz155240 int argc; 114ab25eeb5Syz155240 char *argv[]; 115ab25eeb5Syz155240 { 116ab25eeb5Syz155240 addrfamily_t a, b; 117ab25eeb5Syz155240 iplookupop_t op; 118ab25eeb5Syz155240 ip_pool_t *ipo; 119ab25eeb5Syz155240 i6addr_t ip; 120*de22af4eSJohn Ojemann fr_info_t fin; 121ab25eeb5Syz155240 122f4b3ec61Sdh155122 RWLOCK_INIT(&ifs->ifs_ip_poolrw, "poolrw"); 123f4b3ec61Sdh155122 ip_pool_init(ifs); 124ab25eeb5Syz155240 125ab25eeb5Syz155240 bzero((char *)&a, sizeof(a)); 126ab25eeb5Syz155240 bzero((char *)&b, sizeof(b)); 127ab25eeb5Syz155240 bzero((char *)&ip, sizeof(ip)); 128ab25eeb5Syz155240 bzero((char *)&op, sizeof(op)); 129ab25eeb5Syz155240 strcpy(op.iplo_name, "0"); 130ab25eeb5Syz155240 131f4b3ec61Sdh155122 if (ip_pool_create(&op, ifs) == 0) 132f4b3ec61Sdh155122 ipo = ip_pool_find(0, "0", ifs); 133ab25eeb5Syz155240 134ab25eeb5Syz155240 a.adf_addr.in4.s_addr = 0x0a010203; 135ab25eeb5Syz155240 b.adf_addr.in4.s_addr = 0xffffffff; 136f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 137f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 138ab25eeb5Syz155240 139ab25eeb5Syz155240 a.adf_addr.in4.s_addr = 0x0a000000; 140ab25eeb5Syz155240 b.adf_addr.in4.s_addr = 0xff000000; 141f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs); 142f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs); 143ab25eeb5Syz155240 144ab25eeb5Syz155240 a.adf_addr.in4.s_addr = 0x0a010100; 145ab25eeb5Syz155240 b.adf_addr.in4.s_addr = 0xffffff00; 146f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 147f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 148ab25eeb5Syz155240 149ab25eeb5Syz155240 a.adf_addr.in4.s_addr = 0x0a010200; 150ab25eeb5Syz155240 b.adf_addr.in4.s_addr = 0xffffff00; 151f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs); 152f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 0, ifs); 153ab25eeb5Syz155240 154ab25eeb5Syz155240 a.adf_addr.in4.s_addr = 0x0a010000; 155ab25eeb5Syz155240 b.adf_addr.in4.s_addr = 0xffff0000; 156f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 157f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 158ab25eeb5Syz155240 159ab25eeb5Syz155240 a.adf_addr.in4.s_addr = 0x0a01020f; 160ab25eeb5Syz155240 b.adf_addr.in4.s_addr = 0xffffffff; 161f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 162f4b3ec61Sdh155122 ip_pool_insert(ipo, &a, &b, 1, ifs); 163ab25eeb5Syz155240 #ifdef DEBUG_POOL 164ab25eeb5Syz155240 treeprint(ipo); 165ab25eeb5Syz155240 #endif 166*de22af4eSJohn Ojemann fin.fin_plen = 20; 167ab25eeb5Syz155240 ip.in4.s_addr = 0x0a00aabb; 168ab25eeb5Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 169*de22af4eSJohn Ojemann ip_pool_search(ipo, 4, &ip, &fin, ifs)); 170ab25eeb5Syz155240 171ab25eeb5Syz155240 ip.in4.s_addr = 0x0a000001; 172ab25eeb5Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 173*de22af4eSJohn Ojemann ip_pool_search(ipo, 4, &ip, &fin, ifs)); 174ab25eeb5Syz155240 175ab25eeb5Syz155240 ip.in4.s_addr = 0x0a000101; 176ab25eeb5Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 177*de22af4eSJohn Ojemann ip_pool_search(ipo, 4, &ip, &fin, ifs)); 178ab25eeb5Syz155240 179ab25eeb5Syz155240 ip.in4.s_addr = 0x0a010001; 180ab25eeb5Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 181*de22af4eSJohn Ojemann ip_pool_search(ipo, 4, &ip, &fin, ifs)); 182ab25eeb5Syz155240 183ab25eeb5Syz155240 ip.in4.s_addr = 0x0a010101; 184ab25eeb5Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 185*de22af4eSJohn Ojemann ip_pool_search(ipo, 4, &ip, &fin, ifs)); 186ab25eeb5Syz155240 187ab25eeb5Syz155240 ip.in4.s_addr = 0x0a010201; 188ab25eeb5Syz155240 printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 189*de22af4eSJohn Ojemann ip_pool_search(ipo, 4, &ip, &fin, ifs)); 190ab25eeb5Syz155240 191ab25eeb5Syz155240 ip.in4.s_addr = 0x0a010203; 192ab25eeb5Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 193*de22af4eSJohn Ojemann ip_pool_search(ipo, 4, &ip, &fin, ifs)); 194ab25eeb5Syz155240 195ab25eeb5Syz155240 ip.in4.s_addr = 0x0a01020f; 196ab25eeb5Syz155240 printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 197*de22af4eSJohn Ojemann ip_pool_search(ipo, 4, &ip, &fin, ifs)); 198ab25eeb5Syz155240 199ab25eeb5Syz155240 ip.in4.s_addr = 0x0b00aabb; 200ab25eeb5Syz155240 printf("search(%#x) = %d (-1)\n", ip.in4.s_addr, 201*de22af4eSJohn Ojemann ip_pool_search(ipo, 4, &ip, &fin, ifs)); 202ab25eeb5Syz155240 203ab25eeb5Syz155240 #ifdef DEBUG_POOL 204ab25eeb5Syz155240 treeprint(ipo); 205ab25eeb5Syz155240 #endif 206ab25eeb5Syz155240 207f4b3ec61Sdh155122 ip_pool_fini(ifs); 208ab25eeb5Syz155240 209ab25eeb5Syz155240 return 0; 210ab25eeb5Syz155240 } 211ab25eeb5Syz155240 212ab25eeb5Syz155240 213ab25eeb5Syz155240 void 214ab25eeb5Syz155240 treeprint(ipo) 215ab25eeb5Syz155240 ip_pool_t *ipo; 216ab25eeb5Syz155240 { 217ab25eeb5Syz155240 ip_pool_node_t *c; 218ab25eeb5Syz155240 219ab25eeb5Syz155240 for (c = ipo->ipo_list; c != NULL; c = c->ipn_next) 220ab25eeb5Syz155240 printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n", 221ab25eeb5Syz155240 c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr, 222ab25eeb5Syz155240 c->ipn_mask.adf_addr.in4.s_addr, 223ab25eeb5Syz155240 c->ipn_info, c->ipn_hits); 224ab25eeb5Syz155240 } 225ab25eeb5Syz155240 #endif /* TEST_POOL */ 226ab25eeb5Syz155240 227ab25eeb5Syz155240 228ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 229ab25eeb5Syz155240 /* Function: ip_pool_init */ 230ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 231ab25eeb5Syz155240 /* */ 232ab25eeb5Syz155240 /* Initialise the routing table data structures where required. */ 233ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 234f4b3ec61Sdh155122 int ip_pool_init(ifs) 235f4b3ec61Sdh155122 ipf_stack_t *ifs; 236ab25eeb5Syz155240 { 237ab25eeb5Syz155240 238f4b3ec61Sdh155122 bzero(&ifs->ifs_ipoolstat, sizeof (ip_pool_stat_t)); 239ab25eeb5Syz155240 240c793af95Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10)) 241ab25eeb5Syz155240 rn_init(); 242ab25eeb5Syz155240 #endif 243ab25eeb5Syz155240 return 0; 244ab25eeb5Syz155240 } 245ab25eeb5Syz155240 246ab25eeb5Syz155240 247ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 248ab25eeb5Syz155240 /* Function: ip_pool_fini */ 249ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 250ab25eeb5Syz155240 /* Locks: WRITE(ipf_global) */ 251ab25eeb5Syz155240 /* */ 252ab25eeb5Syz155240 /* Clean up all the pool data structures allocated and call the cleanup */ 253ab25eeb5Syz155240 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/ 254ab25eeb5Syz155240 /* used to delete the pools one by one to ensure they're properly freed up. */ 255ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 256f4b3ec61Sdh155122 void ip_pool_fini(ifs) 257f4b3ec61Sdh155122 ipf_stack_t *ifs; 258ab25eeb5Syz155240 { 259ab25eeb5Syz155240 ip_pool_t *p, *q; 260ab25eeb5Syz155240 iplookupop_t op; 261ab25eeb5Syz155240 int i; 262ab25eeb5Syz155240 263f4b3ec61Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0); 264ab25eeb5Syz155240 265ab25eeb5Syz155240 for (i = 0; i <= IPL_LOGMAX; i++) { 266f4b3ec61Sdh155122 for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) { 267ab25eeb5Syz155240 op.iplo_unit = i; 268ab25eeb5Syz155240 (void)strncpy(op.iplo_name, p->ipo_name, 269ab25eeb5Syz155240 sizeof(op.iplo_name)); 270ab25eeb5Syz155240 q = p->ipo_next; 271f4b3ec61Sdh155122 (void) ip_pool_destroy(&op, ifs); 272ab25eeb5Syz155240 } 273ab25eeb5Syz155240 } 274ab25eeb5Syz155240 275c793af95Ssangeeta #if !defined(_KERNEL) || ((BSD < 199306) && (SOLARIS2 < 10)) 276ab25eeb5Syz155240 rn_fini(); 277ab25eeb5Syz155240 #endif 278ab25eeb5Syz155240 } 279ab25eeb5Syz155240 280ab25eeb5Syz155240 281ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 282ab25eeb5Syz155240 /* Function: ip_pool_statistics */ 283ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 284ab25eeb5Syz155240 /* Parameters: op(I) - pointer to lookup operation arguments */ 285ab25eeb5Syz155240 /* */ 286ab25eeb5Syz155240 /* Copy the current statistics out into user space, collecting pool list */ 287ab25eeb5Syz155240 /* pointers as appropriate for later use. */ 288ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 289f4b3ec61Sdh155122 int ip_pool_statistics(op, ifs) 290ab25eeb5Syz155240 iplookupop_t *op; 291f4b3ec61Sdh155122 ipf_stack_t *ifs; 292ab25eeb5Syz155240 { 293ab25eeb5Syz155240 ip_pool_stat_t stats; 294ab25eeb5Syz155240 int unit, i, err = 0; 295ab25eeb5Syz155240 296f4b3ec61Sdh155122 if (op->iplo_size != sizeof(ip_pool_stat_t)) 297ab25eeb5Syz155240 return EINVAL; 298ab25eeb5Syz155240 299f4b3ec61Sdh155122 bcopy((char *)&ifs->ifs_ipoolstat, (char *)&stats, sizeof(stats)); 300ab25eeb5Syz155240 unit = op->iplo_unit; 301ab25eeb5Syz155240 if (unit == IPL_LOGALL) { 302ab25eeb5Syz155240 for (i = 0; i < IPL_LOGSIZE; i++) 303f4b3ec61Sdh155122 stats.ipls_list[i] = ifs->ifs_ip_pool_list[i]; 304ab25eeb5Syz155240 } else if (unit >= 0 && unit < IPL_LOGSIZE) { 305ab25eeb5Syz155240 if (op->iplo_name[0] != '\0') 306ab25eeb5Syz155240 stats.ipls_list[unit] = ip_pool_find(unit, 307f4b3ec61Sdh155122 op->iplo_name, ifs); 308ab25eeb5Syz155240 else 309f4b3ec61Sdh155122 stats.ipls_list[unit] = ifs->ifs_ip_pool_list[unit]; 310ab25eeb5Syz155240 } else 311ab25eeb5Syz155240 err = EINVAL; 312ab25eeb5Syz155240 if (err == 0) 313ab25eeb5Syz155240 err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); 314ab25eeb5Syz155240 return err; 315ab25eeb5Syz155240 } 316ab25eeb5Syz155240 317ab25eeb5Syz155240 318ab25eeb5Syz155240 319ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 320ab25eeb5Syz155240 /* Function: ip_pool_find */ 321ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 322ab25eeb5Syz155240 /* Parameters: ipo(I) - pointer to the pool getting the new node. */ 323ab25eeb5Syz155240 /* */ 324ab25eeb5Syz155240 /* Find a matching pool inside the collection of pools for a particular */ 325ab25eeb5Syz155240 /* device, indicated by the unit number. */ 326ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 327f4b3ec61Sdh155122 void *ip_pool_find(unit, name, ifs) 328ab25eeb5Syz155240 int unit; 329ab25eeb5Syz155240 char *name; 330f4b3ec61Sdh155122 ipf_stack_t *ifs; 331ab25eeb5Syz155240 { 332ab25eeb5Syz155240 ip_pool_t *p; 333ab25eeb5Syz155240 334f4b3ec61Sdh155122 for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; p = p->ipo_next) 335ab25eeb5Syz155240 if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0) 336ab25eeb5Syz155240 break; 337ab25eeb5Syz155240 return p; 338ab25eeb5Syz155240 } 339ab25eeb5Syz155240 340ab25eeb5Syz155240 341ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 342ab25eeb5Syz155240 /* Function: ip_pool_findeq */ 343ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 344ab25eeb5Syz155240 /* Parameters: ipo(I) - pointer to the pool getting the new node. */ 345ab25eeb5Syz155240 /* addr(I) - pointer to address information to delete */ 346ab25eeb5Syz155240 /* mask(I) - */ 347ab25eeb5Syz155240 /* */ 348ab25eeb5Syz155240 /* Searches for an exact match of an entry in the pool. */ 349ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 350ab25eeb5Syz155240 ip_pool_node_t *ip_pool_findeq(ipo, addr, mask) 351ab25eeb5Syz155240 ip_pool_t *ipo; 352ab25eeb5Syz155240 addrfamily_t *addr, *mask; 353ab25eeb5Syz155240 { 354ab25eeb5Syz155240 struct radix_node *n; 355ab25eeb5Syz155240 SPL_INT(s); 356ab25eeb5Syz155240 357ab25eeb5Syz155240 SPL_NET(s); 358ab25eeb5Syz155240 n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head); 359ab25eeb5Syz155240 SPL_X(s); 360ab25eeb5Syz155240 return (ip_pool_node_t *)n; 361ab25eeb5Syz155240 } 362ab25eeb5Syz155240 363ab25eeb5Syz155240 364ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 365ab25eeb5Syz155240 /* Function: ip_pool_search */ 366ab25eeb5Syz155240 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 367ab25eeb5Syz155240 /* Parameters: tptr(I) - pointer to the pool to search */ 368ab25eeb5Syz155240 /* version(I) - IP protocol version (4 or 6) */ 369ab25eeb5Syz155240 /* dptr(I) - pointer to address information */ 370*de22af4eSJohn Ojemann /* fin - pointer to packet information */ 371*de22af4eSJohn Ojemann /* ifs - ipf stack instance */ 372ab25eeb5Syz155240 /* */ 373ab25eeb5Syz155240 /* Search the pool for a given address and return a search result. */ 374ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 375*de22af4eSJohn Ojemann int ip_pool_search(tptr, version, dptr, fin, ifs) 376ab25eeb5Syz155240 void *tptr; 377ab25eeb5Syz155240 int version; 378ab25eeb5Syz155240 void *dptr; 379*de22af4eSJohn Ojemann fr_info_t *fin; 380f4b3ec61Sdh155122 ipf_stack_t *ifs; 381ab25eeb5Syz155240 { 382ab25eeb5Syz155240 struct radix_node *rn; 383ab25eeb5Syz155240 ip_pool_node_t *m; 384ab25eeb5Syz155240 i6addr_t *addr; 385ab25eeb5Syz155240 addrfamily_t v; 386ab25eeb5Syz155240 ip_pool_t *ipo; 387ab25eeb5Syz155240 int rv; 388ab25eeb5Syz155240 389ab25eeb5Syz155240 ipo = tptr; 390ab25eeb5Syz155240 if (ipo == NULL) 391ab25eeb5Syz155240 return -1; 392ab25eeb5Syz155240 393ab25eeb5Syz155240 rv = 1; 394ab25eeb5Syz155240 m = NULL; 395ab25eeb5Syz155240 addr = (i6addr_t *)dptr; 396ab25eeb5Syz155240 bzero(&v, sizeof(v)); 397ab25eeb5Syz155240 v.adf_len = offsetof(addrfamily_t, adf_addr); 398ab25eeb5Syz155240 399ab25eeb5Syz155240 if (version == 4) { 400ab25eeb5Syz155240 v.adf_len += sizeof(addr->in4); 401ab25eeb5Syz155240 v.adf_addr.in4 = addr->in4; 402ab25eeb5Syz155240 #ifdef USE_INET6 403ab25eeb5Syz155240 } else if (version == 6) { 404ab25eeb5Syz155240 v.adf_len += sizeof(addr->in6); 405ab25eeb5Syz155240 v.adf_addr.in6 = addr->in6; 406ab25eeb5Syz155240 #endif 407ab25eeb5Syz155240 } else 408ab25eeb5Syz155240 return -1; 409ab25eeb5Syz155240 410f4b3ec61Sdh155122 READ_ENTER(&ifs->ifs_ip_poolrw); 411ab25eeb5Syz155240 412ab25eeb5Syz155240 rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head); 413ab25eeb5Syz155240 414ab25eeb5Syz155240 if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) { 415ab25eeb5Syz155240 m = (ip_pool_node_t *)rn; 416ab25eeb5Syz155240 ipo->ipo_hits++; 417ab25eeb5Syz155240 m->ipn_hits++; 418*de22af4eSJohn Ojemann m->ipn_bytes += fin->fin_plen; 419ab25eeb5Syz155240 rv = m->ipn_info; 420ab25eeb5Syz155240 } 421f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 422ab25eeb5Syz155240 return rv; 423ab25eeb5Syz155240 } 424ab25eeb5Syz155240 425ab25eeb5Syz155240 426ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 427ab25eeb5Syz155240 /* Function: ip_pool_insert */ 428ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 429ab25eeb5Syz155240 /* Parameters: ipo(I) - pointer to the pool getting the new node. */ 430ab25eeb5Syz155240 /* addr(I) - IPv4/6 address being added as a node */ 431ab25eeb5Syz155240 /* mask(I) - IPv4/6 netmask to with the node being added */ 432ab25eeb5Syz155240 /* info(I) - extra information to store in this node. */ 433ab25eeb5Syz155240 /* Locks: WRITE(ip_poolrw) */ 434ab25eeb5Syz155240 /* */ 435ab25eeb5Syz155240 /* Add another node to the pool given by ipo. The three parameters passed */ 436ab25eeb5Syz155240 /* in (addr, mask, info) shold all be stored in the node. */ 437ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 438f4b3ec61Sdh155122 int ip_pool_insert(ipo, addr, mask, info, ifs) 439ab25eeb5Syz155240 ip_pool_t *ipo; 440ab25eeb5Syz155240 addrfamily_t *addr, *mask; 441ab25eeb5Syz155240 int info; 442f4b3ec61Sdh155122 ipf_stack_t *ifs; 443ab25eeb5Syz155240 { 444ab25eeb5Syz155240 struct radix_node *rn; 445ab25eeb5Syz155240 ip_pool_node_t *x; 446ab25eeb5Syz155240 447f4b3ec61Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 448ab25eeb5Syz155240 449ab25eeb5Syz155240 KMALLOC(x, ip_pool_node_t *); 450ab25eeb5Syz155240 if (x == NULL) { 451ab25eeb5Syz155240 return ENOMEM; 452ab25eeb5Syz155240 } 453ab25eeb5Syz155240 454ab25eeb5Syz155240 bzero(x, sizeof(*x)); 455ab25eeb5Syz155240 456ab25eeb5Syz155240 x->ipn_info = info; 457ab25eeb5Syz155240 (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name)); 458ab25eeb5Syz155240 459ab25eeb5Syz155240 bcopy(addr, &x->ipn_addr, sizeof(*addr)); 460ab25eeb5Syz155240 x->ipn_addr.adf_len = sizeof(x->ipn_addr); 461ab25eeb5Syz155240 bcopy(mask, &x->ipn_mask, sizeof(*mask)); 462ab25eeb5Syz155240 x->ipn_mask.adf_len = sizeof(x->ipn_mask); 463ab25eeb5Syz155240 464ab25eeb5Syz155240 rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask, 465ab25eeb5Syz155240 ipo->ipo_head, x->ipn_nodes); 466ab25eeb5Syz155240 #ifdef DEBUG_POOL 467ab25eeb5Syz155240 printf("Added %p at %p\n", x, rn); 468ab25eeb5Syz155240 #endif 469ab25eeb5Syz155240 470ab25eeb5Syz155240 if (rn == NULL) { 471ab25eeb5Syz155240 KFREE(x); 472ab25eeb5Syz155240 return ENOMEM; 473ab25eeb5Syz155240 } 474ab25eeb5Syz155240 475f4b3ec61Sdh155122 x->ipn_ref = 1; 476ab25eeb5Syz155240 x->ipn_next = ipo->ipo_list; 477ab25eeb5Syz155240 x->ipn_pnext = &ipo->ipo_list; 478ab25eeb5Syz155240 if (ipo->ipo_list != NULL) 479ab25eeb5Syz155240 ipo->ipo_list->ipn_pnext = &x->ipn_next; 480ab25eeb5Syz155240 ipo->ipo_list = x; 481ab25eeb5Syz155240 482f4b3ec61Sdh155122 ifs->ifs_ipoolstat.ipls_nodes++; 483ab25eeb5Syz155240 484ab25eeb5Syz155240 return 0; 485ab25eeb5Syz155240 } 486ab25eeb5Syz155240 487ab25eeb5Syz155240 488ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 489ab25eeb5Syz155240 /* Function: ip_pool_create */ 490ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 491ab25eeb5Syz155240 /* Parameters: op(I) - pointer to iplookup struct with call details */ 492ab25eeb5Syz155240 /* Locks: WRITE(ip_poolrw) */ 493ab25eeb5Syz155240 /* */ 494ab25eeb5Syz155240 /* Creates a new group according to the paramters passed in via the */ 495ab25eeb5Syz155240 /* iplookupop structure. Does not check to see if the group already exists */ 496ab25eeb5Syz155240 /* when being inserted - assume this has already been done. If the pool is */ 497ab25eeb5Syz155240 /* marked as being anonymous, give it a new, unique, identifier. Call any */ 498ab25eeb5Syz155240 /* other functions required to initialise the structure. */ 499ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 500f4b3ec61Sdh155122 int ip_pool_create(op, ifs) 501ab25eeb5Syz155240 iplookupop_t *op; 502f4b3ec61Sdh155122 ipf_stack_t *ifs; 503ab25eeb5Syz155240 { 504ab25eeb5Syz155240 char name[FR_GROUPLEN]; 505ab25eeb5Syz155240 int poolnum, unit; 506ab25eeb5Syz155240 ip_pool_t *h; 507ab25eeb5Syz155240 508f4b3ec61Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 509ab25eeb5Syz155240 510ab25eeb5Syz155240 KMALLOC(h, ip_pool_t *); 511ab25eeb5Syz155240 if (h == NULL) 512ab25eeb5Syz155240 return ENOMEM; 513ab25eeb5Syz155240 bzero(h, sizeof(*h)); 514ab25eeb5Syz155240 515ab25eeb5Syz155240 if (rn_inithead((void **)&h->ipo_head, 516ab25eeb5Syz155240 offsetof(addrfamily_t, adf_addr) << 3) == 0) { 517ab25eeb5Syz155240 KFREE(h); 518ab25eeb5Syz155240 return ENOMEM; 519ab25eeb5Syz155240 } 520ab25eeb5Syz155240 521ab25eeb5Syz155240 unit = op->iplo_unit; 522ab25eeb5Syz155240 523ab25eeb5Syz155240 if ((op->iplo_arg & IPOOL_ANON) != 0) { 524ab25eeb5Syz155240 ip_pool_t *p; 525ab25eeb5Syz155240 526ab25eeb5Syz155240 poolnum = IPOOL_ANON; 527ab25eeb5Syz155240 528ab25eeb5Syz155240 #if defined(SNPRINTF) && defined(_KERNEL) 529ab25eeb5Syz155240 (void)SNPRINTF(name, sizeof(name), "%x", poolnum); 530ab25eeb5Syz155240 #else 531ab25eeb5Syz155240 (void)sprintf(name, "%x", poolnum); 532ab25eeb5Syz155240 #endif 533ab25eeb5Syz155240 534f4b3ec61Sdh155122 for (p = ifs->ifs_ip_pool_list[unit]; p != NULL; ) { 535ab25eeb5Syz155240 if (strncmp(name, p->ipo_name, 536ab25eeb5Syz155240 sizeof(p->ipo_name)) == 0) { 537ab25eeb5Syz155240 poolnum++; 538ab25eeb5Syz155240 #if defined(SNPRINTF) && defined(_KERNEL) 539ab25eeb5Syz155240 (void)SNPRINTF(name, sizeof(name), "%x", poolnum); 540ab25eeb5Syz155240 #else 541ab25eeb5Syz155240 (void)sprintf(name, "%x", poolnum); 542ab25eeb5Syz155240 #endif 543f4b3ec61Sdh155122 p = ifs->ifs_ip_pool_list[unit]; 544ab25eeb5Syz155240 } else 545ab25eeb5Syz155240 p = p->ipo_next; 546ab25eeb5Syz155240 } 547ab25eeb5Syz155240 548ab25eeb5Syz155240 (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name)); 549ab25eeb5Syz155240 } else { 550ab25eeb5Syz155240 (void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); 551ab25eeb5Syz155240 } 552ab25eeb5Syz155240 553ab25eeb5Syz155240 h->ipo_ref = 1; 554ab25eeb5Syz155240 h->ipo_list = NULL; 555ab25eeb5Syz155240 h->ipo_unit = unit; 556f4b3ec61Sdh155122 h->ipo_next = ifs->ifs_ip_pool_list[unit]; 557f4b3ec61Sdh155122 if (ifs->ifs_ip_pool_list[unit] != NULL) 558f4b3ec61Sdh155122 ifs->ifs_ip_pool_list[unit]->ipo_pnext = &h->ipo_next; 559f4b3ec61Sdh155122 h->ipo_pnext = &ifs->ifs_ip_pool_list[unit]; 560f4b3ec61Sdh155122 ifs->ifs_ip_pool_list[unit] = h; 561ab25eeb5Syz155240 562f4b3ec61Sdh155122 ifs->ifs_ipoolstat.ipls_pools++; 563ab25eeb5Syz155240 564ab25eeb5Syz155240 return 0; 565ab25eeb5Syz155240 } 566ab25eeb5Syz155240 567ab25eeb5Syz155240 568ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 569ab25eeb5Syz155240 /* Function: ip_pool_remove */ 570ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 571ab25eeb5Syz155240 /* Parameters: ipo(I) - pointer to the pool to remove the node from. */ 572ab25eeb5Syz155240 /* ipe(I) - address being deleted as a node */ 573ab25eeb5Syz155240 /* Locks: WRITE(ip_poolrw) */ 574ab25eeb5Syz155240 /* */ 575ab25eeb5Syz155240 /* Add another node to the pool given by ipo. The three parameters passed */ 576ab25eeb5Syz155240 /* in (addr, mask, info) shold all be stored in the node. */ 577ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 578f4b3ec61Sdh155122 int ip_pool_remove(ipo, ipe, ifs) 579ab25eeb5Syz155240 ip_pool_t *ipo; 580ab25eeb5Syz155240 ip_pool_node_t *ipe; 581f4b3ec61Sdh155122 ipf_stack_t *ifs; 582ab25eeb5Syz155240 { 583ab25eeb5Syz155240 ip_pool_node_t **ipp, *n; 584ab25eeb5Syz155240 585f4b3ec61Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 586ab25eeb5Syz155240 587ab25eeb5Syz155240 for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) { 588ab25eeb5Syz155240 if (ipe == n) { 589ab25eeb5Syz155240 *n->ipn_pnext = n->ipn_next; 590ab25eeb5Syz155240 if (n->ipn_next) 591ab25eeb5Syz155240 n->ipn_next->ipn_pnext = n->ipn_pnext; 592ab25eeb5Syz155240 break; 593ab25eeb5Syz155240 } 594ab25eeb5Syz155240 } 595ab25eeb5Syz155240 596ab25eeb5Syz155240 if (n == NULL) 597ab25eeb5Syz155240 return ENOENT; 598ab25eeb5Syz155240 599ab25eeb5Syz155240 ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, 600ab25eeb5Syz155240 ipo->ipo_head); 601ab25eeb5Syz155240 KFREE(n); 602ab25eeb5Syz155240 603f4b3ec61Sdh155122 ifs->ifs_ipoolstat.ipls_nodes--; 604ab25eeb5Syz155240 605ab25eeb5Syz155240 return 0; 606ab25eeb5Syz155240 } 607ab25eeb5Syz155240 608ab25eeb5Syz155240 609ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 610ab25eeb5Syz155240 /* Function: ip_pool_destroy */ 611ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 612ab25eeb5Syz155240 /* Parameters: op(I) - information about the pool to remove */ 613ab25eeb5Syz155240 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 614ab25eeb5Syz155240 /* */ 615ab25eeb5Syz155240 /* Search for a pool using paramters passed in and if it's not otherwise */ 616ab25eeb5Syz155240 /* busy, free it. */ 617ab25eeb5Syz155240 /* */ 618ab25eeb5Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ 619ab25eeb5Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking */ 620ab25eeb5Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 621ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 622f4b3ec61Sdh155122 int ip_pool_destroy(op, ifs) 623ab25eeb5Syz155240 iplookupop_t *op; 624f4b3ec61Sdh155122 ipf_stack_t *ifs; 625ab25eeb5Syz155240 { 626ab25eeb5Syz155240 ip_pool_t *ipo; 627ab25eeb5Syz155240 628f4b3ec61Sdh155122 ipo = ip_pool_find(op->iplo_unit, op->iplo_name, ifs); 629ab25eeb5Syz155240 if (ipo == NULL) 630ab25eeb5Syz155240 return ESRCH; 631ab25eeb5Syz155240 632ab25eeb5Syz155240 if (ipo->ipo_ref != 1) 633ab25eeb5Syz155240 return EBUSY; 634ab25eeb5Syz155240 635f4b3ec61Sdh155122 ip_pool_free(ipo, ifs); 636ab25eeb5Syz155240 return 0; 637ab25eeb5Syz155240 } 638ab25eeb5Syz155240 639ab25eeb5Syz155240 640ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 641ab25eeb5Syz155240 /* Function: ip_pool_flush */ 642ab25eeb5Syz155240 /* Returns: int - number of pools deleted */ 643ab25eeb5Syz155240 /* Parameters: fp(I) - which pool(s) to flush */ 644ab25eeb5Syz155240 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 645ab25eeb5Syz155240 /* */ 646ab25eeb5Syz155240 /* Free all pools associated with the device that matches the unit number */ 647ab25eeb5Syz155240 /* passed in with operation. */ 648ab25eeb5Syz155240 /* */ 649ab25eeb5Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ 650ab25eeb5Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking */ 651ab25eeb5Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 652ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 653f4b3ec61Sdh155122 int ip_pool_flush(fp, ifs) 654ab25eeb5Syz155240 iplookupflush_t *fp; 655f4b3ec61Sdh155122 ipf_stack_t *ifs; 656ab25eeb5Syz155240 { 657ab25eeb5Syz155240 int i, num = 0, unit, err; 658ab25eeb5Syz155240 ip_pool_t *p, *q; 659ab25eeb5Syz155240 iplookupop_t op; 660ab25eeb5Syz155240 661ab25eeb5Syz155240 unit = fp->iplf_unit; 662ab25eeb5Syz155240 663ab25eeb5Syz155240 for (i = 0; i <= IPL_LOGMAX; i++) { 664ab25eeb5Syz155240 if (unit != IPLT_ALL && i != unit) 665ab25eeb5Syz155240 continue; 666f4b3ec61Sdh155122 for (q = ifs->ifs_ip_pool_list[i]; (p = q) != NULL; ) { 667ab25eeb5Syz155240 op.iplo_unit = i; 668ab25eeb5Syz155240 (void)strncpy(op.iplo_name, p->ipo_name, 669ab25eeb5Syz155240 sizeof(op.iplo_name)); 670ab25eeb5Syz155240 q = p->ipo_next; 671f4b3ec61Sdh155122 err = ip_pool_destroy(&op, ifs); 672ab25eeb5Syz155240 if (err == 0) 673ab25eeb5Syz155240 num++; 674ab25eeb5Syz155240 else 675ab25eeb5Syz155240 break; 676ab25eeb5Syz155240 } 677ab25eeb5Syz155240 } 678ab25eeb5Syz155240 return num; 679ab25eeb5Syz155240 } 680ab25eeb5Syz155240 681ab25eeb5Syz155240 682ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 683ab25eeb5Syz155240 /* Function: ip_pool_free */ 684ab25eeb5Syz155240 /* Returns: void */ 685ab25eeb5Syz155240 /* Parameters: ipo(I) - pointer to pool structure */ 686ab25eeb5Syz155240 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 687ab25eeb5Syz155240 /* */ 688ab25eeb5Syz155240 /* Deletes the pool strucutre passed in from the list of pools and deletes */ 689ab25eeb5Syz155240 /* all of the address information stored in it, including any tree data */ 690ab25eeb5Syz155240 /* structures also allocated. */ 691ab25eeb5Syz155240 /* */ 692ab25eeb5Syz155240 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ 693ab25eeb5Syz155240 /* may not be initialised, we can't use an ASSERT to enforce the locking */ 694ab25eeb5Syz155240 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 695ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 696f4b3ec61Sdh155122 void ip_pool_free(ipo, ifs) 697ab25eeb5Syz155240 ip_pool_t *ipo; 698f4b3ec61Sdh155122 ipf_stack_t *ifs; 699ab25eeb5Syz155240 { 700ab25eeb5Syz155240 ip_pool_node_t *n; 701ab25eeb5Syz155240 702ab25eeb5Syz155240 while ((n = ipo->ipo_list) != NULL) { 703ab25eeb5Syz155240 ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, 704ab25eeb5Syz155240 ipo->ipo_head); 705ab25eeb5Syz155240 706ab25eeb5Syz155240 *n->ipn_pnext = n->ipn_next; 707ab25eeb5Syz155240 if (n->ipn_next) 708ab25eeb5Syz155240 n->ipn_next->ipn_pnext = n->ipn_pnext; 709ab25eeb5Syz155240 710ab25eeb5Syz155240 KFREE(n); 711ab25eeb5Syz155240 712f4b3ec61Sdh155122 ifs->ifs_ipoolstat.ipls_nodes--; 713ab25eeb5Syz155240 } 714ab25eeb5Syz155240 715ab25eeb5Syz155240 ipo->ipo_list = NULL; 716ab25eeb5Syz155240 if (ipo->ipo_next != NULL) 717ab25eeb5Syz155240 ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; 718ab25eeb5Syz155240 *ipo->ipo_pnext = ipo->ipo_next; 719ab25eeb5Syz155240 rn_freehead(ipo->ipo_head); 720ab25eeb5Syz155240 KFREE(ipo); 721ab25eeb5Syz155240 722f4b3ec61Sdh155122 ifs->ifs_ipoolstat.ipls_pools--; 723ab25eeb5Syz155240 } 724ab25eeb5Syz155240 725ab25eeb5Syz155240 726ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 727ab25eeb5Syz155240 /* Function: ip_pool_deref */ 728ab25eeb5Syz155240 /* Returns: void */ 729ab25eeb5Syz155240 /* Parameters: ipo(I) - pointer to pool structure */ 730ab25eeb5Syz155240 /* Locks: WRITE(ip_poolrw) */ 731ab25eeb5Syz155240 /* */ 732ab25eeb5Syz155240 /* Drop the number of known references to this pool structure by one and if */ 733ab25eeb5Syz155240 /* we arrive at zero known references, free it. */ 734ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 735f4b3ec61Sdh155122 void ip_pool_deref(ipo, ifs) 736ab25eeb5Syz155240 ip_pool_t *ipo; 737f4b3ec61Sdh155122 ipf_stack_t *ifs; 738ab25eeb5Syz155240 { 739ab25eeb5Syz155240 740f4b3ec61Sdh155122 ASSERT(rw_read_locked(&ifs->ifs_ip_poolrw.ipf_lk) == 0); 741ab25eeb5Syz155240 742ab25eeb5Syz155240 ipo->ipo_ref--; 743ab25eeb5Syz155240 if (ipo->ipo_ref == 0) 744f4b3ec61Sdh155122 ip_pool_free(ipo, ifs); 745f4b3ec61Sdh155122 } 746f4b3ec61Sdh155122 747f4b3ec61Sdh155122 748f4b3ec61Sdh155122 749f4b3ec61Sdh155122 void ip_pool_node_deref(ipn, ifs) 750f4b3ec61Sdh155122 ip_pool_node_t *ipn; 751f4b3ec61Sdh155122 ipf_stack_t *ifs; 752f4b3ec61Sdh155122 { 753f4b3ec61Sdh155122 754f4b3ec61Sdh155122 ipn->ipn_ref--; 755f4b3ec61Sdh155122 756f4b3ec61Sdh155122 if (ipn->ipn_ref == 0) { 757f4b3ec61Sdh155122 KFREE(ipn); 758f4b3ec61Sdh155122 ifs->ifs_ipoolstat.ipls_nodes--; 759f4b3ec61Sdh155122 } 760f4b3ec61Sdh155122 } 761f4b3ec61Sdh155122 762f4b3ec61Sdh155122 763f4b3ec61Sdh155122 int ip_pool_getnext(token, ilp, ifs) 764f4b3ec61Sdh155122 ipftoken_t *token; 765f4b3ec61Sdh155122 ipflookupiter_t *ilp; 766f4b3ec61Sdh155122 ipf_stack_t *ifs; 767f4b3ec61Sdh155122 { 768f4b3ec61Sdh155122 ip_pool_node_t *node, zn, *nextnode; 769f4b3ec61Sdh155122 ip_pool_t *ipo, zp, *nextipo; 770f4b3ec61Sdh155122 int err; 771f4b3ec61Sdh155122 772f4b3ec61Sdh155122 err = 0; 773f4b3ec61Sdh155122 node = NULL; 774f4b3ec61Sdh155122 nextnode = NULL; 775f4b3ec61Sdh155122 ipo = NULL; 776f4b3ec61Sdh155122 nextipo = NULL; 777f4b3ec61Sdh155122 778f4b3ec61Sdh155122 READ_ENTER(&ifs->ifs_ip_poolrw); 779f4b3ec61Sdh155122 780786c7074Sjojemann /* 781786c7074Sjojemann * Get "previous" entry from the token and find the next entry. 782786c7074Sjojemann * 783786c7074Sjojemann * If we found an entry, add a reference to it and update the token. 784786c7074Sjojemann * Otherwise, zero out data to be returned and NULL out token. 785786c7074Sjojemann */ 786f4b3ec61Sdh155122 switch (ilp->ili_otype) 787f4b3ec61Sdh155122 { 788f4b3ec61Sdh155122 case IPFLOOKUPITER_LIST : 789f4b3ec61Sdh155122 ipo = token->ipt_data; 790f4b3ec61Sdh155122 if (ipo == NULL) { 791f4b3ec61Sdh155122 nextipo = ifs->ifs_ip_pool_list[(int)ilp->ili_unit]; 792f4b3ec61Sdh155122 } else { 793f4b3ec61Sdh155122 nextipo = ipo->ipo_next; 794f4b3ec61Sdh155122 } 795f4b3ec61Sdh155122 if (nextipo != NULL) { 796f4b3ec61Sdh155122 ATOMIC_INC(nextipo->ipo_ref); 797786c7074Sjojemann token->ipt_data = nextipo; 798f4b3ec61Sdh155122 } else { 799f4b3ec61Sdh155122 bzero((char *)&zp, sizeof(zp)); 800f4b3ec61Sdh155122 nextipo = &zp; 801786c7074Sjojemann token->ipt_data = NULL; 802f4b3ec61Sdh155122 } 803f4b3ec61Sdh155122 break; 804f4b3ec61Sdh155122 805f4b3ec61Sdh155122 case IPFLOOKUPITER_NODE : 806f4b3ec61Sdh155122 node = token->ipt_data; 807f4b3ec61Sdh155122 if (node == NULL) { 808f4b3ec61Sdh155122 ipo = ip_pool_find(ilp->ili_unit, ilp->ili_name, ifs); 809f4b3ec61Sdh155122 if (ipo == NULL) 810f4b3ec61Sdh155122 err = ESRCH; 811f4b3ec61Sdh155122 else { 812f4b3ec61Sdh155122 nextnode = ipo->ipo_list; 813f4b3ec61Sdh155122 ipo = NULL; 814f4b3ec61Sdh155122 } 815f4b3ec61Sdh155122 } else { 816f4b3ec61Sdh155122 nextnode = node->ipn_next; 817f4b3ec61Sdh155122 } 818f4b3ec61Sdh155122 if (nextnode != NULL) { 819f4b3ec61Sdh155122 ATOMIC_INC(nextnode->ipn_ref); 820786c7074Sjojemann token->ipt_data = nextnode; 821f4b3ec61Sdh155122 } else { 822f4b3ec61Sdh155122 bzero((char *)&zn, sizeof(zn)); 823f4b3ec61Sdh155122 nextnode = &zn; 824786c7074Sjojemann token->ipt_data = NULL; 825f4b3ec61Sdh155122 } 826f4b3ec61Sdh155122 break; 827786c7074Sjojemann 828f4b3ec61Sdh155122 default : 829f4b3ec61Sdh155122 err = EINVAL; 830f4b3ec61Sdh155122 break; 831f4b3ec61Sdh155122 } 832f4b3ec61Sdh155122 833786c7074Sjojemann /* 834786c7074Sjojemann * Now that we have ref, it's save to give up lock. 835786c7074Sjojemann */ 836f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 837f4b3ec61Sdh155122 838f4b3ec61Sdh155122 if (err != 0) 839f4b3ec61Sdh155122 return err; 840f4b3ec61Sdh155122 841786c7074Sjojemann /* 842786c7074Sjojemann * Copy out the data and update the references and token as needed. 843786c7074Sjojemann */ 844f4b3ec61Sdh155122 switch (ilp->ili_otype) 845f4b3ec61Sdh155122 { 846f4b3ec61Sdh155122 case IPFLOOKUPITER_LIST : 847786c7074Sjojemann err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); 848786c7074Sjojemann if (err != 0) 849786c7074Sjojemann err = EFAULT; 850786c7074Sjojemann if (token->ipt_data == NULL) { 851786c7074Sjojemann ipf_freetoken(token, ifs); 852786c7074Sjojemann } else { 853f4b3ec61Sdh155122 if (ipo != NULL) { 854f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 855f4b3ec61Sdh155122 ip_pool_deref(ipo, ifs); 856f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 857f4b3ec61Sdh155122 } 858786c7074Sjojemann if (nextipo->ipo_next == NULL) 859786c7074Sjojemann ipf_freetoken(token, ifs); 860786c7074Sjojemann } 861f4b3ec61Sdh155122 break; 862f4b3ec61Sdh155122 863f4b3ec61Sdh155122 case IPFLOOKUPITER_NODE : 864786c7074Sjojemann err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); 865786c7074Sjojemann if (err != 0) 866786c7074Sjojemann err = EFAULT; 867786c7074Sjojemann if (token->ipt_data == NULL) { 868786c7074Sjojemann ipf_freetoken(token, ifs); 869786c7074Sjojemann } else { 870f4b3ec61Sdh155122 if (node != NULL) { 871f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 872f4b3ec61Sdh155122 ip_pool_node_deref(node, ifs); 873f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 874f4b3ec61Sdh155122 } 875786c7074Sjojemann if (nextnode->ipn_next == NULL) 876786c7074Sjojemann ipf_freetoken(token, ifs); 877786c7074Sjojemann } 878f4b3ec61Sdh155122 break; 879f4b3ec61Sdh155122 } 880f4b3ec61Sdh155122 881f4b3ec61Sdh155122 return err; 882f4b3ec61Sdh155122 } 883f4b3ec61Sdh155122 884f4b3ec61Sdh155122 885f4b3ec61Sdh155122 void ip_pool_iterderef(otype, unit, data, ifs) 886f4b3ec61Sdh155122 u_int otype; 887f4b3ec61Sdh155122 int unit; 888f4b3ec61Sdh155122 void *data; 889f4b3ec61Sdh155122 ipf_stack_t *ifs; 890f4b3ec61Sdh155122 { 891f4b3ec61Sdh155122 892f4b3ec61Sdh155122 if (data == NULL) 893f4b3ec61Sdh155122 return; 894f4b3ec61Sdh155122 895f4b3ec61Sdh155122 if (unit < 0 || unit > IPL_LOGMAX) 896f4b3ec61Sdh155122 return; 897f4b3ec61Sdh155122 898f4b3ec61Sdh155122 switch (otype) 899f4b3ec61Sdh155122 { 900f4b3ec61Sdh155122 case IPFLOOKUPITER_LIST : 901f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 902f4b3ec61Sdh155122 ip_pool_deref((ip_pool_t *)data, ifs); 903f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 904f4b3ec61Sdh155122 break; 905f4b3ec61Sdh155122 906f4b3ec61Sdh155122 case IPFLOOKUPITER_NODE : 907f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 908f4b3ec61Sdh155122 ip_pool_node_deref((ip_pool_node_t *)data, ifs); 909f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 910f4b3ec61Sdh155122 break; 911f4b3ec61Sdh155122 default : 912f4b3ec61Sdh155122 break; 913f4b3ec61Sdh155122 } 914ab25eeb5Syz155240 } 915ab25eeb5Syz155240 916ab25eeb5Syz155240 917ab25eeb5Syz155240 # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \ 918ab25eeb5Syz155240 !defined(__hpux) && !defined(__sgi)) 919ab25eeb5Syz155240 static int 920f4b3ec61Sdh155122 rn_freenode(struct radix_node *n, void *p, ipf_stack_t *ifs) 921ab25eeb5Syz155240 { 922ab25eeb5Syz155240 struct radix_node_head *rnh = p; 923ab25eeb5Syz155240 struct radix_node *d; 924ab25eeb5Syz155240 925ab25eeb5Syz155240 d = rnh->rnh_deladdr(n->rn_key, NULL, rnh); 926ab25eeb5Syz155240 if (d != NULL) { 927f4b3ec61Sdh155122 FreeS(d, ifs->ifs_max_keylen + 2 * sizeof (*d)); 928ab25eeb5Syz155240 } 929ab25eeb5Syz155240 return 0; 930ab25eeb5Syz155240 } 931ab25eeb5Syz155240 932ab25eeb5Syz155240 933ab25eeb5Syz155240 void 934ab25eeb5Syz155240 rn_freehead(rnh) 935ab25eeb5Syz155240 struct radix_node_head *rnh; 936ab25eeb5Syz155240 { 937ab25eeb5Syz155240 938ab25eeb5Syz155240 (*rnh->rnh_walktree)(rnh, rn_freenode, rnh); 939ab25eeb5Syz155240 940ab25eeb5Syz155240 rnh->rnh_addaddr = NULL; 941ab25eeb5Syz155240 rnh->rnh_deladdr = NULL; 942ab25eeb5Syz155240 rnh->rnh_matchaddr = NULL; 943ab25eeb5Syz155240 rnh->rnh_lookup = NULL; 944ab25eeb5Syz155240 rnh->rnh_walktree = NULL; 945ab25eeb5Syz155240 946ab25eeb5Syz155240 Free(rnh); 947ab25eeb5Syz155240 } 948ab25eeb5Syz155240 # endif 949ab25eeb5Syz155240 950ab25eeb5Syz155240 #endif /* IPFILTER_LOOKUP */ 951