1145516Sdarrenr/* 2255332Scy * Copyright (C) 2012 by Darren Reed. 3145516Sdarrenr * 4145516Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 5145516Sdarrenr */ 6145516Sdarrenr#if defined(KERNEL) || defined(_KERNEL) 7145516Sdarrenr# undef KERNEL 8145516Sdarrenr# undef _KERNEL 9145516Sdarrenr# define KERNEL 1 10145516Sdarrenr# define _KERNEL 1 11145516Sdarrenr#endif 12145516Sdarrenr#if defined(__osf__) 13145516Sdarrenr# define _PROTO_NET_H_ 14145516Sdarrenr#endif 15145516Sdarrenr#include <sys/errno.h> 16145516Sdarrenr#include <sys/types.h> 17145516Sdarrenr#include <sys/param.h> 18145516Sdarrenr#include <sys/file.h> 19145516Sdarrenr#if !defined(_KERNEL) && !defined(__KERNEL__) 20145516Sdarrenr# include <stdio.h> 21145516Sdarrenr# include <stdlib.h> 22145516Sdarrenr# include <string.h> 23145516Sdarrenr# define _KERNEL 24145516Sdarrenr# ifdef __OpenBSD__ 25145516Sdarrenrstruct file; 26145516Sdarrenr# endif 27145516Sdarrenr# include <sys/uio.h> 28145516Sdarrenr# undef _KERNEL 29145516Sdarrenr#else 30145516Sdarrenr# include <sys/systm.h> 31145516Sdarrenr# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) 32145516Sdarrenr# include <sys/proc.h> 33145516Sdarrenr# endif 34145516Sdarrenr#endif 35145516Sdarrenr#include <sys/time.h> 36255332Scy#if defined(_KERNEL) && !defined(SOLARIS2) 37145516Sdarrenr# include <sys/mbuf.h> 38145516Sdarrenr#endif 39145516Sdarrenr#if defined(__SVR4) || defined(__svr4__) 40145516Sdarrenr# include <sys/byteorder.h> 41145516Sdarrenr# ifdef _KERNEL 42145516Sdarrenr# include <sys/dditypes.h> 43145516Sdarrenr# endif 44145516Sdarrenr# include <sys/stream.h> 45145516Sdarrenr# include <sys/kmem.h> 46145516Sdarrenr#endif 47145516Sdarrenr#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 48145516Sdarrenr# include <sys/malloc.h> 49145516Sdarrenr#endif 50145516Sdarrenr 51255332Scy#include <sys/socket.h> 52145516Sdarrenr#include <net/if.h> 53145516Sdarrenr#include <netinet/in.h> 54255332Scy#if !defined(_KERNEL) 55255332Scy# include "ipf.h" 56255332Scy#endif 57145516Sdarrenr 58145516Sdarrenr#include "netinet/ip_compat.h" 59145516Sdarrenr#include "netinet/ip_fil.h" 60145516Sdarrenr#include "netinet/ip_pool.h" 61255332Scy#include "netinet/radix_ipf.h" 62145516Sdarrenr 63145516Sdarrenr/* END OF INCLUDES */ 64145516Sdarrenr 65145516Sdarrenr#if !defined(lint) 66145516Sdarrenrstatic const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 67255332Scystatic const char rcsid[] = "@(#)$Id$"; 68145516Sdarrenr#endif 69145516Sdarrenr 70255332Scytypedef struct ipf_pool_softc_s { 71255332Scy void *ipf_radix; 72255332Scy ip_pool_t *ipf_pool_list[LOOKUP_POOL_SZ]; 73255332Scy ipf_pool_stat_t ipf_pool_stats; 74255332Scy ip_pool_node_t *ipf_node_explist; 75255332Scy} ipf_pool_softc_t; 76145516Sdarrenr 77145516Sdarrenr 78255332Scystatic void ipf_pool_clearnodes __P((ipf_main_softc_t *, ipf_pool_softc_t *, 79255332Scy ip_pool_t *)); 80255332Scystatic int ipf_pool_create __P((ipf_main_softc_t *, ipf_pool_softc_t *, iplookupop_t *)); 81255332Scystatic int ipf_pool_deref __P((ipf_main_softc_t *, void *, void *)); 82255332Scystatic int ipf_pool_destroy __P((ipf_main_softc_t *, ipf_pool_softc_t *, int, char *)); 83255332Scystatic void *ipf_pool_exists __P((ipf_pool_softc_t *, int, char *)); 84255332Scystatic void *ipf_pool_find __P((void *, int, char *)); 85255332Scystatic ip_pool_node_t *ipf_pool_findeq __P((ipf_pool_softc_t *, ip_pool_t *, 86255332Scy addrfamily_t *, addrfamily_t *)); 87255332Scystatic void ipf_pool_free __P((ipf_main_softc_t *, ipf_pool_softc_t *, 88255332Scy ip_pool_t *)); 89255332Scystatic int ipf_pool_insert_node __P((ipf_main_softc_t *, ipf_pool_softc_t *, 90255332Scy ip_pool_t *, struct ip_pool_node *)); 91255332Scystatic int ipf_pool_iter_deref __P((ipf_main_softc_t *, void *, int, int, void *)); 92255332Scystatic int ipf_pool_iter_next __P((ipf_main_softc_t *, void *, ipftoken_t *, 93255332Scy ipflookupiter_t *)); 94255332Scystatic size_t ipf_pool_flush __P((ipf_main_softc_t *, void *, iplookupflush_t *)); 95255332Scystatic int ipf_pool_node_add __P((ipf_main_softc_t *, void *, iplookupop_t *, 96255332Scy int)); 97255332Scystatic int ipf_pool_node_del __P((ipf_main_softc_t *, void *, iplookupop_t *, 98255332Scy int)); 99255332Scystatic void ipf_pool_node_deref __P((ipf_pool_softc_t *, ip_pool_node_t *)); 100255332Scystatic int ipf_pool_remove_node __P((ipf_main_softc_t *, ipf_pool_softc_t *, 101255332Scy ip_pool_t *, ip_pool_node_t *)); 102255332Scystatic int ipf_pool_search __P((ipf_main_softc_t *, void *, int, 103255332Scy void *, u_int)); 104255332Scystatic void *ipf_pool_soft_create __P((ipf_main_softc_t *)); 105255332Scystatic void ipf_pool_soft_destroy __P((ipf_main_softc_t *, void *)); 106255332Scystatic void ipf_pool_soft_fini __P((ipf_main_softc_t *, void *)); 107255332Scystatic int ipf_pool_soft_init __P((ipf_main_softc_t *, void *)); 108255332Scystatic int ipf_pool_stats_get __P((ipf_main_softc_t *, void *, iplookupop_t *)); 109255332Scystatic int ipf_pool_table_add __P((ipf_main_softc_t *, void *, iplookupop_t *)); 110255332Scystatic int ipf_pool_table_del __P((ipf_main_softc_t *, void *, iplookupop_t *)); 111255332Scystatic void *ipf_pool_select_add_ref __P((void *, int, char *)); 112255332Scystatic void ipf_pool_expire __P((ipf_main_softc_t *, void *)); 113170263Sdarrenr 114255332Scyipf_lookup_t ipf_pool_backend = { 115255332Scy IPLT_POOL, 116255332Scy ipf_pool_soft_create, 117255332Scy ipf_pool_soft_destroy, 118255332Scy ipf_pool_soft_init, 119255332Scy ipf_pool_soft_fini, 120255332Scy ipf_pool_search, 121255332Scy ipf_pool_flush, 122255332Scy ipf_pool_iter_deref, 123255332Scy ipf_pool_iter_next, 124255332Scy ipf_pool_node_add, 125255332Scy ipf_pool_node_del, 126255332Scy ipf_pool_stats_get, 127255332Scy ipf_pool_table_add, 128255332Scy ipf_pool_table_del, 129255332Scy ipf_pool_deref, 130255332Scy ipf_pool_find, 131255332Scy ipf_pool_select_add_ref, 132255332Scy NULL, 133255332Scy ipf_pool_expire, 134255332Scy NULL 135255332Scy}; 136145516Sdarrenr 137145516Sdarrenr 138145516Sdarrenr#ifdef TEST_POOL 139145516Sdarrenrvoid treeprint __P((ip_pool_t *)); 140145516Sdarrenr 141145516Sdarrenrint 142145516Sdarrenrmain(argc, argv) 143145516Sdarrenr int argc; 144145516Sdarrenr char *argv[]; 145145516Sdarrenr{ 146255332Scy ip_pool_node_t node; 147145516Sdarrenr addrfamily_t a, b; 148145516Sdarrenr iplookupop_t op; 149145516Sdarrenr ip_pool_t *ipo; 150145516Sdarrenr i6addr_t ip; 151145516Sdarrenr 152255332Scy RWLOCK_INIT(softc->ipf_poolrw, "poolrw"); 153255332Scy ipf_pool_init(); 154145516Sdarrenr 155145516Sdarrenr bzero((char *)&ip, sizeof(ip)); 156145516Sdarrenr bzero((char *)&op, sizeof(op)); 157255332Scy bzero((char *)&node, sizeof(node)); 158145516Sdarrenr strcpy(op.iplo_name, "0"); 159145516Sdarrenr 160255332Scy if (ipf_pool_create(&op) == 0) 161255332Scy ipo = ipf_pool_exists(0, "0"); 162145516Sdarrenr 163255332Scy node.ipn_addr.adf_family = AF_INET; 164145516Sdarrenr 165255332Scy node.ipn_addr.adf_addr.in4.s_addr = 0x0a010203; 166255332Scy node.ipn_mask.adf_addr.in4.s_addr = 0xffffffff; 167255332Scy node.ipn_info = 1; 168255332Scy ipf_pool_insert_node(ipo, &node); 169145516Sdarrenr 170255332Scy node.ipn_addr.adf_addr.in4.s_addr = 0x0a000000; 171255332Scy node.ipn_mask.adf_addr.in4.s_addr = 0xff000000; 172255332Scy node.ipn_info = 0; 173255332Scy ipf_pool_insert_node(ipo, &node); 174145516Sdarrenr 175255332Scy node.ipn_addr.adf_addr.in4.s_addr = 0x0a010100; 176255332Scy node.ipn_mask.adf_addr.in4.s_addr = 0xffffff00; 177255332Scy node.ipn_info = 1; 178255332Scy ipf_pool_insert_node(ipo, &node); 179145516Sdarrenr 180255332Scy node.ipn_addr.adf_addr.in4.s_addr = 0x0a010200; 181255332Scy node.ipn_mask.adf_addr.in4.s_addr = 0xffffff00; 182255332Scy node.ipn_info = 0; 183255332Scy ipf_pool_insert_node(ipo, &node); 184145516Sdarrenr 185255332Scy node.ipn_addr.adf_addr.in4.s_addr = 0x0a010000; 186255332Scy node.ipn_mask.adf_addr.in4.s_addr = 0xffff0000; 187255332Scy node.ipn_info = 1; 188255332Scy ipf_pool_insert_node(ipo, &node); 189255332Scy 190255332Scy node.ipn_addr.adf_addr.in4.s_addr = 0x0a01020f; 191255332Scy node.ipn_mask.adf_addr.in4.s_addr = 0xffffffff; 192255332Scy node.ipn_info = 1; 193255332Scy ipf_pool_insert_node(ipo, &node); 194145516Sdarrenr#ifdef DEBUG_POOL 195255332Scy treeprint(ipo); 196145516Sdarrenr#endif 197145516Sdarrenr ip.in4.s_addr = 0x0a00aabb; 198145516Sdarrenr printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 199255332Scy ipf_pool_search(ipo, 4, &ip, 1)); 200145516Sdarrenr 201145516Sdarrenr ip.in4.s_addr = 0x0a000001; 202145516Sdarrenr printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 203255332Scy ipf_pool_search(ipo, 4, &ip, 1)); 204145516Sdarrenr 205145516Sdarrenr ip.in4.s_addr = 0x0a000101; 206145516Sdarrenr printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 207255332Scy ipf_pool_search(ipo, 4, &ip, 1)); 208145516Sdarrenr 209145516Sdarrenr ip.in4.s_addr = 0x0a010001; 210145516Sdarrenr printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 211255332Scy ipf_pool_search(ipo, 4, &ip, 1)); 212145516Sdarrenr 213145516Sdarrenr ip.in4.s_addr = 0x0a010101; 214145516Sdarrenr printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 215255332Scy ipf_pool_search(ipo, 4, &ip, 1)); 216145516Sdarrenr 217145516Sdarrenr ip.in4.s_addr = 0x0a010201; 218145516Sdarrenr printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 219255332Scy ipf_pool_search(ipo, 4, &ip, 1)); 220145516Sdarrenr 221145516Sdarrenr ip.in4.s_addr = 0x0a010203; 222145516Sdarrenr printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 223255332Scy ipf_pool_search(ipo, 4, &ip, 1)); 224145516Sdarrenr 225145516Sdarrenr ip.in4.s_addr = 0x0a01020f; 226145516Sdarrenr printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 227255332Scy ipf_pool_search(ipo, 4, &ip, 1)); 228145516Sdarrenr 229145516Sdarrenr ip.in4.s_addr = 0x0b00aabb; 230145516Sdarrenr printf("search(%#x) = %d (-1)\n", ip.in4.s_addr, 231255332Scy ipf_pool_search(ipo, 4, &ip, 1)); 232145516Sdarrenr 233145516Sdarrenr#ifdef DEBUG_POOL 234255332Scy treeprint(ipo); 235145516Sdarrenr#endif 236145516Sdarrenr 237255332Scy ipf_pool_fini(); 238145516Sdarrenr 239145516Sdarrenr return 0; 240145516Sdarrenr} 241145516Sdarrenr 242145516Sdarrenr 243145516Sdarrenrvoid 244145516Sdarrenrtreeprint(ipo) 245255332Scy ip_pool_t *ipo; 246145516Sdarrenr{ 247145516Sdarrenr ip_pool_node_t *c; 248145516Sdarrenr 249145516Sdarrenr for (c = ipo->ipo_list; c != NULL; c = c->ipn_next) 250145516Sdarrenr printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n", 251145516Sdarrenr c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr, 252145516Sdarrenr c->ipn_mask.adf_addr.in4.s_addr, 253145516Sdarrenr c->ipn_info, c->ipn_hits); 254145516Sdarrenr} 255145516Sdarrenr#endif /* TEST_POOL */ 256145516Sdarrenr 257145516Sdarrenr 258145516Sdarrenr/* ------------------------------------------------------------------------ */ 259255332Scy/* Function: ipf_pool_soft_create */ 260255332Scy/* Returns: void * - NULL = failure, else pointer to local context */ 261255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 262255332Scy/* */ 263255332Scy/* Initialise the routing table data structures where required. */ 264255332Scy/* ------------------------------------------------------------------------ */ 265255332Scystatic void * 266255332Scyipf_pool_soft_create(softc) 267255332Scy ipf_main_softc_t *softc; 268255332Scy{ 269255332Scy ipf_pool_softc_t *softp; 270255332Scy 271255332Scy KMALLOC(softp, ipf_pool_softc_t *); 272255332Scy if (softp == NULL) { 273255332Scy IPFERROR(70032); 274255332Scy return NULL; 275255332Scy } 276255332Scy 277255332Scy bzero((char *)softp, sizeof(*softp)); 278255332Scy 279255332Scy softp->ipf_radix = ipf_rx_create(); 280255332Scy if (softp->ipf_radix == NULL) { 281255332Scy IPFERROR(70033); 282255332Scy KFREE(softp); 283255332Scy return NULL; 284255332Scy } 285255332Scy 286255332Scy return softp; 287255332Scy} 288255332Scy 289255332Scy 290255332Scy/* ------------------------------------------------------------------------ */ 291255332Scy/* Function: ipf_pool_soft_init */ 292145516Sdarrenr/* Returns: int - 0 = success, else error */ 293255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 294255332Scy/* arg(I) - pointer to local context to use */ 295145516Sdarrenr/* */ 296145516Sdarrenr/* Initialise the routing table data structures where required. */ 297145516Sdarrenr/* ------------------------------------------------------------------------ */ 298255332Scystatic int 299255332Scyipf_pool_soft_init(softc, arg) 300255332Scy ipf_main_softc_t *softc; 301255332Scy void *arg; 302145516Sdarrenr{ 303255332Scy ipf_pool_softc_t *softp = arg; 304145516Sdarrenr 305255332Scy ipf_rx_init(softp->ipf_radix); 306145516Sdarrenr 307145516Sdarrenr return 0; 308145516Sdarrenr} 309145516Sdarrenr 310145516Sdarrenr 311145516Sdarrenr/* ------------------------------------------------------------------------ */ 312255332Scy/* Function: ipf_pool_soft_fini */ 313255332Scy/* Returns: Nil */ 314255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 315255332Scy/* arg(I) - pointer to local context to use */ 316145516Sdarrenr/* Locks: WRITE(ipf_global) */ 317145516Sdarrenr/* */ 318145516Sdarrenr/* Clean up all the pool data structures allocated and call the cleanup */ 319255332Scy/* function for the radix tree that supports the pools. ipf_pool_destroy is */ 320145516Sdarrenr/* used to delete the pools one by one to ensure they're properly freed up. */ 321145516Sdarrenr/* ------------------------------------------------------------------------ */ 322255332Scystatic void 323255332Scyipf_pool_soft_fini(softc, arg) 324255332Scy ipf_main_softc_t *softc; 325255332Scy void *arg; 326145516Sdarrenr{ 327255332Scy ipf_pool_softc_t *softp = arg; 328145516Sdarrenr ip_pool_t *p, *q; 329145516Sdarrenr int i; 330145516Sdarrenr 331255332Scy softc = arg; 332255332Scy 333255332Scy for (i = -1; i <= IPL_LOGMAX; i++) { 334255332Scy for (q = softp->ipf_pool_list[i + 1]; (p = q) != NULL; ) { 335145516Sdarrenr q = p->ipo_next; 336255332Scy (void) ipf_pool_destroy(softc, arg, i, p->ipo_name); 337145516Sdarrenr } 338145516Sdarrenr } 339255332Scy} 340145516Sdarrenr 341255332Scy 342255332Scy/* ------------------------------------------------------------------------ */ 343255332Scy/* Function: ipf_pool_soft_destroy */ 344255332Scy/* Returns: Nil */ 345255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 346255332Scy/* arg(I) - pointer to local context to use */ 347255332Scy/* */ 348255332Scy/* Clean up the pool by free'ing the radix tree associated with it and free */ 349255332Scy/* up the pool context too. */ 350255332Scy/* ------------------------------------------------------------------------ */ 351255332Scystatic void 352255332Scyipf_pool_soft_destroy(softc, arg) 353255332Scy ipf_main_softc_t *softc; 354255332Scy void *arg; 355255332Scy{ 356255332Scy ipf_pool_softc_t *softp = arg; 357255332Scy 358255332Scy ipf_rx_destroy(softp->ipf_radix); 359255332Scy 360255332Scy KFREE(softp); 361255332Scy} 362255332Scy 363255332Scy 364255332Scy/* ------------------------------------------------------------------------ */ 365255332Scy/* Function: ipf_pool_node_add */ 366255332Scy/* Returns: int - 0 = success, else error */ 367255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 368255332Scy/* arg(I) - pointer to local context to use */ 369255332Scy/* op(I) - pointer to lookup operatin data */ 370255332Scy/* */ 371255332Scy/* When adding a new node, a check is made to ensure that the address/mask */ 372255332Scy/* pair supplied has been appropriately prepared by applying the mask to */ 373255332Scy/* the address prior to calling for the pair to be added. */ 374255332Scy/* ------------------------------------------------------------------------ */ 375255332Scystatic int 376255332Scyipf_pool_node_add(softc, arg, op, uid) 377255332Scy ipf_main_softc_t *softc; 378255332Scy void *arg; 379255332Scy iplookupop_t *op; 380255332Scy int uid; 381255332Scy{ 382255332Scy ip_pool_node_t node, *m; 383255332Scy ip_pool_t *p; 384255332Scy int err; 385255332Scy 386255332Scy if (op->iplo_size != sizeof(node)) { 387255332Scy IPFERROR(70014); 388255332Scy return EINVAL; 389255332Scy } 390255332Scy 391255332Scy err = COPYIN(op->iplo_struct, &node, sizeof(node)); 392255332Scy if (err != 0) { 393255332Scy IPFERROR(70015); 394255332Scy return EFAULT; 395255332Scy } 396255332Scy 397255332Scy p = ipf_pool_find(arg, op->iplo_unit, op->iplo_name); 398255332Scy if (p == NULL) { 399255332Scy IPFERROR(70017); 400255332Scy return ESRCH; 401255332Scy } 402255332Scy 403255332Scy if (node.ipn_addr.adf_family == AF_INET) { 404255332Scy if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) + 405255332Scy sizeof(struct in_addr)) { 406255332Scy IPFERROR(70028); 407255332Scy return EINVAL; 408255332Scy } 409255332Scy } 410255332Scy#ifdef USE_INET6 411255332Scy else if (node.ipn_addr.adf_family == AF_INET6) { 412255332Scy if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) + 413255332Scy sizeof(struct in6_addr)) { 414255332Scy IPFERROR(70034); 415255332Scy return EINVAL; 416255332Scy } 417255332Scy } 418145516Sdarrenr#endif 419255332Scy if (node.ipn_mask.adf_len != node.ipn_addr.adf_len) { 420255332Scy IPFERROR(70029); 421255332Scy return EINVAL; 422255332Scy } 423255332Scy 424255332Scy /* 425255332Scy * Check that the address/mask pair works. 426255332Scy */ 427255332Scy if (node.ipn_addr.adf_family == AF_INET) { 428255332Scy if ((node.ipn_addr.adf_addr.in4.s_addr & 429255332Scy node.ipn_mask.adf_addr.in4.s_addr) != 430255332Scy node.ipn_addr.adf_addr.in4.s_addr) { 431255332Scy IPFERROR(70035); 432255332Scy return EINVAL; 433255332Scy } 434255332Scy } 435255332Scy#ifdef USE_INET6 436255332Scy else if (node.ipn_addr.adf_family == AF_INET6) { 437255332Scy if (IP6_MASKNEQ(&node.ipn_addr.adf_addr.in6, 438255332Scy &node.ipn_mask.adf_addr.in6, 439255332Scy &node.ipn_addr.adf_addr.in6)) { 440255332Scy IPFERROR(70036); 441255332Scy return EINVAL; 442255332Scy } 443255332Scy } 444255332Scy#endif 445255332Scy 446255332Scy /* 447255332Scy * add an entry to a pool - return an error if it already 448255332Scy * exists remove an entry from a pool - if it exists 449255332Scy * - in both cases, the pool *must* exist! 450255332Scy */ 451255332Scy m = ipf_pool_findeq(arg, p, &node.ipn_addr, &node.ipn_mask); 452255332Scy if (m != NULL) { 453255332Scy IPFERROR(70018); 454255332Scy return EEXIST; 455255332Scy } 456255332Scy err = ipf_pool_insert_node(softc, arg, p, &node); 457255332Scy 458255332Scy return err; 459145516Sdarrenr} 460145516Sdarrenr 461145516Sdarrenr 462145516Sdarrenr/* ------------------------------------------------------------------------ */ 463255332Scy/* Function: ipf_pool_node_del */ 464255332Scy/* Returns: int - 0 = success, else error */ 465255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 466255332Scy/* arg(I) - pointer to local context to use */ 467255332Scy/* op(I) - pointer to lookup operatin data */ 468145516Sdarrenr/* */ 469255332Scy/* ------------------------------------------------------------------------ */ 470255332Scystatic int 471255332Scyipf_pool_node_del(softc, arg, op, uid) 472255332Scy ipf_main_softc_t *softc; 473255332Scy void *arg; 474255332Scy iplookupop_t *op; 475255332Scy int uid; 476255332Scy{ 477255332Scy ip_pool_node_t node, *m; 478255332Scy ip_pool_t *p; 479255332Scy int err; 480255332Scy 481255332Scy 482255332Scy if (op->iplo_size != sizeof(node)) { 483255332Scy IPFERROR(70019); 484255332Scy return EINVAL; 485255332Scy } 486255332Scy node.ipn_uid = uid; 487255332Scy 488255332Scy err = COPYIN(op->iplo_struct, &node, sizeof(node)); 489255332Scy if (err != 0) { 490255332Scy IPFERROR(70020); 491255332Scy return EFAULT; 492255332Scy } 493255332Scy 494255332Scy if (node.ipn_addr.adf_family == AF_INET) { 495255332Scy if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) + 496255332Scy sizeof(struct in_addr)) { 497255332Scy IPFERROR(70030); 498255332Scy return EINVAL; 499255332Scy } 500255332Scy } 501255332Scy#ifdef USE_INET6 502255332Scy else if (node.ipn_addr.adf_family == AF_INET6) { 503255332Scy if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) + 504255332Scy sizeof(struct in6_addr)) { 505255332Scy IPFERROR(70037); 506255332Scy return EINVAL; 507255332Scy } 508255332Scy } 509255332Scy#endif 510255332Scy if (node.ipn_mask.adf_len != node.ipn_addr.adf_len) { 511255332Scy IPFERROR(70031); 512255332Scy return EINVAL; 513255332Scy } 514255332Scy 515255332Scy p = ipf_pool_find(arg, op->iplo_unit, op->iplo_name); 516255332Scy if (p == NULL) { 517255332Scy IPFERROR(70021); 518255332Scy return ESRCH; 519255332Scy } 520255332Scy 521255332Scy m = ipf_pool_findeq(arg, p, &node.ipn_addr, &node.ipn_mask); 522255332Scy if (m == NULL) { 523255332Scy IPFERROR(70022); 524255332Scy return ENOENT; 525255332Scy } 526255332Scy 527255332Scy if ((uid != 0) && (uid != m->ipn_uid)) { 528255332Scy IPFERROR(70024); 529255332Scy return EACCES; 530255332Scy } 531255332Scy 532255332Scy err = ipf_pool_remove_node(softc, arg, p, m); 533255332Scy 534255332Scy return err; 535255332Scy} 536255332Scy 537255332Scy 538255332Scy/* ------------------------------------------------------------------------ */ 539255332Scy/* Function: ipf_pool_table_add */ 540255332Scy/* Returns: int - 0 = success, else error */ 541255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 542255332Scy/* arg(I) - pointer to local context to use */ 543255332Scy/* op(I) - pointer to lookup operatin data */ 544255332Scy/* */ 545255332Scy/* ------------------------------------------------------------------------ */ 546255332Scystatic int 547255332Scyipf_pool_table_add(softc, arg, op) 548255332Scy ipf_main_softc_t *softc; 549255332Scy void *arg; 550255332Scy iplookupop_t *op; 551255332Scy{ 552255332Scy int err; 553255332Scy 554255332Scy if (((op->iplo_arg & LOOKUP_ANON) == 0) && 555255332Scy (ipf_pool_find(arg, op->iplo_unit, op->iplo_name) != NULL)) { 556255332Scy IPFERROR(70023); 557255332Scy err = EEXIST; 558255332Scy } else { 559255332Scy err = ipf_pool_create(softc, arg, op); 560255332Scy } 561255332Scy 562255332Scy return err; 563255332Scy} 564255332Scy 565255332Scy 566255332Scy/* ------------------------------------------------------------------------ */ 567255332Scy/* Function: ipf_pool_table_del */ 568255332Scy/* Returns: int - 0 = success, else error */ 569255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 570255332Scy/* arg(I) - pointer to local context to use */ 571255332Scy/* op(I) - pointer to lookup operatin data */ 572255332Scy/* */ 573255332Scy/* ------------------------------------------------------------------------ */ 574255332Scystatic int 575255332Scyipf_pool_table_del(softc, arg, op) 576255332Scy ipf_main_softc_t *softc; 577255332Scy void *arg; 578255332Scy iplookupop_t *op; 579255332Scy{ 580255332Scy return ipf_pool_destroy(softc, arg, op->iplo_unit, op->iplo_name); 581255332Scy} 582255332Scy 583255332Scy 584255332Scy/* ------------------------------------------------------------------------ */ 585255332Scy/* Function: ipf_pool_statistics */ 586255332Scy/* Returns: int - 0 = success, else error */ 587255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 588255332Scy/* arg(I) - pointer to local context to use */ 589255332Scy/* op(I) - pointer to lookup operatin data */ 590255332Scy/* */ 591145516Sdarrenr/* Copy the current statistics out into user space, collecting pool list */ 592145516Sdarrenr/* pointers as appropriate for later use. */ 593145516Sdarrenr/* ------------------------------------------------------------------------ */ 594255332Scystatic int 595255332Scyipf_pool_stats_get(softc, arg, op) 596255332Scy ipf_main_softc_t *softc; 597255332Scy void *arg; 598255332Scy iplookupop_t *op; 599145516Sdarrenr{ 600255332Scy ipf_pool_softc_t *softp = arg; 601255332Scy ipf_pool_stat_t stats; 602145516Sdarrenr int unit, i, err = 0; 603145516Sdarrenr 604255332Scy if (op->iplo_size != sizeof(ipf_pool_stat_t)) { 605255332Scy IPFERROR(70001); 606145516Sdarrenr return EINVAL; 607255332Scy } 608145516Sdarrenr 609255332Scy bcopy((char *)&softp->ipf_pool_stats, (char *)&stats, sizeof(stats)); 610145516Sdarrenr unit = op->iplo_unit; 611145516Sdarrenr if (unit == IPL_LOGALL) { 612255332Scy for (i = 0; i <= LOOKUP_POOL_MAX; i++) 613255332Scy stats.ipls_list[i] = softp->ipf_pool_list[i]; 614255332Scy } else if (unit >= 0 && unit <= IPL_LOGMAX) { 615255332Scy unit++; /* -1 => 0 */ 616145516Sdarrenr if (op->iplo_name[0] != '\0') 617255332Scy stats.ipls_list[unit] = ipf_pool_exists(softp, unit - 1, 618255332Scy op->iplo_name); 619145516Sdarrenr else 620255332Scy stats.ipls_list[unit] = softp->ipf_pool_list[unit]; 621255332Scy } else { 622255332Scy IPFERROR(70025); 623145516Sdarrenr err = EINVAL; 624255332Scy } 625255332Scy if (err == 0) { 626145516Sdarrenr err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); 627255332Scy if (err != 0) { 628255332Scy IPFERROR(70026); 629255332Scy return EFAULT; 630255332Scy } 631255332Scy } 632255332Scy return 0; 633145516Sdarrenr} 634145516Sdarrenr 635145516Sdarrenr 636145516Sdarrenr/* ------------------------------------------------------------------------ */ 637255332Scy/* Function: ipf_pool_exists */ 638255332Scy/* Returns: int - 0 = success, else error */ 639255332Scy/* Parameters: softp(I) - pointer to soft context pool information */ 640255332Scy/* unit(I) - ipfilter device to which we are working on */ 641255332Scy/* name(I) - name of the pool */ 642145516Sdarrenr/* */ 643145516Sdarrenr/* Find a matching pool inside the collection of pools for a particular */ 644145516Sdarrenr/* device, indicated by the unit number. */ 645145516Sdarrenr/* ------------------------------------------------------------------------ */ 646255332Scystatic void * 647255332Scyipf_pool_exists(softp, unit, name) 648255332Scy ipf_pool_softc_t *softp; 649255332Scy int unit; 650255332Scy char *name; 651145516Sdarrenr{ 652145516Sdarrenr ip_pool_t *p; 653255332Scy int i; 654145516Sdarrenr 655255332Scy if (unit == IPL_LOGALL) { 656255332Scy for (i = 0; i <= LOOKUP_POOL_MAX; i++) { 657255332Scy for (p = softp->ipf_pool_list[i]; p != NULL; 658255332Scy p = p->ipo_next) { 659255332Scy if (strncmp(p->ipo_name, name, 660255332Scy sizeof(p->ipo_name)) == 0) 661255332Scy break; 662255332Scy } 663255332Scy if (p != NULL) 664255332Scy break; 665255332Scy } 666255332Scy } else { 667255332Scy for (p = softp->ipf_pool_list[unit + 1]; p != NULL; 668255332Scy p = p->ipo_next) 669255332Scy if (strncmp(p->ipo_name, name, 670255332Scy sizeof(p->ipo_name)) == 0) 671255332Scy break; 672255332Scy } 673145516Sdarrenr return p; 674145516Sdarrenr} 675145516Sdarrenr 676145516Sdarrenr 677145516Sdarrenr/* ------------------------------------------------------------------------ */ 678255332Scy/* Function: ipf_pool_find */ 679255332Scy/* Returns: int - 0 = success, else error */ 680255332Scy/* Parameters: arg(I) - pointer to local context to use */ 681255332Scy/* unit(I) - ipfilter device to which we are working on */ 682255332Scy/* name(I) - name of the pool */ 683170263Sdarrenr/* */ 684170263Sdarrenr/* Find a matching pool inside the collection of pools for a particular */ 685170263Sdarrenr/* device, indicated by the unit number. If it is marked for deletion then */ 686170263Sdarrenr/* pretend it does not exist. */ 687170263Sdarrenr/* ------------------------------------------------------------------------ */ 688255332Scystatic void * 689255332Scyipf_pool_find(arg, unit, name) 690255332Scy void *arg; 691255332Scy int unit; 692255332Scy char *name; 693170263Sdarrenr{ 694255332Scy ipf_pool_softc_t *softp = arg; 695170263Sdarrenr ip_pool_t *p; 696170263Sdarrenr 697255332Scy p = ipf_pool_exists(softp, unit, name); 698170263Sdarrenr if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE)) 699170263Sdarrenr return NULL; 700170263Sdarrenr 701170263Sdarrenr return p; 702170263Sdarrenr} 703170263Sdarrenr 704170263Sdarrenr 705170263Sdarrenr/* ------------------------------------------------------------------------ */ 706255332Scy/* Function: ipf_pool_select_add_ref */ 707255332Scy/* Returns: int - 0 = success, else error */ 708255332Scy/* Parameters: arg(I) - pointer to local context to use */ 709255332Scy/* unit(I) - ipfilter device to which we are working on */ 710255332Scy/* name(I) - name of the pool */ 711255332Scy/* */ 712255332Scy/* ------------------------------------------------------------------------ */ 713255332Scystatic void * 714255332Scyipf_pool_select_add_ref(arg, unit, name) 715255332Scy void *arg; 716255332Scy int unit; 717255332Scy char *name; 718255332Scy{ 719255332Scy ip_pool_t *p; 720255332Scy 721255332Scy p = ipf_pool_find(arg, -1, name); 722255332Scy if (p == NULL) 723255332Scy p = ipf_pool_find(arg, unit, name); 724255332Scy if (p != NULL) { 725255332Scy ATOMIC_INC32(p->ipo_ref); 726255332Scy } 727255332Scy return p; 728255332Scy} 729255332Scy 730255332Scy 731255332Scy/* ------------------------------------------------------------------------ */ 732255332Scy/* Function: ipf_pool_findeq */ 733145516Sdarrenr/* Returns: int - 0 = success, else error */ 734255332Scy/* Parameters: softp(I) - pointer to soft context pool information */ 735255332Scy/* ipo(I) - pointer to the pool getting the new node. */ 736255332Scy/* addr(I) - pointer to address information to match on */ 737255332Scy/* mask(I) - pointer to the address mask to match */ 738145516Sdarrenr/* */ 739145516Sdarrenr/* Searches for an exact match of an entry in the pool. */ 740145516Sdarrenr/* ------------------------------------------------------------------------ */ 741255332Scyextern void printhostmask __P((int, u_32_t *, u_32_t *)); 742255332Scystatic ip_pool_node_t * 743255332Scyipf_pool_findeq(softp, ipo, addr, mask) 744255332Scy ipf_pool_softc_t *softp; 745255332Scy ip_pool_t *ipo; 746255332Scy addrfamily_t *addr, *mask; 747145516Sdarrenr{ 748255332Scy ipf_rdx_node_t *n; 749145516Sdarrenr 750255332Scy n = ipo->ipo_head->lookup(ipo->ipo_head, addr, mask); 751145516Sdarrenr return (ip_pool_node_t *)n; 752145516Sdarrenr} 753145516Sdarrenr 754145516Sdarrenr 755145516Sdarrenr/* ------------------------------------------------------------------------ */ 756255332Scy/* Function: ipf_pool_search */ 757145516Sdarrenr/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 758255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 759255332Scy/* tptr(I) - pointer to the pool to search */ 760145516Sdarrenr/* version(I) - IP protocol version (4 or 6) */ 761145516Sdarrenr/* dptr(I) - pointer to address information */ 762255332Scy/* bytes(I) - length of packet */ 763145516Sdarrenr/* */ 764145516Sdarrenr/* Search the pool for a given address and return a search result. */ 765145516Sdarrenr/* ------------------------------------------------------------------------ */ 766255332Scystatic int 767255332Scyipf_pool_search(softc, tptr, ipversion, dptr, bytes) 768255332Scy ipf_main_softc_t *softc; 769255332Scy void *tptr; 770255332Scy int ipversion; 771255332Scy void *dptr; 772255332Scy u_int bytes; 773145516Sdarrenr{ 774255332Scy ipf_rdx_node_t *rn; 775145516Sdarrenr ip_pool_node_t *m; 776145516Sdarrenr i6addr_t *addr; 777145516Sdarrenr addrfamily_t v; 778145516Sdarrenr ip_pool_t *ipo; 779145516Sdarrenr int rv; 780145516Sdarrenr 781145516Sdarrenr ipo = tptr; 782145516Sdarrenr if (ipo == NULL) 783145516Sdarrenr return -1; 784145516Sdarrenr 785145516Sdarrenr rv = 1; 786145516Sdarrenr m = NULL; 787145516Sdarrenr addr = (i6addr_t *)dptr; 788145516Sdarrenr bzero(&v, sizeof(v)); 789145516Sdarrenr 790170263Sdarrenr if (ipversion == 4) { 791255332Scy v.adf_family = AF_INET; 792255332Scy v.adf_len = offsetof(addrfamily_t, adf_addr) + 793255332Scy sizeof(struct in_addr); 794145516Sdarrenr v.adf_addr.in4 = addr->in4; 795145516Sdarrenr#ifdef USE_INET6 796170263Sdarrenr } else if (ipversion == 6) { 797255332Scy v.adf_family = AF_INET6; 798255332Scy v.adf_len = offsetof(addrfamily_t, adf_addr) + 799255332Scy sizeof(struct in6_addr); 800145516Sdarrenr v.adf_addr.in6 = addr->in6; 801145516Sdarrenr#endif 802145516Sdarrenr } else 803145516Sdarrenr return -1; 804145516Sdarrenr 805255332Scy READ_ENTER(&softc->ipf_poolrw); 806145516Sdarrenr 807255332Scy rn = ipo->ipo_head->matchaddr(ipo->ipo_head, &v); 808145516Sdarrenr 809255332Scy if ((rn != NULL) && (rn->root == 0)) { 810145516Sdarrenr m = (ip_pool_node_t *)rn; 811145516Sdarrenr ipo->ipo_hits++; 812255332Scy m->ipn_bytes += bytes; 813145516Sdarrenr m->ipn_hits++; 814145516Sdarrenr rv = m->ipn_info; 815145516Sdarrenr } 816255332Scy RWLOCK_EXIT(&softc->ipf_poolrw); 817145516Sdarrenr return rv; 818145516Sdarrenr} 819145516Sdarrenr 820145516Sdarrenr 821145516Sdarrenr/* ------------------------------------------------------------------------ */ 822255332Scy/* Function: ipf_pool_insert_node */ 823255332Scy/* Returns: int - 0 = success, else error */ 824255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 825255332Scy/* softp(I) - pointer to soft context pool information */ 826255332Scy/* ipo(I) - pointer to the pool getting the new node. */ 827255332Scy/* node(I) - structure with address/mask to add */ 828255332Scy/* Locks: WRITE(ipf_poolrw) */ 829145516Sdarrenr/* */ 830145516Sdarrenr/* Add another node to the pool given by ipo. The three parameters passed */ 831145516Sdarrenr/* in (addr, mask, info) shold all be stored in the node. */ 832145516Sdarrenr/* ------------------------------------------------------------------------ */ 833255332Scystatic int 834255332Scyipf_pool_insert_node(softc, softp, ipo, node) 835255332Scy ipf_main_softc_t *softc; 836255332Scy ipf_pool_softc_t *softp; 837255332Scy ip_pool_t *ipo; 838255332Scy struct ip_pool_node *node; 839145516Sdarrenr{ 840255332Scy ipf_rdx_node_t *rn; 841145516Sdarrenr ip_pool_node_t *x; 842145516Sdarrenr 843255332Scy if ((node->ipn_addr.adf_len > sizeof(*rn)) || 844255332Scy (node->ipn_addr.adf_len < 4)) { 845255332Scy IPFERROR(70003); 846255332Scy return EINVAL; 847255332Scy } 848255332Scy 849255332Scy if ((node->ipn_mask.adf_len > sizeof(*rn)) || 850255332Scy (node->ipn_mask.adf_len < 4)) { 851255332Scy IPFERROR(70004); 852255332Scy return EINVAL; 853255332Scy } 854255332Scy 855145516Sdarrenr KMALLOC(x, ip_pool_node_t *); 856145516Sdarrenr if (x == NULL) { 857255332Scy IPFERROR(70002); 858145516Sdarrenr return ENOMEM; 859145516Sdarrenr } 860145516Sdarrenr 861255332Scy *x = *node; 862255332Scy bzero((char *)x->ipn_nodes, sizeof(x->ipn_nodes)); 863255332Scy x->ipn_owner = ipo; 864255332Scy x->ipn_hits = 0; 865255332Scy x->ipn_next = NULL; 866255332Scy x->ipn_pnext = NULL; 867255332Scy x->ipn_dnext = NULL; 868255332Scy x->ipn_pdnext = NULL; 869145516Sdarrenr 870255332Scy if (x->ipn_die != 0) { 871255332Scy /* 872255332Scy * If the new node has a given expiration time, insert it 873255332Scy * into the list of expiring nodes with the ones to be 874255332Scy * removed first added to the front of the list. The 875255332Scy * insertion is O(n) but it is kept sorted for quick scans 876255332Scy * at expiration interval checks. 877255332Scy */ 878255332Scy ip_pool_node_t *n; 879145516Sdarrenr 880255332Scy x->ipn_die = softc->ipf_ticks + IPF_TTLVAL(x->ipn_die); 881255332Scy for (n = softp->ipf_node_explist; n != NULL; n = n->ipn_dnext) { 882255332Scy if (x->ipn_die < n->ipn_die) 883255332Scy break; 884255332Scy if (n->ipn_dnext == NULL) { 885255332Scy /* 886255332Scy * We've got to the last node and everything 887255332Scy * wanted to be expired before this new node, 888255332Scy * so we have to tack it on the end... 889255332Scy */ 890255332Scy n->ipn_dnext = x; 891255332Scy x->ipn_pdnext = &n->ipn_dnext; 892255332Scy n = NULL; 893255332Scy break; 894255332Scy } 895255332Scy } 896145516Sdarrenr 897255332Scy if (softp->ipf_node_explist == NULL) { 898255332Scy softp->ipf_node_explist = x; 899255332Scy x->ipn_pdnext = &softp->ipf_node_explist; 900255332Scy } else if (n != NULL) { 901255332Scy x->ipn_dnext = n; 902255332Scy x->ipn_pdnext = n->ipn_pdnext; 903255332Scy n->ipn_pdnext = &x->ipn_dnext; 904255332Scy } 905255332Scy } 906255332Scy 907255332Scy rn = ipo->ipo_head->addaddr(ipo->ipo_head, &x->ipn_addr, &x->ipn_mask, 908255332Scy x->ipn_nodes); 909145516Sdarrenr#ifdef DEBUG_POOL 910145516Sdarrenr printf("Added %p at %p\n", x, rn); 911145516Sdarrenr#endif 912145516Sdarrenr 913145516Sdarrenr if (rn == NULL) { 914145516Sdarrenr KFREE(x); 915255332Scy IPFERROR(70005); 916145516Sdarrenr return ENOMEM; 917145516Sdarrenr } 918145516Sdarrenr 919170263Sdarrenr x->ipn_ref = 1; 920255332Scy x->ipn_pnext = ipo->ipo_tail; 921255332Scy *ipo->ipo_tail = x; 922255332Scy ipo->ipo_tail = &x->ipn_next; 923145516Sdarrenr 924255332Scy softp->ipf_pool_stats.ipls_nodes++; 925145516Sdarrenr 926145516Sdarrenr return 0; 927145516Sdarrenr} 928145516Sdarrenr 929145516Sdarrenr 930145516Sdarrenr/* ------------------------------------------------------------------------ */ 931255332Scy/* Function: ipf_pool_create */ 932255332Scy/* Returns: int - 0 = success, else error */ 933255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 934255332Scy/* softp(I) - pointer to soft context pool information */ 935255332Scy/* op(I) - pointer to iplookup struct with call details */ 936255332Scy/* Locks: WRITE(ipf_poolrw) */ 937145516Sdarrenr/* */ 938145516Sdarrenr/* Creates a new group according to the paramters passed in via the */ 939145516Sdarrenr/* iplookupop structure. Does not check to see if the group already exists */ 940145516Sdarrenr/* when being inserted - assume this has already been done. If the pool is */ 941145516Sdarrenr/* marked as being anonymous, give it a new, unique, identifier. Call any */ 942145516Sdarrenr/* other functions required to initialise the structure. */ 943170263Sdarrenr/* */ 944170263Sdarrenr/* If the structure is flagged for deletion then reset the flag and return, */ 945170263Sdarrenr/* as this likely means we've tried to free a pool that is in use (flush) */ 946170263Sdarrenr/* and now want to repopulate it with "new" data. */ 947145516Sdarrenr/* ------------------------------------------------------------------------ */ 948255332Scystatic int 949255332Scyipf_pool_create(softc, softp, op) 950255332Scy ipf_main_softc_t *softc; 951255332Scy ipf_pool_softc_t *softp; 952255332Scy iplookupop_t *op; 953145516Sdarrenr{ 954145516Sdarrenr char name[FR_GROUPLEN]; 955145516Sdarrenr int poolnum, unit; 956145516Sdarrenr ip_pool_t *h; 957145516Sdarrenr 958170263Sdarrenr unit = op->iplo_unit; 959145516Sdarrenr 960172771Sdarrenr if ((op->iplo_arg & LOOKUP_ANON) == 0) { 961255332Scy h = ipf_pool_exists(softp, unit, op->iplo_name); 962172771Sdarrenr if (h != NULL) { 963255332Scy if ((h->ipo_flags & IPOOL_DELETE) == 0) { 964255332Scy IPFERROR(70006); 965172771Sdarrenr return EEXIST; 966255332Scy } 967170263Sdarrenr h->ipo_flags &= ~IPOOL_DELETE; 968170263Sdarrenr return 0; 969170263Sdarrenr } 970172771Sdarrenr } 971170263Sdarrenr 972172771Sdarrenr KMALLOC(h, ip_pool_t *); 973255332Scy if (h == NULL) { 974255332Scy IPFERROR(70007); 975172771Sdarrenr return ENOMEM; 976255332Scy } 977172771Sdarrenr bzero(h, sizeof(*h)); 978172771Sdarrenr 979255332Scy if (ipf_rx_inithead(softp->ipf_radix, &h->ipo_head) != 0) { 980172771Sdarrenr KFREE(h); 981255332Scy IPFERROR(70008); 982172771Sdarrenr return ENOMEM; 983145516Sdarrenr } 984145516Sdarrenr 985170263Sdarrenr if ((op->iplo_arg & LOOKUP_ANON) != 0) { 986145516Sdarrenr ip_pool_t *p; 987145516Sdarrenr 988170263Sdarrenr h->ipo_flags |= IPOOL_ANON; 989170263Sdarrenr poolnum = LOOKUP_ANON; 990145516Sdarrenr 991145516Sdarrenr#if defined(SNPRINTF) && defined(_KERNEL) 992145516Sdarrenr SNPRINTF(name, sizeof(name), "%x", poolnum); 993145516Sdarrenr#else 994145516Sdarrenr (void)sprintf(name, "%x", poolnum); 995145516Sdarrenr#endif 996145516Sdarrenr 997255332Scy for (p = softp->ipf_pool_list[unit + 1]; p != NULL; ) { 998145516Sdarrenr if (strncmp(name, p->ipo_name, 999145516Sdarrenr sizeof(p->ipo_name)) == 0) { 1000145516Sdarrenr poolnum++; 1001145516Sdarrenr#if defined(SNPRINTF) && defined(_KERNEL) 1002145516Sdarrenr SNPRINTF(name, sizeof(name), "%x", poolnum); 1003145516Sdarrenr#else 1004145516Sdarrenr (void)sprintf(name, "%x", poolnum); 1005145516Sdarrenr#endif 1006255332Scy p = softp->ipf_pool_list[unit + 1]; 1007145516Sdarrenr } else 1008145516Sdarrenr p = p->ipo_next; 1009145516Sdarrenr } 1010145516Sdarrenr 1011145516Sdarrenr (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name)); 1012153872Sguido (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name)); 1013145516Sdarrenr } else { 1014170263Sdarrenr (void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); 1015145516Sdarrenr } 1016145516Sdarrenr 1017255332Scy h->ipo_radix = softp->ipf_radix; 1018172771Sdarrenr h->ipo_ref = 1; 1019172771Sdarrenr h->ipo_list = NULL; 1020255332Scy h->ipo_tail = &h->ipo_list; 1021172771Sdarrenr h->ipo_unit = unit; 1022255332Scy h->ipo_next = softp->ipf_pool_list[unit + 1]; 1023255332Scy if (softp->ipf_pool_list[unit + 1] != NULL) 1024255332Scy softp->ipf_pool_list[unit + 1]->ipo_pnext = &h->ipo_next; 1025255332Scy h->ipo_pnext = &softp->ipf_pool_list[unit + 1]; 1026255332Scy softp->ipf_pool_list[unit + 1] = h; 1027145516Sdarrenr 1028255332Scy softp->ipf_pool_stats.ipls_pools++; 1029145516Sdarrenr 1030145516Sdarrenr return 0; 1031145516Sdarrenr} 1032145516Sdarrenr 1033145516Sdarrenr 1034145516Sdarrenr/* ------------------------------------------------------------------------ */ 1035255332Scy/* Function: ipf_pool_remove_node */ 1036255332Scy/* Returns: int - 0 = success, else error */ 1037255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1038255332Scy/* ipo(I) - pointer to the pool to remove the node from. */ 1039255332Scy/* ipe(I) - address being deleted as a node */ 1040255332Scy/* Locks: WRITE(ipf_poolrw) */ 1041145516Sdarrenr/* */ 1042170263Sdarrenr/* Remove a node from the pool given by ipo. */ 1043145516Sdarrenr/* ------------------------------------------------------------------------ */ 1044255332Scystatic int 1045255332Scyipf_pool_remove_node(softc, softp, ipo, ipe) 1046255332Scy ipf_main_softc_t *softc; 1047255332Scy ipf_pool_softc_t *softp; 1048255332Scy ip_pool_t *ipo; 1049255332Scy ip_pool_node_t *ipe; 1050145516Sdarrenr{ 1051255332Scy void *ptr; 1052145516Sdarrenr 1053255332Scy if (ipo->ipo_tail == &ipe->ipn_next) 1054255332Scy ipo->ipo_tail = ipe->ipn_pnext; 1055255332Scy 1056170263Sdarrenr if (ipe->ipn_pnext != NULL) 1057170263Sdarrenr *ipe->ipn_pnext = ipe->ipn_next; 1058170263Sdarrenr if (ipe->ipn_next != NULL) 1059170263Sdarrenr ipe->ipn_next->ipn_pnext = ipe->ipn_pnext; 1060145516Sdarrenr 1061255332Scy if (ipe->ipn_pdnext != NULL) 1062255332Scy *ipe->ipn_pdnext = ipe->ipn_dnext; 1063255332Scy if (ipe->ipn_dnext != NULL) 1064255332Scy ipe->ipn_dnext->ipn_pdnext = ipe->ipn_pdnext; 1065145516Sdarrenr 1066255332Scy ptr = ipo->ipo_head->deladdr(ipo->ipo_head, &ipe->ipn_addr, 1067255332Scy &ipe->ipn_mask); 1068145516Sdarrenr 1069255332Scy if (ptr != NULL) { 1070255332Scy ipf_pool_node_deref(softp, ipe); 1071255332Scy return 0; 1072255332Scy } 1073255332Scy IPFERROR(70027); 1074255332Scy return ESRCH; 1075145516Sdarrenr} 1076145516Sdarrenr 1077145516Sdarrenr 1078145516Sdarrenr/* ------------------------------------------------------------------------ */ 1079255332Scy/* Function: ipf_pool_destroy */ 1080145516Sdarrenr/* Returns: int - 0 = success, else error */ 1081255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1082255332Scy/* softp(I) - pointer to soft context pool information */ 1083255332Scy/* unit(I) - ipfilter device to which we are working on */ 1084255332Scy/* name(I) - name of the pool */ 1085255332Scy/* Locks: WRITE(ipf_poolrw) or WRITE(ipf_global) */ 1086145516Sdarrenr/* */ 1087145516Sdarrenr/* Search for a pool using paramters passed in and if it's not otherwise */ 1088170263Sdarrenr/* busy, free it. If it is busy, clear all of its nodes, mark it for being */ 1089170263Sdarrenr/* deleted and return an error saying it is busy. */ 1090145516Sdarrenr/* */ 1091255332Scy/* NOTE: Because this function is called out of ipfdetach() where ipf_poolrw*/ 1092145516Sdarrenr/* may not be initialised, we can't use an ASSERT to enforce the locking */ 1093255332Scy/* assertion that one of the two (ipf_poolrw,ipf_global) is held. */ 1094145516Sdarrenr/* ------------------------------------------------------------------------ */ 1095255332Scystatic int 1096255332Scyipf_pool_destroy(softc, softp, unit, name) 1097255332Scy ipf_main_softc_t *softc; 1098255332Scy ipf_pool_softc_t *softp; 1099255332Scy int unit; 1100255332Scy char *name; 1101145516Sdarrenr{ 1102145516Sdarrenr ip_pool_t *ipo; 1103145516Sdarrenr 1104255332Scy ipo = ipf_pool_exists(softp, unit, name); 1105255332Scy if (ipo == NULL) { 1106255332Scy IPFERROR(70009); 1107145516Sdarrenr return ESRCH; 1108255332Scy } 1109145516Sdarrenr 1110170263Sdarrenr if (ipo->ipo_ref != 1) { 1111255332Scy ipf_pool_clearnodes(softc, softp, ipo); 1112170263Sdarrenr ipo->ipo_flags |= IPOOL_DELETE; 1113170263Sdarrenr return 0; 1114170263Sdarrenr } 1115145516Sdarrenr 1116255332Scy ipf_pool_free(softc, softp, ipo); 1117145516Sdarrenr return 0; 1118145516Sdarrenr} 1119145516Sdarrenr 1120145516Sdarrenr 1121145516Sdarrenr/* ------------------------------------------------------------------------ */ 1122255332Scy/* Function: ipf_pool_flush */ 1123145516Sdarrenr/* Returns: int - number of pools deleted */ 1124255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1125255332Scy/* arg(I) - pointer to local context to use */ 1126255332Scy/* fp(I) - which pool(s) to flush */ 1127255332Scy/* Locks: WRITE(ipf_poolrw) or WRITE(ipf_global) */ 1128145516Sdarrenr/* */ 1129145516Sdarrenr/* Free all pools associated with the device that matches the unit number */ 1130145516Sdarrenr/* passed in with operation. */ 1131145516Sdarrenr/* */ 1132255332Scy/* NOTE: Because this function is called out of ipfdetach() where ipf_poolrw*/ 1133145516Sdarrenr/* may not be initialised, we can't use an ASSERT to enforce the locking */ 1134255332Scy/* assertion that one of the two (ipf_poolrw,ipf_global) is held. */ 1135145516Sdarrenr/* ------------------------------------------------------------------------ */ 1136255332Scystatic size_t 1137255332Scyipf_pool_flush(softc, arg, fp) 1138255332Scy ipf_main_softc_t *softc; 1139255332Scy void *arg; 1140255332Scy iplookupflush_t *fp; 1141145516Sdarrenr{ 1142255332Scy ipf_pool_softc_t *softp = arg; 1143145516Sdarrenr int i, num = 0, unit, err; 1144145516Sdarrenr ip_pool_t *p, *q; 1145145516Sdarrenr 1146145516Sdarrenr unit = fp->iplf_unit; 1147255332Scy for (i = -1; i <= IPL_LOGMAX; i++) { 1148145516Sdarrenr if (unit != IPLT_ALL && i != unit) 1149145516Sdarrenr continue; 1150255332Scy for (q = softp->ipf_pool_list[i + 1]; (p = q) != NULL; ) { 1151145516Sdarrenr q = p->ipo_next; 1152255332Scy err = ipf_pool_destroy(softc, softp, i, p->ipo_name); 1153145516Sdarrenr if (err == 0) 1154145516Sdarrenr num++; 1155145516Sdarrenr } 1156145516Sdarrenr } 1157145516Sdarrenr return num; 1158145516Sdarrenr} 1159145516Sdarrenr 1160145516Sdarrenr 1161145516Sdarrenr/* ------------------------------------------------------------------------ */ 1162255332Scy/* Function: ipf_pool_free */ 1163145516Sdarrenr/* Returns: void */ 1164255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1165255332Scy/* softp(I) - pointer to soft context pool information */ 1166255332Scy/* ipo(I) - pointer to pool structure */ 1167255332Scy/* Locks: WRITE(ipf_poolrw) or WRITE(ipf_global) */ 1168145516Sdarrenr/* */ 1169145516Sdarrenr/* Deletes the pool strucutre passed in from the list of pools and deletes */ 1170145516Sdarrenr/* all of the address information stored in it, including any tree data */ 1171145516Sdarrenr/* structures also allocated. */ 1172145516Sdarrenr/* */ 1173255332Scy/* NOTE: Because this function is called out of ipfdetach() where ipf_poolrw*/ 1174145516Sdarrenr/* may not be initialised, we can't use an ASSERT to enforce the locking */ 1175255332Scy/* assertion that one of the two (ipf_poolrw,ipf_global) is held. */ 1176145516Sdarrenr/* ------------------------------------------------------------------------ */ 1177255332Scystatic void 1178255332Scyipf_pool_free(softc, softp, ipo) 1179255332Scy ipf_main_softc_t *softc; 1180255332Scy ipf_pool_softc_t *softp; 1181255332Scy ip_pool_t *ipo; 1182145516Sdarrenr{ 1183170263Sdarrenr 1184255332Scy ipf_pool_clearnodes(softc, softp, ipo); 1185170263Sdarrenr 1186170263Sdarrenr if (ipo->ipo_next != NULL) 1187170263Sdarrenr ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; 1188170263Sdarrenr *ipo->ipo_pnext = ipo->ipo_next; 1189255332Scy ipf_rx_freehead(ipo->ipo_head); 1190170263Sdarrenr KFREE(ipo); 1191170263Sdarrenr 1192255332Scy softp->ipf_pool_stats.ipls_pools--; 1193170263Sdarrenr} 1194170263Sdarrenr 1195170263Sdarrenr 1196170263Sdarrenr/* ------------------------------------------------------------------------ */ 1197255332Scy/* Function: ipf_pool_clearnodes */ 1198170263Sdarrenr/* Returns: void */ 1199255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1200255332Scy/* softp(I) - pointer to soft context pool information */ 1201255332Scy/* ipo(I) - pointer to pool structure */ 1202255332Scy/* Locks: WRITE(ipf_poolrw) or WRITE(ipf_global) */ 1203170263Sdarrenr/* */ 1204170263Sdarrenr/* Deletes all nodes stored in a pool structure. */ 1205170263Sdarrenr/* ------------------------------------------------------------------------ */ 1206255332Scystatic void 1207255332Scyipf_pool_clearnodes(softc, softp, ipo) 1208255332Scy ipf_main_softc_t *softc; 1209255332Scy ipf_pool_softc_t *softp; 1210255332Scy ip_pool_t *ipo; 1211170263Sdarrenr{ 1212255332Scy ip_pool_node_t *n, **next; 1213145516Sdarrenr 1214255332Scy for (next = &ipo->ipo_list; (n = *next) != NULL; ) 1215255332Scy ipf_pool_remove_node(softc, softp, ipo, n); 1216145516Sdarrenr 1217145516Sdarrenr ipo->ipo_list = NULL; 1218145516Sdarrenr} 1219145516Sdarrenr 1220145516Sdarrenr 1221145516Sdarrenr/* ------------------------------------------------------------------------ */ 1222255332Scy/* Function: ipf_pool_deref */ 1223145516Sdarrenr/* Returns: void */ 1224255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1225255332Scy/* arg(I) - pointer to local context to use */ 1226255332Scy/* pool(I) - pointer to pool structure */ 1227255332Scy/* Locks: WRITE(ipf_poolrw) */ 1228145516Sdarrenr/* */ 1229145516Sdarrenr/* Drop the number of known references to this pool structure by one and if */ 1230145516Sdarrenr/* we arrive at zero known references, free it. */ 1231145516Sdarrenr/* ------------------------------------------------------------------------ */ 1232255332Scystatic int 1233255332Scyipf_pool_deref(softc, arg, pool) 1234255332Scy ipf_main_softc_t *softc; 1235255332Scy void *arg, *pool; 1236145516Sdarrenr{ 1237255332Scy ip_pool_t *ipo = pool; 1238145516Sdarrenr 1239145516Sdarrenr ipo->ipo_ref--; 1240170263Sdarrenr 1241145516Sdarrenr if (ipo->ipo_ref == 0) 1242255332Scy ipf_pool_free(softc, arg, ipo); 1243170263Sdarrenr 1244170263Sdarrenr else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE)) 1245255332Scy ipf_pool_destroy(softc, arg, ipo->ipo_unit, ipo->ipo_name); 1246255332Scy 1247255332Scy return 0; 1248145516Sdarrenr} 1249145516Sdarrenr 1250145516Sdarrenr 1251170263Sdarrenr/* ------------------------------------------------------------------------ */ 1252255332Scy/* Function: ipf_pool_node_deref */ 1253170263Sdarrenr/* Returns: void */ 1254255332Scy/* Parameters: softp(I) - pointer to soft context pool information */ 1255255332Scy/* ipn(I) - pointer to pool structure */ 1256255332Scy/* Locks: WRITE(ipf_poolrw) */ 1257170263Sdarrenr/* */ 1258170263Sdarrenr/* Drop a reference to the pool node passed in and if we're the last, free */ 1259170263Sdarrenr/* it all up and adjust the stats accordingly. */ 1260170263Sdarrenr/* ------------------------------------------------------------------------ */ 1261255332Scystatic void 1262255332Scyipf_pool_node_deref(softp, ipn) 1263255332Scy ipf_pool_softc_t *softp; 1264255332Scy ip_pool_node_t *ipn; 1265170263Sdarrenr{ 1266170263Sdarrenr 1267170263Sdarrenr ipn->ipn_ref--; 1268170263Sdarrenr 1269170263Sdarrenr if (ipn->ipn_ref == 0) { 1270170263Sdarrenr KFREE(ipn); 1271255332Scy softp->ipf_pool_stats.ipls_nodes--; 1272170263Sdarrenr } 1273170263Sdarrenr} 1274170263Sdarrenr 1275170263Sdarrenr 1276170263Sdarrenr/* ------------------------------------------------------------------------ */ 1277255332Scy/* Function: ipf_pool_iter_next */ 1278170263Sdarrenr/* Returns: void */ 1279255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1280255332Scy/* arg(I) - pointer to local context to use */ 1281255332Scy/* token(I) - pointer to pool structure */ 1282255332Scy/* ilp(IO) - pointer to pool iterating structure */ 1283170263Sdarrenr/* */ 1284170263Sdarrenr/* ------------------------------------------------------------------------ */ 1285255332Scystatic int 1286255332Scyipf_pool_iter_next(softc, arg, token, ilp) 1287255332Scy ipf_main_softc_t *softc; 1288255332Scy void *arg; 1289255332Scy ipftoken_t *token; 1290255332Scy ipflookupiter_t *ilp; 1291170263Sdarrenr{ 1292255332Scy ipf_pool_softc_t *softp = arg; 1293170263Sdarrenr ip_pool_node_t *node, zn, *nextnode; 1294170263Sdarrenr ip_pool_t *ipo, zp, *nextipo; 1295255332Scy void *pnext; 1296170263Sdarrenr int err; 1297170263Sdarrenr 1298170263Sdarrenr err = 0; 1299170263Sdarrenr node = NULL; 1300170263Sdarrenr nextnode = NULL; 1301170263Sdarrenr ipo = NULL; 1302170263Sdarrenr nextipo = NULL; 1303170263Sdarrenr 1304255332Scy READ_ENTER(&softc->ipf_poolrw); 1305170263Sdarrenr 1306170263Sdarrenr switch (ilp->ili_otype) 1307170263Sdarrenr { 1308170263Sdarrenr case IPFLOOKUPITER_LIST : 1309170263Sdarrenr ipo = token->ipt_data; 1310170263Sdarrenr if (ipo == NULL) { 1311255332Scy nextipo = softp->ipf_pool_list[(int)ilp->ili_unit + 1]; 1312170263Sdarrenr } else { 1313170263Sdarrenr nextipo = ipo->ipo_next; 1314170263Sdarrenr } 1315170263Sdarrenr 1316170263Sdarrenr if (nextipo != NULL) { 1317255332Scy ATOMIC_INC32(nextipo->ipo_ref); 1318172771Sdarrenr token->ipt_data = nextipo; 1319170263Sdarrenr } else { 1320170263Sdarrenr bzero((char *)&zp, sizeof(zp)); 1321170263Sdarrenr nextipo = &zp; 1322172771Sdarrenr token->ipt_data = NULL; 1323170263Sdarrenr } 1324255332Scy pnext = nextipo->ipo_next; 1325170263Sdarrenr break; 1326170263Sdarrenr 1327170263Sdarrenr case IPFLOOKUPITER_NODE : 1328170263Sdarrenr node = token->ipt_data; 1329170263Sdarrenr if (node == NULL) { 1330255332Scy ipo = ipf_pool_exists(arg, ilp->ili_unit, 1331255332Scy ilp->ili_name); 1332255332Scy if (ipo == NULL) { 1333255332Scy IPFERROR(70010); 1334170263Sdarrenr err = ESRCH; 1335255332Scy } else { 1336170263Sdarrenr nextnode = ipo->ipo_list; 1337170263Sdarrenr ipo = NULL; 1338170263Sdarrenr } 1339170263Sdarrenr } else { 1340170263Sdarrenr nextnode = node->ipn_next; 1341170263Sdarrenr } 1342170263Sdarrenr 1343170263Sdarrenr if (nextnode != NULL) { 1344255332Scy ATOMIC_INC32(nextnode->ipn_ref); 1345172771Sdarrenr token->ipt_data = nextnode; 1346170263Sdarrenr } else { 1347170263Sdarrenr bzero((char *)&zn, sizeof(zn)); 1348170263Sdarrenr nextnode = &zn; 1349172771Sdarrenr token->ipt_data = NULL; 1350170263Sdarrenr } 1351255332Scy pnext = nextnode->ipn_next; 1352170263Sdarrenr break; 1353255332Scy 1354170263Sdarrenr default : 1355255332Scy IPFERROR(70011); 1356255332Scy pnext = NULL; 1357170263Sdarrenr err = EINVAL; 1358170263Sdarrenr break; 1359170263Sdarrenr } 1360170263Sdarrenr 1361255332Scy RWLOCK_EXIT(&softc->ipf_poolrw); 1362170263Sdarrenr if (err != 0) 1363170263Sdarrenr return err; 1364170263Sdarrenr 1365170263Sdarrenr switch (ilp->ili_otype) 1366170263Sdarrenr { 1367170263Sdarrenr case IPFLOOKUPITER_LIST : 1368255332Scy err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); 1369255332Scy if (err != 0) { 1370255332Scy IPFERROR(70012); 1371255332Scy err = EFAULT; 1372255332Scy } 1373170263Sdarrenr if (ipo != NULL) { 1374255332Scy WRITE_ENTER(&softc->ipf_poolrw); 1375255332Scy ipf_pool_deref(softc, softp, ipo); 1376255332Scy RWLOCK_EXIT(&softc->ipf_poolrw); 1377170263Sdarrenr } 1378170263Sdarrenr break; 1379170263Sdarrenr 1380170263Sdarrenr case IPFLOOKUPITER_NODE : 1381255332Scy err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); 1382255332Scy if (err != 0) { 1383255332Scy IPFERROR(70013); 1384255332Scy err = EFAULT; 1385255332Scy } 1386170263Sdarrenr if (node != NULL) { 1387255332Scy WRITE_ENTER(&softc->ipf_poolrw); 1388255332Scy ipf_pool_node_deref(softp, node); 1389255332Scy RWLOCK_EXIT(&softc->ipf_poolrw); 1390170263Sdarrenr } 1391170263Sdarrenr break; 1392170263Sdarrenr } 1393255332Scy if (pnext == NULL) 1394255332Scy ipf_token_mark_complete(token); 1395170263Sdarrenr 1396170263Sdarrenr return err; 1397170263Sdarrenr} 1398170263Sdarrenr 1399170263Sdarrenr 1400170263Sdarrenr/* ------------------------------------------------------------------------ */ 1401255332Scy/* Function: ipf_pool_iterderef */ 1402170263Sdarrenr/* Returns: void */ 1403255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1404255332Scy/* arg(I) - pointer to local context to use */ 1405255332Scy/* unit(I) - ipfilter device to which we are working on */ 1406255332Scy/* Locks: WRITE(ipf_poolrw) */ 1407170263Sdarrenr/* */ 1408170263Sdarrenr/* ------------------------------------------------------------------------ */ 1409255332Scystatic int 1410255332Scyipf_pool_iter_deref(softc, arg, otype, unit, data) 1411255332Scy ipf_main_softc_t *softc; 1412255332Scy void *arg; 1413255332Scy int otype; 1414255332Scy int unit; 1415255332Scy void *data; 1416170263Sdarrenr{ 1417255332Scy ipf_pool_softc_t *softp = arg; 1418170263Sdarrenr 1419170263Sdarrenr if (data == NULL) 1420255332Scy return EINVAL; 1421170263Sdarrenr 1422170263Sdarrenr if (unit < 0 || unit > IPL_LOGMAX) 1423255332Scy return EINVAL; 1424170263Sdarrenr 1425170263Sdarrenr switch (otype) 1426170263Sdarrenr { 1427170263Sdarrenr case IPFLOOKUPITER_LIST : 1428255332Scy ipf_pool_deref(softc, softp, (ip_pool_t *)data); 1429170263Sdarrenr break; 1430170263Sdarrenr 1431170263Sdarrenr case IPFLOOKUPITER_NODE : 1432255332Scy ipf_pool_node_deref(softp, (ip_pool_node_t *)data); 1433170263Sdarrenr break; 1434170263Sdarrenr default : 1435170263Sdarrenr break; 1436170263Sdarrenr } 1437255332Scy 1438255332Scy return 0; 1439170263Sdarrenr} 1440170263Sdarrenr 1441170263Sdarrenr 1442255332Scy/* ------------------------------------------------------------------------ */ 1443255332Scy/* Function: ipf_pool_expire */ 1444255332Scy/* Returns: Nil */ 1445255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1446255332Scy/* arg(I) - pointer to local context to use */ 1447255332Scy/* */ 1448255332Scy/* At present this function exists just to support temporary addition of */ 1449255332Scy/* nodes to the address pool. */ 1450255332Scy/* ------------------------------------------------------------------------ */ 1451255332Scystatic void 1452255332Scyipf_pool_expire(softc, arg) 1453255332Scy ipf_main_softc_t *softc; 1454255332Scy void *arg; 1455145516Sdarrenr{ 1456255332Scy ipf_pool_softc_t *softp = arg; 1457255332Scy ip_pool_node_t *n; 1458145516Sdarrenr 1459255332Scy while ((n = softp->ipf_node_explist) != NULL) { 1460255332Scy /* 1461255332Scy * Because the list is kept sorted on insertion, the fist 1462255332Scy * one that dies in the future means no more work to do. 1463255332Scy */ 1464255332Scy if (n->ipn_die > softc->ipf_ticks) 1465255332Scy break; 1466255332Scy ipf_pool_remove_node(softc, softp, n->ipn_owner, n); 1467145516Sdarrenr } 1468145516Sdarrenr} 1469145516Sdarrenr 1470145516Sdarrenr 1471255332Scy 1472255332Scy 1473255332Scy#ifndef _KERNEL 1474145516Sdarrenrvoid 1475255332Scyipf_pool_dump(softc, arg) 1476255332Scy ipf_main_softc_t *softc; 1477255332Scy void *arg; 1478145516Sdarrenr{ 1479255332Scy ipf_pool_softc_t *softp = arg; 1480255332Scy ip_pool_t *ipl; 1481255332Scy int i; 1482145516Sdarrenr 1483255332Scy printf("List of configured pools\n"); 1484255332Scy for (i = 0; i <= LOOKUP_POOL_MAX; i++) 1485255332Scy for (ipl = softp->ipf_pool_list[i]; ipl != NULL; 1486255332Scy ipl = ipl->ipo_next) 1487255332Scy printpool(ipl, bcopywrap, NULL, opts, NULL); 1488145516Sdarrenr} 1489255332Scy#endif 1490