1145516Sdarrenr/* 2145516Sdarrenr * Copyright (C) 1993-2001, 2003 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> 36145516Sdarrenr#if !defined(linux) 37145516Sdarrenr# include <sys/protosw.h> 38145516Sdarrenr#endif 39145516Sdarrenr#include <sys/socket.h> 40145516Sdarrenr#if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__)) 41145516Sdarrenr# include <sys/mbuf.h> 42145516Sdarrenr#endif 43145516Sdarrenr#if defined(__SVR4) || defined(__svr4__) 44145516Sdarrenr# include <sys/filio.h> 45145516Sdarrenr# include <sys/byteorder.h> 46145516Sdarrenr# ifdef _KERNEL 47145516Sdarrenr# include <sys/dditypes.h> 48145516Sdarrenr# endif 49145516Sdarrenr# include <sys/stream.h> 50145516Sdarrenr# include <sys/kmem.h> 51145516Sdarrenr#endif 52145516Sdarrenr#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 53145516Sdarrenr# include <sys/malloc.h> 54145516Sdarrenr#endif 55145516Sdarrenr 56172771Sdarrenr#if defined(SOLARIS2) && !defined(_KERNEL) 57172771Sdarrenr# include "radix_ipf.h" 58172771Sdarrenr#endif 59153872Sguido#if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \ 60153872Sguido defined(__hpux) || defined(__sgi)) 61145516Sdarrenr# include "radix_ipf_local.h" 62145516Sdarrenr# define _RADIX_H_ 63145516Sdarrenr#endif 64145516Sdarrenr#include <net/if.h> 65145516Sdarrenr#include <netinet/in.h> 66145516Sdarrenr 67145516Sdarrenr#include "netinet/ip_compat.h" 68145516Sdarrenr#include "netinet/ip_fil.h" 69145516Sdarrenr#include "netinet/ip_pool.h" 70145516Sdarrenr 71145516Sdarrenr#if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \ 72145516Sdarrenr ((BSD >= 198911) && !defined(__osf__) && \ 73145516Sdarrenr !defined(__hpux) && !defined(__sgi)) 74145516Sdarrenrstatic int rn_freenode __P((struct radix_node *, void *)); 75145516Sdarrenr#endif 76145516Sdarrenr 77145516Sdarrenr/* END OF INCLUDES */ 78145516Sdarrenr 79145516Sdarrenr#if !defined(lint) 80145516Sdarrenrstatic const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 81172771Sdarrenrstatic const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.24 2007/10/10 09:45:37 darrenr Exp $"; 82145516Sdarrenr#endif 83145516Sdarrenr 84145516Sdarrenr#ifdef IPFILTER_LOOKUP 85145516Sdarrenr 86172771Sdarrenr# if !defined(RADIX_NODE_HEAD_LOCK) || !defined(RADIX_NODE_HEAD_UNLOCK) || \ 87172771Sdarrenr !defined(_KERNEL) 88172771Sdarrenr# undef RADIX_NODE_HEAD_LOCK 89172771Sdarrenr# undef RADIX_NODE_HEAD_UNLOCK 90145516Sdarrenr# define RADIX_NODE_HEAD_LOCK(x) ; 91145516Sdarrenr# define RADIX_NODE_HEAD_UNLOCK(x) ; 92145516Sdarrenr# endif 93145516Sdarrenr 94170263Sdarrenrstatic void ip_pool_clearnodes __P((ip_pool_t *)); 95170263Sdarrenrstatic void *ip_pool_exists __P((int, char *)); 96170263Sdarrenr 97145516Sdarrenrip_pool_stat_t ipoolstat; 98145516Sdarrenripfrwlock_t ip_poolrw; 99145516Sdarrenr 100145516Sdarrenr/* 101145516Sdarrenr * Binary tree routines from Sedgewick and enhanced to do ranges of addresses. 102145516Sdarrenr * NOTE: Insertion *MUST* be from greatest range to least for it to work! 103145516Sdarrenr * These should be replaced, eventually, by something else - most notably a 104145516Sdarrenr * interval searching method. The important feature is to be able to find 105145516Sdarrenr * the best match. 106145516Sdarrenr * 107145516Sdarrenr * So why not use a radix tree for this? As the first line implies, it 108145516Sdarrenr * has been written to work with a _range_ of addresses. A range is not 109145516Sdarrenr * necessarily a match with any given netmask so what we end up dealing 110145516Sdarrenr * with is an interval tree. Implementations of these are hard to find 111145516Sdarrenr * and the one herein is far from bug free. 112145516Sdarrenr * 113145516Sdarrenr * Sigh, in the end I became convinced that the bugs the code contained did 114145516Sdarrenr * not make it worthwhile not using radix trees. For now the radix tree from 115145516Sdarrenr * 4.4 BSD is used, but this is not viewed as a long term solution. 116145516Sdarrenr */ 117145516Sdarrenrip_pool_t *ip_pool_list[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL, 118145516Sdarrenr NULL, NULL, NULL, NULL }; 119145516Sdarrenr 120145516Sdarrenr 121145516Sdarrenr#ifdef TEST_POOL 122145516Sdarrenrvoid treeprint __P((ip_pool_t *)); 123145516Sdarrenr 124145516Sdarrenrint 125145516Sdarrenrmain(argc, argv) 126145516Sdarrenr int argc; 127145516Sdarrenr char *argv[]; 128145516Sdarrenr{ 129145516Sdarrenr addrfamily_t a, b; 130145516Sdarrenr iplookupop_t op; 131145516Sdarrenr ip_pool_t *ipo; 132145516Sdarrenr i6addr_t ip; 133145516Sdarrenr 134145516Sdarrenr RWLOCK_INIT(&ip_poolrw, "poolrw"); 135145516Sdarrenr ip_pool_init(); 136145516Sdarrenr 137145516Sdarrenr bzero((char *)&a, sizeof(a)); 138145516Sdarrenr bzero((char *)&b, sizeof(b)); 139145516Sdarrenr bzero((char *)&ip, sizeof(ip)); 140145516Sdarrenr bzero((char *)&op, sizeof(op)); 141145516Sdarrenr strcpy(op.iplo_name, "0"); 142145516Sdarrenr 143145516Sdarrenr if (ip_pool_create(&op) == 0) 144170263Sdarrenr ipo = ip_pool_exists(0, "0"); 145145516Sdarrenr 146145516Sdarrenr a.adf_addr.in4.s_addr = 0x0a010203; 147145516Sdarrenr b.adf_addr.in4.s_addr = 0xffffffff; 148145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); 149145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); 150145516Sdarrenr 151145516Sdarrenr a.adf_addr.in4.s_addr = 0x0a000000; 152145516Sdarrenr b.adf_addr.in4.s_addr = 0xff000000; 153145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); 154145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); 155145516Sdarrenr 156145516Sdarrenr a.adf_addr.in4.s_addr = 0x0a010100; 157145516Sdarrenr b.adf_addr.in4.s_addr = 0xffffff00; 158145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); 159145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); 160145516Sdarrenr 161145516Sdarrenr a.adf_addr.in4.s_addr = 0x0a010200; 162145516Sdarrenr b.adf_addr.in4.s_addr = 0xffffff00; 163145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); 164145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); 165145516Sdarrenr 166145516Sdarrenr a.adf_addr.in4.s_addr = 0x0a010000; 167145516Sdarrenr b.adf_addr.in4.s_addr = 0xffff0000; 168145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); 169145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); 170145516Sdarrenr 171145516Sdarrenr a.adf_addr.in4.s_addr = 0x0a01020f; 172145516Sdarrenr b.adf_addr.in4.s_addr = 0xffffffff; 173145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); 174145516Sdarrenr ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); 175145516Sdarrenr#ifdef DEBUG_POOL 176145516Sdarrenrtreeprint(ipo); 177145516Sdarrenr#endif 178145516Sdarrenr ip.in4.s_addr = 0x0a00aabb; 179145516Sdarrenr printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 180145516Sdarrenr ip_pool_search(ipo, 4, &ip)); 181145516Sdarrenr 182145516Sdarrenr ip.in4.s_addr = 0x0a000001; 183145516Sdarrenr printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 184145516Sdarrenr ip_pool_search(ipo, 4, &ip)); 185145516Sdarrenr 186145516Sdarrenr ip.in4.s_addr = 0x0a000101; 187145516Sdarrenr printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 188145516Sdarrenr ip_pool_search(ipo, 4, &ip)); 189145516Sdarrenr 190145516Sdarrenr ip.in4.s_addr = 0x0a010001; 191145516Sdarrenr printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 192145516Sdarrenr ip_pool_search(ipo, 4, &ip)); 193145516Sdarrenr 194145516Sdarrenr ip.in4.s_addr = 0x0a010101; 195145516Sdarrenr printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 196145516Sdarrenr ip_pool_search(ipo, 4, &ip)); 197145516Sdarrenr 198145516Sdarrenr ip.in4.s_addr = 0x0a010201; 199145516Sdarrenr printf("search(%#x) = %d (0)\n", ip.in4.s_addr, 200145516Sdarrenr ip_pool_search(ipo, 4, &ip)); 201145516Sdarrenr 202145516Sdarrenr ip.in4.s_addr = 0x0a010203; 203145516Sdarrenr printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 204145516Sdarrenr ip_pool_search(ipo, 4, &ip)); 205145516Sdarrenr 206145516Sdarrenr ip.in4.s_addr = 0x0a01020f; 207145516Sdarrenr printf("search(%#x) = %d (1)\n", ip.in4.s_addr, 208145516Sdarrenr ip_pool_search(ipo, 4, &ip)); 209145516Sdarrenr 210145516Sdarrenr ip.in4.s_addr = 0x0b00aabb; 211145516Sdarrenr printf("search(%#x) = %d (-1)\n", ip.in4.s_addr, 212145516Sdarrenr ip_pool_search(ipo, 4, &ip)); 213145516Sdarrenr 214145516Sdarrenr#ifdef DEBUG_POOL 215145516Sdarrenrtreeprint(ipo); 216145516Sdarrenr#endif 217145516Sdarrenr 218145516Sdarrenr ip_pool_fini(); 219145516Sdarrenr 220145516Sdarrenr return 0; 221145516Sdarrenr} 222145516Sdarrenr 223145516Sdarrenr 224145516Sdarrenrvoid 225145516Sdarrenrtreeprint(ipo) 226145516Sdarrenrip_pool_t *ipo; 227145516Sdarrenr{ 228145516Sdarrenr ip_pool_node_t *c; 229145516Sdarrenr 230145516Sdarrenr for (c = ipo->ipo_list; c != NULL; c = c->ipn_next) 231145516Sdarrenr printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n", 232145516Sdarrenr c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr, 233145516Sdarrenr c->ipn_mask.adf_addr.in4.s_addr, 234145516Sdarrenr c->ipn_info, c->ipn_hits); 235145516Sdarrenr} 236145516Sdarrenr#endif /* TEST_POOL */ 237145516Sdarrenr 238145516Sdarrenr 239145516Sdarrenr/* ------------------------------------------------------------------------ */ 240145516Sdarrenr/* Function: ip_pool_init */ 241145516Sdarrenr/* Returns: int - 0 = success, else error */ 242145516Sdarrenr/* */ 243145516Sdarrenr/* Initialise the routing table data structures where required. */ 244145516Sdarrenr/* ------------------------------------------------------------------------ */ 245145516Sdarrenrint ip_pool_init() 246145516Sdarrenr{ 247145516Sdarrenr 248145516Sdarrenr bzero((char *)&ipoolstat, sizeof(ipoolstat)); 249145516Sdarrenr 250145516Sdarrenr#if (!defined(_KERNEL) || (BSD < 199306)) 251145516Sdarrenr rn_init(); 252145516Sdarrenr#endif 253145516Sdarrenr return 0; 254145516Sdarrenr} 255145516Sdarrenr 256145516Sdarrenr 257145516Sdarrenr/* ------------------------------------------------------------------------ */ 258145516Sdarrenr/* Function: ip_pool_fini */ 259145516Sdarrenr/* Returns: int - 0 = success, else error */ 260145516Sdarrenr/* Locks: WRITE(ipf_global) */ 261145516Sdarrenr/* */ 262145516Sdarrenr/* Clean up all the pool data structures allocated and call the cleanup */ 263145516Sdarrenr/* function for the radix tree that supports the pools. ip_pool_destroy() is*/ 264145516Sdarrenr/* used to delete the pools one by one to ensure they're properly freed up. */ 265145516Sdarrenr/* ------------------------------------------------------------------------ */ 266145516Sdarrenrvoid ip_pool_fini() 267145516Sdarrenr{ 268145516Sdarrenr ip_pool_t *p, *q; 269145516Sdarrenr int i; 270145516Sdarrenr 271145516Sdarrenr for (i = 0; i <= IPL_LOGMAX; i++) { 272145516Sdarrenr for (q = ip_pool_list[i]; (p = q) != NULL; ) { 273145516Sdarrenr q = p->ipo_next; 274170263Sdarrenr (void) ip_pool_destroy(i, p->ipo_name); 275145516Sdarrenr } 276145516Sdarrenr } 277145516Sdarrenr 278145516Sdarrenr#if (!defined(_KERNEL) || (BSD < 199306)) 279145516Sdarrenr rn_fini(); 280145516Sdarrenr#endif 281145516Sdarrenr} 282145516Sdarrenr 283145516Sdarrenr 284145516Sdarrenr/* ------------------------------------------------------------------------ */ 285145516Sdarrenr/* Function: ip_pool_statistics */ 286145516Sdarrenr/* Returns: int - 0 = success, else error */ 287145516Sdarrenr/* Parameters: op(I) - pointer to lookup operation arguments */ 288145516Sdarrenr/* */ 289145516Sdarrenr/* Copy the current statistics out into user space, collecting pool list */ 290145516Sdarrenr/* pointers as appropriate for later use. */ 291145516Sdarrenr/* ------------------------------------------------------------------------ */ 292145516Sdarrenrint ip_pool_statistics(op) 293145516Sdarrenriplookupop_t *op; 294145516Sdarrenr{ 295145516Sdarrenr ip_pool_stat_t stats; 296145516Sdarrenr int unit, i, err = 0; 297145516Sdarrenr 298145516Sdarrenr if (op->iplo_size != sizeof(ipoolstat)) 299145516Sdarrenr return EINVAL; 300145516Sdarrenr 301145516Sdarrenr bcopy((char *)&ipoolstat, (char *)&stats, sizeof(stats)); 302145516Sdarrenr unit = op->iplo_unit; 303145516Sdarrenr if (unit == IPL_LOGALL) { 304145516Sdarrenr for (i = 0; i < IPL_LOGSIZE; i++) 305145516Sdarrenr stats.ipls_list[i] = ip_pool_list[i]; 306145516Sdarrenr } else if (unit >= 0 && unit < IPL_LOGSIZE) { 307145516Sdarrenr if (op->iplo_name[0] != '\0') 308170263Sdarrenr stats.ipls_list[unit] = ip_pool_exists(unit, 309170263Sdarrenr op->iplo_name); 310145516Sdarrenr else 311145516Sdarrenr stats.ipls_list[unit] = ip_pool_list[unit]; 312145516Sdarrenr } else 313145516Sdarrenr err = EINVAL; 314145516Sdarrenr if (err == 0) 315145516Sdarrenr err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); 316145516Sdarrenr return err; 317145516Sdarrenr} 318145516Sdarrenr 319145516Sdarrenr 320145516Sdarrenr/* ------------------------------------------------------------------------ */ 321170263Sdarrenr/* Function: ip_pool_exists */ 322145516Sdarrenr/* Returns: int - 0 = success, else error */ 323145516Sdarrenr/* Parameters: ipo(I) - pointer to the pool getting the new node. */ 324145516Sdarrenr/* */ 325145516Sdarrenr/* Find a matching pool inside the collection of pools for a particular */ 326145516Sdarrenr/* device, indicated by the unit number. */ 327145516Sdarrenr/* ------------------------------------------------------------------------ */ 328170263Sdarrenrstatic void *ip_pool_exists(unit, name) 329145516Sdarrenrint unit; 330145516Sdarrenrchar *name; 331145516Sdarrenr{ 332145516Sdarrenr ip_pool_t *p; 333145516Sdarrenr 334145516Sdarrenr for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next) 335145516Sdarrenr if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0) 336145516Sdarrenr break; 337145516Sdarrenr return p; 338145516Sdarrenr} 339145516Sdarrenr 340145516Sdarrenr 341145516Sdarrenr/* ------------------------------------------------------------------------ */ 342170263Sdarrenr/* Function: ip_pool_find */ 343170263Sdarrenr/* Returns: int - 0 = success, else error */ 344170263Sdarrenr/* Parameters: ipo(I) - pointer to the pool getting the new node. */ 345170263Sdarrenr/* */ 346170263Sdarrenr/* Find a matching pool inside the collection of pools for a particular */ 347170263Sdarrenr/* device, indicated by the unit number. If it is marked for deletion then */ 348170263Sdarrenr/* pretend it does not exist. */ 349170263Sdarrenr/* ------------------------------------------------------------------------ */ 350170263Sdarrenrvoid *ip_pool_find(unit, name) 351170263Sdarrenrint unit; 352170263Sdarrenrchar *name; 353170263Sdarrenr{ 354170263Sdarrenr ip_pool_t *p; 355170263Sdarrenr 356170263Sdarrenr p = ip_pool_exists(unit, name); 357170263Sdarrenr if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE)) 358170263Sdarrenr return NULL; 359170263Sdarrenr 360170263Sdarrenr return p; 361170263Sdarrenr} 362170263Sdarrenr 363170263Sdarrenr 364170263Sdarrenr/* ------------------------------------------------------------------------ */ 365145516Sdarrenr/* Function: ip_pool_findeq */ 366145516Sdarrenr/* Returns: int - 0 = success, else error */ 367145516Sdarrenr/* Parameters: ipo(I) - pointer to the pool getting the new node. */ 368145516Sdarrenr/* addr(I) - pointer to address information to delete */ 369145516Sdarrenr/* mask(I) - */ 370145516Sdarrenr/* */ 371145516Sdarrenr/* Searches for an exact match of an entry in the pool. */ 372145516Sdarrenr/* ------------------------------------------------------------------------ */ 373145516Sdarrenrip_pool_node_t *ip_pool_findeq(ipo, addr, mask) 374145516Sdarrenrip_pool_t *ipo; 375145516Sdarrenraddrfamily_t *addr, *mask; 376145516Sdarrenr{ 377145516Sdarrenr struct radix_node *n; 378153872Sguido SPL_INT(s); 379145516Sdarrenr 380145516Sdarrenr SPL_NET(s); 381145516Sdarrenr RADIX_NODE_HEAD_LOCK(ipo->ipo_head); 382145516Sdarrenr n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head); 383145516Sdarrenr RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); 384145516Sdarrenr SPL_X(s); 385145516Sdarrenr return (ip_pool_node_t *)n; 386145516Sdarrenr} 387145516Sdarrenr 388145516Sdarrenr 389145516Sdarrenr/* ------------------------------------------------------------------------ */ 390145516Sdarrenr/* Function: ip_pool_search */ 391145516Sdarrenr/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 392145516Sdarrenr/* Parameters: tptr(I) - pointer to the pool to search */ 393145516Sdarrenr/* version(I) - IP protocol version (4 or 6) */ 394145516Sdarrenr/* dptr(I) - pointer to address information */ 395145516Sdarrenr/* */ 396145516Sdarrenr/* Search the pool for a given address and return a search result. */ 397145516Sdarrenr/* ------------------------------------------------------------------------ */ 398170263Sdarrenrint ip_pool_search(tptr, ipversion, dptr) 399145516Sdarrenrvoid *tptr; 400170263Sdarrenrint ipversion; 401145516Sdarrenrvoid *dptr; 402145516Sdarrenr{ 403145516Sdarrenr struct radix_node *rn; 404145516Sdarrenr ip_pool_node_t *m; 405145516Sdarrenr i6addr_t *addr; 406145516Sdarrenr addrfamily_t v; 407145516Sdarrenr ip_pool_t *ipo; 408145516Sdarrenr int rv; 409145516Sdarrenr 410145516Sdarrenr ipo = tptr; 411145516Sdarrenr if (ipo == NULL) 412145516Sdarrenr return -1; 413145516Sdarrenr 414145516Sdarrenr rv = 1; 415145516Sdarrenr m = NULL; 416145516Sdarrenr addr = (i6addr_t *)dptr; 417145516Sdarrenr bzero(&v, sizeof(v)); 418145516Sdarrenr v.adf_len = offsetof(addrfamily_t, adf_addr); 419145516Sdarrenr 420170263Sdarrenr if (ipversion == 4) { 421145516Sdarrenr v.adf_len += sizeof(addr->in4); 422145516Sdarrenr v.adf_addr.in4 = addr->in4; 423145516Sdarrenr#ifdef USE_INET6 424170263Sdarrenr } else if (ipversion == 6) { 425145516Sdarrenr v.adf_len += sizeof(addr->in6); 426145516Sdarrenr v.adf_addr.in6 = addr->in6; 427145516Sdarrenr#endif 428145516Sdarrenr } else 429145516Sdarrenr return -1; 430145516Sdarrenr 431145516Sdarrenr READ_ENTER(&ip_poolrw); 432145516Sdarrenr 433145516Sdarrenr RADIX_NODE_HEAD_LOCK(ipo->ipo_head); 434145516Sdarrenr rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head); 435145516Sdarrenr RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); 436145516Sdarrenr 437145516Sdarrenr if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) { 438145516Sdarrenr m = (ip_pool_node_t *)rn; 439145516Sdarrenr ipo->ipo_hits++; 440145516Sdarrenr m->ipn_hits++; 441145516Sdarrenr rv = m->ipn_info; 442145516Sdarrenr } 443145516Sdarrenr RWLOCK_EXIT(&ip_poolrw); 444145516Sdarrenr return rv; 445145516Sdarrenr} 446145516Sdarrenr 447145516Sdarrenr 448145516Sdarrenr/* ------------------------------------------------------------------------ */ 449145516Sdarrenr/* Function: ip_pool_insert */ 450145516Sdarrenr/* Returns: int - 0 = success, else error */ 451145516Sdarrenr/* Parameters: ipo(I) - pointer to the pool getting the new node. */ 452145516Sdarrenr/* addr(I) - address being added as a node */ 453145516Sdarrenr/* mask(I) - netmask to with the node being added */ 454145516Sdarrenr/* info(I) - extra information to store in this node. */ 455145516Sdarrenr/* Locks: WRITE(ip_poolrw) */ 456145516Sdarrenr/* */ 457145516Sdarrenr/* Add another node to the pool given by ipo. The three parameters passed */ 458145516Sdarrenr/* in (addr, mask, info) shold all be stored in the node. */ 459145516Sdarrenr/* ------------------------------------------------------------------------ */ 460145516Sdarrenrint ip_pool_insert(ipo, addr, mask, info) 461145516Sdarrenrip_pool_t *ipo; 462145516Sdarrenri6addr_t *addr, *mask; 463145516Sdarrenrint info; 464145516Sdarrenr{ 465145516Sdarrenr struct radix_node *rn; 466145516Sdarrenr ip_pool_node_t *x; 467145516Sdarrenr 468145516Sdarrenr KMALLOC(x, ip_pool_node_t *); 469145516Sdarrenr if (x == NULL) { 470145516Sdarrenr return ENOMEM; 471145516Sdarrenr } 472145516Sdarrenr 473145516Sdarrenr bzero(x, sizeof(*x)); 474145516Sdarrenr 475145516Sdarrenr x->ipn_info = info; 476145516Sdarrenr (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name)); 477145516Sdarrenr 478145516Sdarrenr bcopy(addr, &x->ipn_addr.adf_addr, sizeof(*addr)); 479145516Sdarrenr x->ipn_addr.adf_len = sizeof(x->ipn_addr); 480145516Sdarrenr bcopy(mask, &x->ipn_mask.adf_addr, sizeof(*mask)); 481145516Sdarrenr x->ipn_mask.adf_len = sizeof(x->ipn_mask); 482145516Sdarrenr 483145516Sdarrenr RADIX_NODE_HEAD_LOCK(ipo->ipo_head); 484145516Sdarrenr rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask, 485145516Sdarrenr ipo->ipo_head, x->ipn_nodes); 486145516Sdarrenr RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); 487145516Sdarrenr#ifdef DEBUG_POOL 488145516Sdarrenr printf("Added %p at %p\n", x, rn); 489145516Sdarrenr#endif 490145516Sdarrenr 491145516Sdarrenr if (rn == NULL) { 492145516Sdarrenr KFREE(x); 493145516Sdarrenr return ENOMEM; 494145516Sdarrenr } 495145516Sdarrenr 496170263Sdarrenr x->ipn_ref = 1; 497145516Sdarrenr x->ipn_next = ipo->ipo_list; 498145516Sdarrenr x->ipn_pnext = &ipo->ipo_list; 499145516Sdarrenr if (ipo->ipo_list != NULL) 500145516Sdarrenr ipo->ipo_list->ipn_pnext = &x->ipn_next; 501145516Sdarrenr ipo->ipo_list = x; 502145516Sdarrenr 503145516Sdarrenr ipoolstat.ipls_nodes++; 504145516Sdarrenr 505145516Sdarrenr return 0; 506145516Sdarrenr} 507145516Sdarrenr 508145516Sdarrenr 509145516Sdarrenr/* ------------------------------------------------------------------------ */ 510145516Sdarrenr/* Function: ip_pool_create */ 511145516Sdarrenr/* Returns: int - 0 = success, else error */ 512145516Sdarrenr/* Parameters: op(I) - pointer to iplookup struct with call details */ 513145516Sdarrenr/* Locks: WRITE(ip_poolrw) */ 514145516Sdarrenr/* */ 515145516Sdarrenr/* Creates a new group according to the paramters passed in via the */ 516145516Sdarrenr/* iplookupop structure. Does not check to see if the group already exists */ 517145516Sdarrenr/* when being inserted - assume this has already been done. If the pool is */ 518145516Sdarrenr/* marked as being anonymous, give it a new, unique, identifier. Call any */ 519145516Sdarrenr/* other functions required to initialise the structure. */ 520170263Sdarrenr/* */ 521170263Sdarrenr/* If the structure is flagged for deletion then reset the flag and return, */ 522170263Sdarrenr/* as this likely means we've tried to free a pool that is in use (flush) */ 523170263Sdarrenr/* and now want to repopulate it with "new" data. */ 524145516Sdarrenr/* ------------------------------------------------------------------------ */ 525145516Sdarrenrint ip_pool_create(op) 526145516Sdarrenriplookupop_t *op; 527145516Sdarrenr{ 528145516Sdarrenr char name[FR_GROUPLEN]; 529145516Sdarrenr int poolnum, unit; 530145516Sdarrenr ip_pool_t *h; 531145516Sdarrenr 532170263Sdarrenr unit = op->iplo_unit; 533145516Sdarrenr 534172771Sdarrenr if ((op->iplo_arg & LOOKUP_ANON) == 0) { 535170263Sdarrenr h = ip_pool_exists(unit, op->iplo_name); 536172771Sdarrenr if (h != NULL) { 537172771Sdarrenr if ((h->ipo_flags & IPOOL_DELETE) == 0) 538172771Sdarrenr return EEXIST; 539170263Sdarrenr h->ipo_flags &= ~IPOOL_DELETE; 540170263Sdarrenr return 0; 541170263Sdarrenr } 542172771Sdarrenr } 543170263Sdarrenr 544172771Sdarrenr KMALLOC(h, ip_pool_t *); 545172771Sdarrenr if (h == NULL) 546172771Sdarrenr return ENOMEM; 547172771Sdarrenr bzero(h, sizeof(*h)); 548172771Sdarrenr 549172771Sdarrenr if (rn_inithead((void **)&h->ipo_head, 550172771Sdarrenr offsetof(addrfamily_t, adf_addr) << 3) == 0) { 551172771Sdarrenr KFREE(h); 552172771Sdarrenr return ENOMEM; 553145516Sdarrenr } 554145516Sdarrenr 555170263Sdarrenr if ((op->iplo_arg & LOOKUP_ANON) != 0) { 556145516Sdarrenr ip_pool_t *p; 557145516Sdarrenr 558170263Sdarrenr h->ipo_flags |= IPOOL_ANON; 559170263Sdarrenr poolnum = LOOKUP_ANON; 560145516Sdarrenr 561145516Sdarrenr#if defined(SNPRINTF) && defined(_KERNEL) 562145516Sdarrenr SNPRINTF(name, sizeof(name), "%x", poolnum); 563145516Sdarrenr#else 564145516Sdarrenr (void)sprintf(name, "%x", poolnum); 565145516Sdarrenr#endif 566145516Sdarrenr 567145516Sdarrenr for (p = ip_pool_list[unit]; p != NULL; ) { 568145516Sdarrenr if (strncmp(name, p->ipo_name, 569145516Sdarrenr sizeof(p->ipo_name)) == 0) { 570145516Sdarrenr poolnum++; 571145516Sdarrenr#if defined(SNPRINTF) && defined(_KERNEL) 572145516Sdarrenr SNPRINTF(name, sizeof(name), "%x", poolnum); 573145516Sdarrenr#else 574145516Sdarrenr (void)sprintf(name, "%x", poolnum); 575145516Sdarrenr#endif 576145516Sdarrenr p = ip_pool_list[unit]; 577145516Sdarrenr } else 578145516Sdarrenr p = p->ipo_next; 579145516Sdarrenr } 580145516Sdarrenr 581145516Sdarrenr (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name)); 582153872Sguido (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name)); 583145516Sdarrenr } else { 584170263Sdarrenr (void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); 585145516Sdarrenr } 586145516Sdarrenr 587172771Sdarrenr h->ipo_ref = 1; 588172771Sdarrenr h->ipo_list = NULL; 589172771Sdarrenr h->ipo_unit = unit; 590172771Sdarrenr h->ipo_next = ip_pool_list[unit]; 591172771Sdarrenr if (ip_pool_list[unit] != NULL) 592172771Sdarrenr ip_pool_list[unit]->ipo_pnext = &h->ipo_next; 593172771Sdarrenr h->ipo_pnext = &ip_pool_list[unit]; 594172771Sdarrenr ip_pool_list[unit] = h; 595145516Sdarrenr 596172771Sdarrenr ipoolstat.ipls_pools++; 597145516Sdarrenr 598145516Sdarrenr return 0; 599145516Sdarrenr} 600145516Sdarrenr 601145516Sdarrenr 602145516Sdarrenr/* ------------------------------------------------------------------------ */ 603145516Sdarrenr/* Function: ip_pool_remove */ 604145516Sdarrenr/* Returns: int - 0 = success, else error */ 605145516Sdarrenr/* Parameters: ipo(I) - pointer to the pool to remove the node from. */ 606145516Sdarrenr/* ipe(I) - address being deleted as a node */ 607145516Sdarrenr/* Locks: WRITE(ip_poolrw) */ 608145516Sdarrenr/* */ 609170263Sdarrenr/* Remove a node from the pool given by ipo. */ 610145516Sdarrenr/* ------------------------------------------------------------------------ */ 611145516Sdarrenrint ip_pool_remove(ipo, ipe) 612145516Sdarrenrip_pool_t *ipo; 613145516Sdarrenrip_pool_node_t *ipe; 614145516Sdarrenr{ 615145516Sdarrenr 616170263Sdarrenr if (ipe->ipn_pnext != NULL) 617170263Sdarrenr *ipe->ipn_pnext = ipe->ipn_next; 618170263Sdarrenr if (ipe->ipn_next != NULL) 619170263Sdarrenr ipe->ipn_next->ipn_pnext = ipe->ipn_pnext; 620145516Sdarrenr 621145516Sdarrenr RADIX_NODE_HEAD_LOCK(ipo->ipo_head); 622170263Sdarrenr ipo->ipo_head->rnh_deladdr(&ipe->ipn_addr, &ipe->ipn_mask, 623145516Sdarrenr ipo->ipo_head); 624145516Sdarrenr RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); 625145516Sdarrenr 626170263Sdarrenr ip_pool_node_deref(ipe); 627145516Sdarrenr 628145516Sdarrenr return 0; 629145516Sdarrenr} 630145516Sdarrenr 631145516Sdarrenr 632145516Sdarrenr/* ------------------------------------------------------------------------ */ 633145516Sdarrenr/* Function: ip_pool_destroy */ 634145516Sdarrenr/* Returns: int - 0 = success, else error */ 635145516Sdarrenr/* Parameters: op(I) - information about the pool to remove */ 636145516Sdarrenr/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 637145516Sdarrenr/* */ 638145516Sdarrenr/* Search for a pool using paramters passed in and if it's not otherwise */ 639170263Sdarrenr/* busy, free it. If it is busy, clear all of its nodes, mark it for being */ 640170263Sdarrenr/* deleted and return an error saying it is busy. */ 641145516Sdarrenr/* */ 642170263Sdarrenr/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ 643145516Sdarrenr/* may not be initialised, we can't use an ASSERT to enforce the locking */ 644145516Sdarrenr/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 645145516Sdarrenr/* ------------------------------------------------------------------------ */ 646170263Sdarrenrint ip_pool_destroy(unit, name) 647170263Sdarrenrint unit; 648170263Sdarrenrchar *name; 649145516Sdarrenr{ 650145516Sdarrenr ip_pool_t *ipo; 651145516Sdarrenr 652170263Sdarrenr ipo = ip_pool_exists(unit, name); 653145516Sdarrenr if (ipo == NULL) 654145516Sdarrenr return ESRCH; 655145516Sdarrenr 656170263Sdarrenr if (ipo->ipo_ref != 1) { 657170263Sdarrenr ip_pool_clearnodes(ipo); 658170263Sdarrenr ipo->ipo_flags |= IPOOL_DELETE; 659170263Sdarrenr return 0; 660170263Sdarrenr } 661145516Sdarrenr 662145516Sdarrenr ip_pool_free(ipo); 663145516Sdarrenr return 0; 664145516Sdarrenr} 665145516Sdarrenr 666145516Sdarrenr 667145516Sdarrenr/* ------------------------------------------------------------------------ */ 668145516Sdarrenr/* Function: ip_pool_flush */ 669145516Sdarrenr/* Returns: int - number of pools deleted */ 670145516Sdarrenr/* Parameters: fp(I) - which pool(s) to flush */ 671145516Sdarrenr/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 672145516Sdarrenr/* */ 673145516Sdarrenr/* Free all pools associated with the device that matches the unit number */ 674145516Sdarrenr/* passed in with operation. */ 675145516Sdarrenr/* */ 676170263Sdarrenr/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ 677145516Sdarrenr/* may not be initialised, we can't use an ASSERT to enforce the locking */ 678145516Sdarrenr/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 679145516Sdarrenr/* ------------------------------------------------------------------------ */ 680145516Sdarrenrint ip_pool_flush(fp) 681145516Sdarrenriplookupflush_t *fp; 682145516Sdarrenr{ 683145516Sdarrenr int i, num = 0, unit, err; 684145516Sdarrenr ip_pool_t *p, *q; 685145516Sdarrenr iplookupop_t op; 686145516Sdarrenr 687145516Sdarrenr unit = fp->iplf_unit; 688145516Sdarrenr 689145516Sdarrenr for (i = 0; i <= IPL_LOGMAX; i++) { 690145516Sdarrenr if (unit != IPLT_ALL && i != unit) 691145516Sdarrenr continue; 692145516Sdarrenr for (q = ip_pool_list[i]; (p = q) != NULL; ) { 693145516Sdarrenr op.iplo_unit = i; 694145516Sdarrenr (void)strncpy(op.iplo_name, p->ipo_name, 695145516Sdarrenr sizeof(op.iplo_name)); 696145516Sdarrenr q = p->ipo_next; 697170263Sdarrenr err = ip_pool_destroy(op.iplo_unit, op.iplo_name); 698145516Sdarrenr if (err == 0) 699145516Sdarrenr num++; 700145516Sdarrenr else 701145516Sdarrenr break; 702145516Sdarrenr } 703145516Sdarrenr } 704145516Sdarrenr return num; 705145516Sdarrenr} 706145516Sdarrenr 707145516Sdarrenr 708145516Sdarrenr/* ------------------------------------------------------------------------ */ 709145516Sdarrenr/* Function: ip_pool_free */ 710145516Sdarrenr/* Returns: void */ 711145516Sdarrenr/* Parameters: ipo(I) - pointer to pool structure */ 712145516Sdarrenr/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 713145516Sdarrenr/* */ 714145516Sdarrenr/* Deletes the pool strucutre passed in from the list of pools and deletes */ 715145516Sdarrenr/* all of the address information stored in it, including any tree data */ 716145516Sdarrenr/* structures also allocated. */ 717145516Sdarrenr/* */ 718170263Sdarrenr/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ 719145516Sdarrenr/* may not be initialised, we can't use an ASSERT to enforce the locking */ 720145516Sdarrenr/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ 721145516Sdarrenr/* ------------------------------------------------------------------------ */ 722145516Sdarrenrvoid ip_pool_free(ipo) 723145516Sdarrenrip_pool_t *ipo; 724145516Sdarrenr{ 725170263Sdarrenr 726170263Sdarrenr ip_pool_clearnodes(ipo); 727170263Sdarrenr 728170263Sdarrenr if (ipo->ipo_next != NULL) 729170263Sdarrenr ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; 730170263Sdarrenr *ipo->ipo_pnext = ipo->ipo_next; 731170263Sdarrenr rn_freehead(ipo->ipo_head); 732170263Sdarrenr KFREE(ipo); 733170263Sdarrenr 734170263Sdarrenr ipoolstat.ipls_pools--; 735170263Sdarrenr} 736170263Sdarrenr 737170263Sdarrenr 738170263Sdarrenr/* ------------------------------------------------------------------------ */ 739170263Sdarrenr/* Function: ip_pool_clearnodes */ 740170263Sdarrenr/* Returns: void */ 741170263Sdarrenr/* Parameters: ipo(I) - pointer to pool structure */ 742170263Sdarrenr/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ 743170263Sdarrenr/* */ 744170263Sdarrenr/* Deletes all nodes stored in a pool structure. */ 745170263Sdarrenr/* ------------------------------------------------------------------------ */ 746170263Sdarrenrstatic void ip_pool_clearnodes(ipo) 747170263Sdarrenrip_pool_t *ipo; 748170263Sdarrenr{ 749145516Sdarrenr ip_pool_node_t *n; 750145516Sdarrenr 751145516Sdarrenr RADIX_NODE_HEAD_LOCK(ipo->ipo_head); 752145516Sdarrenr while ((n = ipo->ipo_list) != NULL) { 753145516Sdarrenr ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, 754145516Sdarrenr ipo->ipo_head); 755145516Sdarrenr 756145516Sdarrenr *n->ipn_pnext = n->ipn_next; 757145516Sdarrenr if (n->ipn_next) 758145516Sdarrenr n->ipn_next->ipn_pnext = n->ipn_pnext; 759145516Sdarrenr 760145516Sdarrenr KFREE(n); 761145516Sdarrenr 762145516Sdarrenr ipoolstat.ipls_nodes--; 763145516Sdarrenr } 764145516Sdarrenr RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); 765145516Sdarrenr 766145516Sdarrenr ipo->ipo_list = NULL; 767145516Sdarrenr} 768145516Sdarrenr 769145516Sdarrenr 770145516Sdarrenr/* ------------------------------------------------------------------------ */ 771145516Sdarrenr/* Function: ip_pool_deref */ 772145516Sdarrenr/* Returns: void */ 773145516Sdarrenr/* Parameters: ipo(I) - pointer to pool structure */ 774145516Sdarrenr/* Locks: WRITE(ip_poolrw) */ 775145516Sdarrenr/* */ 776145516Sdarrenr/* Drop the number of known references to this pool structure by one and if */ 777145516Sdarrenr/* we arrive at zero known references, free it. */ 778145516Sdarrenr/* ------------------------------------------------------------------------ */ 779145516Sdarrenrvoid ip_pool_deref(ipo) 780145516Sdarrenrip_pool_t *ipo; 781145516Sdarrenr{ 782145516Sdarrenr 783145516Sdarrenr ipo->ipo_ref--; 784170263Sdarrenr 785145516Sdarrenr if (ipo->ipo_ref == 0) 786145516Sdarrenr ip_pool_free(ipo); 787170263Sdarrenr 788170263Sdarrenr else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE)) 789170263Sdarrenr ip_pool_destroy(ipo->ipo_unit, ipo->ipo_name); 790145516Sdarrenr} 791145516Sdarrenr 792145516Sdarrenr 793170263Sdarrenr/* ------------------------------------------------------------------------ */ 794170263Sdarrenr/* Function: ip_pool_node_deref */ 795170263Sdarrenr/* Returns: void */ 796170263Sdarrenr/* Parameters: ipn(I) - pointer to pool structure */ 797170263Sdarrenr/* Locks: WRITE(ip_poolrw) */ 798170263Sdarrenr/* */ 799170263Sdarrenr/* Drop a reference to the pool node passed in and if we're the last, free */ 800170263Sdarrenr/* it all up and adjust the stats accordingly. */ 801170263Sdarrenr/* ------------------------------------------------------------------------ */ 802170263Sdarrenrvoid ip_pool_node_deref(ipn) 803170263Sdarrenrip_pool_node_t *ipn; 804170263Sdarrenr{ 805170263Sdarrenr 806170263Sdarrenr ipn->ipn_ref--; 807170263Sdarrenr 808170263Sdarrenr if (ipn->ipn_ref == 0) { 809170263Sdarrenr KFREE(ipn); 810170263Sdarrenr ipoolstat.ipls_nodes--; 811170263Sdarrenr } 812170263Sdarrenr} 813170263Sdarrenr 814170263Sdarrenr 815170263Sdarrenr/* ------------------------------------------------------------------------ */ 816170263Sdarrenr/* Function: ip_pool_getnext */ 817170263Sdarrenr/* Returns: void */ 818170263Sdarrenr/* Parameters: token(I) - pointer to pool structure */ 819170263Sdarrenr/* Parameters: ilp(IO) - pointer to pool iterating structure */ 820170263Sdarrenr/* */ 821170263Sdarrenr/* ------------------------------------------------------------------------ */ 822170263Sdarrenrint ip_pool_getnext(token, ilp) 823170263Sdarrenripftoken_t *token; 824170263Sdarrenripflookupiter_t *ilp; 825170263Sdarrenr{ 826170263Sdarrenr ip_pool_node_t *node, zn, *nextnode; 827170263Sdarrenr ip_pool_t *ipo, zp, *nextipo; 828170263Sdarrenr int err; 829170263Sdarrenr 830170263Sdarrenr err = 0; 831170263Sdarrenr node = NULL; 832170263Sdarrenr nextnode = NULL; 833170263Sdarrenr ipo = NULL; 834170263Sdarrenr nextipo = NULL; 835170263Sdarrenr 836170263Sdarrenr READ_ENTER(&ip_poolrw); 837170263Sdarrenr 838170263Sdarrenr switch (ilp->ili_otype) 839170263Sdarrenr { 840170263Sdarrenr case IPFLOOKUPITER_LIST : 841170263Sdarrenr ipo = token->ipt_data; 842170263Sdarrenr if (ipo == NULL) { 843170263Sdarrenr nextipo = ip_pool_list[(int)ilp->ili_unit]; 844170263Sdarrenr } else { 845170263Sdarrenr nextipo = ipo->ipo_next; 846170263Sdarrenr } 847170263Sdarrenr 848170263Sdarrenr if (nextipo != NULL) { 849170263Sdarrenr ATOMIC_INC(nextipo->ipo_ref); 850172771Sdarrenr token->ipt_data = nextipo; 851170263Sdarrenr } else { 852170263Sdarrenr bzero((char *)&zp, sizeof(zp)); 853170263Sdarrenr nextipo = &zp; 854172771Sdarrenr token->ipt_data = NULL; 855170263Sdarrenr } 856170263Sdarrenr break; 857170263Sdarrenr 858170263Sdarrenr case IPFLOOKUPITER_NODE : 859170263Sdarrenr node = token->ipt_data; 860170263Sdarrenr if (node == NULL) { 861170263Sdarrenr ipo = ip_pool_exists(ilp->ili_unit, ilp->ili_name); 862170263Sdarrenr if (ipo == NULL) 863170263Sdarrenr err = ESRCH; 864170263Sdarrenr else { 865170263Sdarrenr nextnode = ipo->ipo_list; 866170263Sdarrenr ipo = NULL; 867170263Sdarrenr } 868170263Sdarrenr } else { 869170263Sdarrenr nextnode = node->ipn_next; 870170263Sdarrenr } 871170263Sdarrenr 872170263Sdarrenr if (nextnode != NULL) { 873170263Sdarrenr ATOMIC_INC(nextnode->ipn_ref); 874172771Sdarrenr token->ipt_data = nextnode; 875170263Sdarrenr } else { 876170263Sdarrenr bzero((char *)&zn, sizeof(zn)); 877170263Sdarrenr nextnode = &zn; 878172771Sdarrenr token->ipt_data = NULL; 879170263Sdarrenr } 880170263Sdarrenr break; 881170263Sdarrenr default : 882170263Sdarrenr err = EINVAL; 883170263Sdarrenr break; 884170263Sdarrenr } 885170263Sdarrenr 886170263Sdarrenr RWLOCK_EXIT(&ip_poolrw); 887170263Sdarrenr 888170263Sdarrenr if (err != 0) 889170263Sdarrenr return err; 890170263Sdarrenr 891170263Sdarrenr switch (ilp->ili_otype) 892170263Sdarrenr { 893170263Sdarrenr case IPFLOOKUPITER_LIST : 894170263Sdarrenr if (ipo != NULL) { 895170263Sdarrenr WRITE_ENTER(&ip_poolrw); 896170263Sdarrenr ip_pool_deref(ipo); 897170263Sdarrenr RWLOCK_EXIT(&ip_poolrw); 898170263Sdarrenr } 899170263Sdarrenr err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); 900170263Sdarrenr if (err != 0) 901170263Sdarrenr err = EFAULT; 902170263Sdarrenr break; 903170263Sdarrenr 904170263Sdarrenr case IPFLOOKUPITER_NODE : 905170263Sdarrenr if (node != NULL) { 906170263Sdarrenr WRITE_ENTER(&ip_poolrw); 907170263Sdarrenr ip_pool_node_deref(node); 908170263Sdarrenr RWLOCK_EXIT(&ip_poolrw); 909170263Sdarrenr } 910170263Sdarrenr err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); 911170263Sdarrenr if (err != 0) 912170263Sdarrenr err = EFAULT; 913170263Sdarrenr break; 914170263Sdarrenr } 915170263Sdarrenr 916170263Sdarrenr return err; 917170263Sdarrenr} 918170263Sdarrenr 919170263Sdarrenr 920170263Sdarrenr/* ------------------------------------------------------------------------ */ 921170263Sdarrenr/* Function: ip_pool_iterderef */ 922170263Sdarrenr/* Returns: void */ 923170263Sdarrenr/* Parameters: ipn(I) - pointer to pool structure */ 924170263Sdarrenr/* Locks: WRITE(ip_poolrw) */ 925170263Sdarrenr/* */ 926170263Sdarrenr/* ------------------------------------------------------------------------ */ 927170263Sdarrenrvoid ip_pool_iterderef(otype, unit, data) 928170263Sdarrenru_int otype; 929170263Sdarrenrint unit; 930170263Sdarrenrvoid *data; 931170263Sdarrenr{ 932170263Sdarrenr 933170263Sdarrenr if (data == NULL) 934170263Sdarrenr return; 935170263Sdarrenr 936170263Sdarrenr if (unit < 0 || unit > IPL_LOGMAX) 937170263Sdarrenr return; 938170263Sdarrenr 939170263Sdarrenr switch (otype) 940170263Sdarrenr { 941170263Sdarrenr case IPFLOOKUPITER_LIST : 942170263Sdarrenr WRITE_ENTER(&ip_poolrw); 943170263Sdarrenr ip_pool_deref((ip_pool_t *)data); 944170263Sdarrenr RWLOCK_EXIT(&ip_poolrw); 945170263Sdarrenr break; 946170263Sdarrenr 947170263Sdarrenr case IPFLOOKUPITER_NODE : 948170263Sdarrenr WRITE_ENTER(&ip_poolrw); 949170263Sdarrenr ip_pool_node_deref((ip_pool_node_t *)data); 950170263Sdarrenr RWLOCK_EXIT(&ip_poolrw); 951170263Sdarrenr break; 952170263Sdarrenr default : 953170263Sdarrenr break; 954170263Sdarrenr } 955170263Sdarrenr} 956170263Sdarrenr 957170263Sdarrenr 958145516Sdarrenr# if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \ 959145516Sdarrenr !defined(__hpux) && !defined(__sgi)) 960145516Sdarrenrstatic int 961145516Sdarrenrrn_freenode(struct radix_node *n, void *p) 962145516Sdarrenr{ 963145516Sdarrenr struct radix_node_head *rnh = p; 964145516Sdarrenr struct radix_node *d; 965145516Sdarrenr 966145516Sdarrenr d = rnh->rnh_deladdr(n->rn_key, NULL, rnh); 967145516Sdarrenr if (d != NULL) { 968145516Sdarrenr FreeS(d, max_keylen + 2 * sizeof (*d)); 969145516Sdarrenr } 970145516Sdarrenr return 0; 971145516Sdarrenr} 972145516Sdarrenr 973145516Sdarrenr 974145516Sdarrenrvoid 975145516Sdarrenrrn_freehead(rnh) 976145516Sdarrenr struct radix_node_head *rnh; 977145516Sdarrenr{ 978145516Sdarrenr 979145516Sdarrenr RADIX_NODE_HEAD_LOCK(rnh); 980145516Sdarrenr (*rnh->rnh_walktree)(rnh, rn_freenode, rnh); 981145516Sdarrenr 982145516Sdarrenr rnh->rnh_addaddr = NULL; 983145516Sdarrenr rnh->rnh_deladdr = NULL; 984145516Sdarrenr rnh->rnh_matchaddr = NULL; 985145516Sdarrenr rnh->rnh_lookup = NULL; 986145516Sdarrenr rnh->rnh_walktree = NULL; 987145516Sdarrenr RADIX_NODE_HEAD_UNLOCK(rnh); 988145516Sdarrenr 989145516Sdarrenr Free(rnh); 990145516Sdarrenr} 991145516Sdarrenr# endif 992145516Sdarrenr#endif /* IPFILTER_LOOKUP */ 993