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