17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (C) 2002-2003 by Darren Reed. 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * See the IPFILTER.LICENCE file for details on licencing. 57c478bd9Sstevel@tonic-gate * 6*bb1d9de5SJohn Ojemann * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 77c478bd9Sstevel@tonic-gate * Use is subject to license terms. 87c478bd9Sstevel@tonic-gate */ 97c478bd9Sstevel@tonic-gate 107c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL) 117c478bd9Sstevel@tonic-gate # undef KERNEL 127c478bd9Sstevel@tonic-gate # undef _KERNEL 137c478bd9Sstevel@tonic-gate # define KERNEL 1 147c478bd9Sstevel@tonic-gate # define _KERNEL 1 157c478bd9Sstevel@tonic-gate #endif 16ab25eeb5Syz #if defined(__osf__) 17ab25eeb5Syz # define _PROTO_NET_H_ 18ab25eeb5Syz #endif 197c478bd9Sstevel@tonic-gate #include <sys/param.h> 207c478bd9Sstevel@tonic-gate #include <sys/errno.h> 217c478bd9Sstevel@tonic-gate #include <sys/types.h> 227c478bd9Sstevel@tonic-gate #include <sys/time.h> 237c478bd9Sstevel@tonic-gate #include <sys/file.h> 247c478bd9Sstevel@tonic-gate #if __FreeBSD_version >= 220000 && defined(_KERNEL) 257c478bd9Sstevel@tonic-gate # include <sys/fcntl.h> 267c478bd9Sstevel@tonic-gate # include <sys/filio.h> 277c478bd9Sstevel@tonic-gate #else 287c478bd9Sstevel@tonic-gate # include <sys/ioctl.h> 297c478bd9Sstevel@tonic-gate #endif 307c478bd9Sstevel@tonic-gate #if !defined(_KERNEL) 317c478bd9Sstevel@tonic-gate # include <string.h> 327c478bd9Sstevel@tonic-gate # define _KERNEL 337c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__ 347c478bd9Sstevel@tonic-gate struct file; 357c478bd9Sstevel@tonic-gate # endif 367c478bd9Sstevel@tonic-gate # include <sys/uio.h> 377c478bd9Sstevel@tonic-gate # undef _KERNEL 387c478bd9Sstevel@tonic-gate #endif 397c478bd9Sstevel@tonic-gate #include <sys/socket.h> 40ab25eeb5Syz #if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) 41ab25eeb5Syz # ifdef __osf__ 42ab25eeb5Syz # include <net/radix.h> 43ab25eeb5Syz # endif 44ab25eeb5Syz # include "radix_ipf_local.h" 45ab25eeb5Syz # define _RADIX_H_ 46ab25eeb5Syz #endif 477c478bd9Sstevel@tonic-gate #include <net/if.h> 487c478bd9Sstevel@tonic-gate #if defined(__FreeBSD__) 497c478bd9Sstevel@tonic-gate # include <sys/cdefs.h> 507c478bd9Sstevel@tonic-gate # include <sys/proc.h> 517c478bd9Sstevel@tonic-gate #endif 527c478bd9Sstevel@tonic-gate #if defined(_KERNEL) 537c478bd9Sstevel@tonic-gate # include <sys/systm.h> 547c478bd9Sstevel@tonic-gate # if !defined(__SVR4) && !defined(__svr4__) 557c478bd9Sstevel@tonic-gate # include <sys/mbuf.h> 567c478bd9Sstevel@tonic-gate # endif 577c478bd9Sstevel@tonic-gate #endif 587c478bd9Sstevel@tonic-gate #include <netinet/in.h> 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h" 617c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h" 627c478bd9Sstevel@tonic-gate #include "netinet/ip_pool.h" 637c478bd9Sstevel@tonic-gate #include "netinet/ip_htable.h" 647c478bd9Sstevel@tonic-gate #include "netinet/ip_lookup.h" 65f4b3ec61Sdh #include "netinet/ipf_stack.h" 66ab25eeb5Syz /* END OF INCLUDES */ 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate #if !defined(lint) 69ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.7 2005/06/12 07:18:20 darrenr Exp $"; 707c478bd9Sstevel@tonic-gate #endif 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 73f4b3ec61Sdh static int iplookup_addnode __P((caddr_t, ipf_stack_t *)); 74f4b3ec61Sdh static int iplookup_delnode __P((caddr_t data, ipf_stack_t *)); 75f4b3ec61Sdh static int iplookup_addtable __P((caddr_t, ipf_stack_t *)); 76f4b3ec61Sdh static int iplookup_deltable __P((caddr_t, ipf_stack_t *)); 77f4b3ec61Sdh static int iplookup_stats __P((caddr_t, ipf_stack_t *)); 78f4b3ec61Sdh static int iplookup_flush __P((caddr_t, ipf_stack_t *)); 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate 82ab25eeb5Syz /* ------------------------------------------------------------------------ */ 83ab25eeb5Syz /* Function: iplookup_init */ 84ab25eeb5Syz /* Returns: int - 0 = success, else error */ 85ab25eeb5Syz /* Parameters: Nil */ 86ab25eeb5Syz /* */ 87ab25eeb5Syz /* Initialise all of the subcomponents of the lookup infrstructure. */ 88ab25eeb5Syz /* ------------------------------------------------------------------------ */ 89f4b3ec61Sdh int ip_lookup_init(ifs) 90f4b3ec61Sdh ipf_stack_t *ifs; 917c478bd9Sstevel@tonic-gate { 92ab25eeb5Syz 93f4b3ec61Sdh if (ip_pool_init(ifs) == -1) 947c478bd9Sstevel@tonic-gate return -1; 957c478bd9Sstevel@tonic-gate 96f4b3ec61Sdh RWLOCK_INIT(&ifs->ifs_ip_poolrw, "ip pool rwlock"); 977c478bd9Sstevel@tonic-gate 98f4b3ec61Sdh ifs->ifs_ip_lookup_inited = 1; 99f4b3ec61Sdh ifs->ifs_ipftokenhead = NULL; 100f4b3ec61Sdh ifs->ifs_ipftokentail = &ifs->ifs_ipftokenhead; 1017c478bd9Sstevel@tonic-gate return 0; 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate 105ab25eeb5Syz /* ------------------------------------------------------------------------ */ 106ab25eeb5Syz /* Function: iplookup_unload */ 107ab25eeb5Syz /* Returns: int - 0 = success, else error */ 108ab25eeb5Syz /* Parameters: Nil */ 109ab25eeb5Syz /* */ 110ab25eeb5Syz /* Free up all pool related memory that has been allocated whilst IPFilter */ 111ab25eeb5Syz /* has been running. Also, do any other deinitialisation required such */ 112ab25eeb5Syz /* ip_lookup_init() can be called again, safely. */ 113ab25eeb5Syz /* ------------------------------------------------------------------------ */ 114f4b3ec61Sdh void ip_lookup_unload(ifs) 115f4b3ec61Sdh ipf_stack_t *ifs; 1167c478bd9Sstevel@tonic-gate { 117f4b3ec61Sdh ip_pool_fini(ifs); 118f4b3ec61Sdh fr_htable_unload(ifs); 1197c478bd9Sstevel@tonic-gate 120f4b3ec61Sdh if (ifs->ifs_ip_lookup_inited == 1) { 121f4b3ec61Sdh RW_DESTROY(&ifs->ifs_ip_poolrw); 122f4b3ec61Sdh ifs->ifs_ip_lookup_inited = 0; 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate 127ab25eeb5Syz /* ------------------------------------------------------------------------ */ 128ab25eeb5Syz /* Function: iplookup_ioctl */ 129ab25eeb5Syz /* Returns: int - 0 = success, else error */ 130ab25eeb5Syz /* Parameters: data(IO) - pointer to ioctl data to be copied to/from user */ 131ab25eeb5Syz /* space. */ 132ab25eeb5Syz /* cmd(I) - ioctl command number */ 133ab25eeb5Syz /* mode(I) - file mode bits used with open */ 134ab25eeb5Syz /* */ 135ab25eeb5Syz /* Handle ioctl commands sent to the ioctl device. For the most part, this */ 136ab25eeb5Syz /* involves just calling another function to handle the specifics of each */ 137ab25eeb5Syz /* command. */ 138ab25eeb5Syz /* ------------------------------------------------------------------------ */ 139f4b3ec61Sdh int ip_lookup_ioctl(data, cmd, mode, uid, ctx, ifs) 1407c478bd9Sstevel@tonic-gate caddr_t data; 141ab25eeb5Syz ioctlcmd_t cmd; 142f4b3ec61Sdh int mode, uid; 143f4b3ec61Sdh void *ctx; 144f4b3ec61Sdh ipf_stack_t *ifs; 1457c478bd9Sstevel@tonic-gate { 1467c478bd9Sstevel@tonic-gate int err; 147ab25eeb5Syz SPL_INT(s); 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate mode = mode; /* LINT */ 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate SPL_NET(s); 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate switch (cmd) 1547c478bd9Sstevel@tonic-gate { 1557c478bd9Sstevel@tonic-gate case SIOCLOOKUPADDNODE : 156ab25eeb5Syz case SIOCLOOKUPADDNODEW : 157f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 158f4b3ec61Sdh err = iplookup_addnode(data, ifs); 159f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 1607c478bd9Sstevel@tonic-gate break; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate case SIOCLOOKUPDELNODE : 163ab25eeb5Syz case SIOCLOOKUPDELNODEW : 164f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 165f4b3ec61Sdh err = iplookup_delnode(data, ifs); 166f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 1677c478bd9Sstevel@tonic-gate break; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate case SIOCLOOKUPADDTABLE : 170f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 171f4b3ec61Sdh err = iplookup_addtable(data, ifs); 172f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 1737c478bd9Sstevel@tonic-gate break; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate case SIOCLOOKUPDELTABLE : 176f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 177f4b3ec61Sdh err = iplookup_deltable(data, ifs); 178f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 1797c478bd9Sstevel@tonic-gate break; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate case SIOCLOOKUPSTAT : 182ab25eeb5Syz case SIOCLOOKUPSTATW : 183f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 184f4b3ec61Sdh err = iplookup_stats(data, ifs); 185f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 1867c478bd9Sstevel@tonic-gate break; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate case SIOCLOOKUPFLUSH : 189f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 190f4b3ec61Sdh err = iplookup_flush(data, ifs); 191f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 192f4b3ec61Sdh break; 193f4b3ec61Sdh 194f4b3ec61Sdh case SIOCLOOKUPITER : 195f4b3ec61Sdh err = ip_lookup_iterate(data, uid, ctx, ifs); 1967c478bd9Sstevel@tonic-gate break; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate default : 1997c478bd9Sstevel@tonic-gate err = EINVAL; 2007c478bd9Sstevel@tonic-gate break; 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate SPL_X(s); 2037c478bd9Sstevel@tonic-gate return err; 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate 207ab25eeb5Syz /* ------------------------------------------------------------------------ */ 208ab25eeb5Syz /* Function: iplookup_addnode */ 209ab25eeb5Syz /* Returns: int - 0 = success, else error */ 210ab25eeb5Syz /* Parameters: data(I) - pointer to data from ioctl call */ 211ab25eeb5Syz /* */ 212ab25eeb5Syz /* Add a new data node to a lookup structure. First, check to see if the */ 213ab25eeb5Syz /* parent structure refered to by name exists and if it does, then go on to */ 214ab25eeb5Syz /* add a node to it. */ 215ab25eeb5Syz /* ------------------------------------------------------------------------ */ 216f4b3ec61Sdh static int iplookup_addnode(data, ifs) 2177c478bd9Sstevel@tonic-gate caddr_t data; 218f4b3ec61Sdh ipf_stack_t *ifs; 2197c478bd9Sstevel@tonic-gate { 2207c478bd9Sstevel@tonic-gate ip_pool_node_t node, *m; 2217c478bd9Sstevel@tonic-gate iplookupop_t op; 2227c478bd9Sstevel@tonic-gate iphtable_t *iph; 2237c478bd9Sstevel@tonic-gate iphtent_t hte; 2247c478bd9Sstevel@tonic-gate ip_pool_t *p; 2257c478bd9Sstevel@tonic-gate int err; 2267c478bd9Sstevel@tonic-gate 227*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 228*bb1d9de5SJohn Ojemann if (err != 0) 229*bb1d9de5SJohn Ojemann return EFAULT; 230*bb1d9de5SJohn Ojemann 2317c478bd9Sstevel@tonic-gate op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate switch (op.iplo_type) 2347c478bd9Sstevel@tonic-gate { 2357c478bd9Sstevel@tonic-gate case IPLT_POOL : 2367c478bd9Sstevel@tonic-gate if (op.iplo_size != sizeof(node)) 2377c478bd9Sstevel@tonic-gate return EINVAL; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate err = COPYIN(op.iplo_struct, &node, sizeof(node)); 2407c478bd9Sstevel@tonic-gate if (err != 0) 2417c478bd9Sstevel@tonic-gate return EFAULT; 2427c478bd9Sstevel@tonic-gate 243f4b3ec61Sdh p = ip_pool_find(op.iplo_unit, op.iplo_name, ifs); 2447c478bd9Sstevel@tonic-gate if (p == NULL) 2457c478bd9Sstevel@tonic-gate return ESRCH; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* 2487c478bd9Sstevel@tonic-gate * add an entry to a pool - return an error if it already 2497c478bd9Sstevel@tonic-gate * exists remove an entry from a pool - if it exists 2507c478bd9Sstevel@tonic-gate * - in both cases, the pool *must* exist! 2517c478bd9Sstevel@tonic-gate */ 2527663b816Sml m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask); 2537c478bd9Sstevel@tonic-gate if (m) 2547c478bd9Sstevel@tonic-gate return EEXIST; 2557663b816Sml err = ip_pool_insert(p, &node.ipn_addr, 256f4b3ec61Sdh &node.ipn_mask, node.ipn_info, ifs); 2577c478bd9Sstevel@tonic-gate break; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate case IPLT_HASH : 2607c478bd9Sstevel@tonic-gate if (op.iplo_size != sizeof(hte)) 2617c478bd9Sstevel@tonic-gate return EINVAL; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate err = COPYIN(op.iplo_struct, &hte, sizeof(hte)); 2647c478bd9Sstevel@tonic-gate if (err != 0) 2657c478bd9Sstevel@tonic-gate return EFAULT; 2667c478bd9Sstevel@tonic-gate 267f4b3ec61Sdh iph = fr_findhtable(op.iplo_unit, op.iplo_name, ifs); 2687c478bd9Sstevel@tonic-gate if (iph == NULL) 2697c478bd9Sstevel@tonic-gate return ESRCH; 270f4b3ec61Sdh err = fr_addhtent(iph, &hte, ifs); 2717c478bd9Sstevel@tonic-gate break; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate default : 2747c478bd9Sstevel@tonic-gate err = EINVAL; 2757c478bd9Sstevel@tonic-gate break; 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate return err; 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate 281ab25eeb5Syz /* ------------------------------------------------------------------------ */ 282ab25eeb5Syz /* Function: iplookup_delnode */ 283ab25eeb5Syz /* Returns: int - 0 = success, else error */ 284ab25eeb5Syz /* Parameters: data(I) - pointer to data from ioctl call */ 285ab25eeb5Syz /* */ 286ab25eeb5Syz /* Delete a node from a lookup table by first looking for the table it is */ 287ab25eeb5Syz /* in and then deleting the entry that gets found. */ 288ab25eeb5Syz /* ------------------------------------------------------------------------ */ 289f4b3ec61Sdh static int iplookup_delnode(data, ifs) 2907c478bd9Sstevel@tonic-gate caddr_t data; 291f4b3ec61Sdh ipf_stack_t *ifs; 2927c478bd9Sstevel@tonic-gate { 2937c478bd9Sstevel@tonic-gate ip_pool_node_t node, *m; 2947c478bd9Sstevel@tonic-gate iplookupop_t op; 2957c478bd9Sstevel@tonic-gate iphtable_t *iph; 2967c478bd9Sstevel@tonic-gate iphtent_t hte; 2977c478bd9Sstevel@tonic-gate ip_pool_t *p; 2987c478bd9Sstevel@tonic-gate int err; 2997c478bd9Sstevel@tonic-gate 300*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 301*bb1d9de5SJohn Ojemann if (err != 0) 302*bb1d9de5SJohn Ojemann return EFAULT; 303ab25eeb5Syz 3047c478bd9Sstevel@tonic-gate op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate switch (op.iplo_type) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate case IPLT_POOL : 3097c478bd9Sstevel@tonic-gate if (op.iplo_size != sizeof(node)) 3107c478bd9Sstevel@tonic-gate return EINVAL; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate err = COPYIN(op.iplo_struct, &node, sizeof(node)); 3137c478bd9Sstevel@tonic-gate if (err != 0) 3147c478bd9Sstevel@tonic-gate return EFAULT; 3157c478bd9Sstevel@tonic-gate 316f4b3ec61Sdh p = ip_pool_find(op.iplo_unit, op.iplo_name, ifs); 3177c478bd9Sstevel@tonic-gate if (!p) 3187c478bd9Sstevel@tonic-gate return ESRCH; 3197c478bd9Sstevel@tonic-gate 3207663b816Sml m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask); 3217c478bd9Sstevel@tonic-gate if (m == NULL) 3227c478bd9Sstevel@tonic-gate return ENOENT; 323f4b3ec61Sdh err = ip_pool_remove(p, m, ifs); 3247c478bd9Sstevel@tonic-gate break; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate case IPLT_HASH : 3277c478bd9Sstevel@tonic-gate if (op.iplo_size != sizeof(hte)) 3287c478bd9Sstevel@tonic-gate return EINVAL; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate err = COPYIN(op.iplo_struct, &hte, sizeof(hte)); 3317c478bd9Sstevel@tonic-gate if (err != 0) 3327c478bd9Sstevel@tonic-gate return EFAULT; 3337c478bd9Sstevel@tonic-gate 334f4b3ec61Sdh iph = fr_findhtable(op.iplo_unit, op.iplo_name, ifs); 3357c478bd9Sstevel@tonic-gate if (iph == NULL) 3367c478bd9Sstevel@tonic-gate return ESRCH; 337f4b3ec61Sdh err = fr_delhtent(iph, &hte, ifs); 3387c478bd9Sstevel@tonic-gate break; 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate default : 3417c478bd9Sstevel@tonic-gate err = EINVAL; 3427c478bd9Sstevel@tonic-gate break; 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate return err; 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate 348ab25eeb5Syz /* ------------------------------------------------------------------------ */ 349ab25eeb5Syz /* Function: iplookup_addtable */ 350ab25eeb5Syz /* Returns: int - 0 = success, else error */ 351ab25eeb5Syz /* Parameters: data(I) - pointer to data from ioctl call */ 352ab25eeb5Syz /* */ 353ab25eeb5Syz /* Create a new lookup table, if one doesn't already exist using the name */ 354ab25eeb5Syz /* for this one. */ 355ab25eeb5Syz /* ------------------------------------------------------------------------ */ 356f4b3ec61Sdh static int iplookup_addtable(data, ifs) 3577c478bd9Sstevel@tonic-gate caddr_t data; 358f4b3ec61Sdh ipf_stack_t *ifs; 3597c478bd9Sstevel@tonic-gate { 3607c478bd9Sstevel@tonic-gate iplookupop_t op; 3617c478bd9Sstevel@tonic-gate int err; 3627c478bd9Sstevel@tonic-gate 363*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 364*bb1d9de5SJohn Ojemann if (err != 0) 365*bb1d9de5SJohn Ojemann return EFAULT; 366ab25eeb5Syz 3677c478bd9Sstevel@tonic-gate op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate switch (op.iplo_type) 3707c478bd9Sstevel@tonic-gate { 3717c478bd9Sstevel@tonic-gate case IPLT_POOL : 372f4b3ec61Sdh if (ip_pool_find(op.iplo_unit, op.iplo_name, ifs) != NULL) 3737c478bd9Sstevel@tonic-gate err = EEXIST; 3747c478bd9Sstevel@tonic-gate else 375f4b3ec61Sdh err = ip_pool_create(&op, ifs); 3767c478bd9Sstevel@tonic-gate break; 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate case IPLT_HASH : 379f4b3ec61Sdh if (fr_findhtable(op.iplo_unit, op.iplo_name, ifs) != NULL) 3807c478bd9Sstevel@tonic-gate err = EEXIST; 3817c478bd9Sstevel@tonic-gate else 382f4b3ec61Sdh err = fr_newhtable(&op, ifs); 3837c478bd9Sstevel@tonic-gate break; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate default : 3867c478bd9Sstevel@tonic-gate err = EINVAL; 3877c478bd9Sstevel@tonic-gate break; 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate return err; 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 3947c478bd9Sstevel@tonic-gate /* Function: iplookup_deltable */ 3957c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 3967c478bd9Sstevel@tonic-gate /* Parameters: data(I) - pointer to data from ioctl call */ 3977c478bd9Sstevel@tonic-gate /* */ 3987c478bd9Sstevel@tonic-gate /* Decodes ioctl request to remove a particular hash table or pool and */ 3997c478bd9Sstevel@tonic-gate /* calls the relevant function to do the cleanup. */ 4007c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 401f4b3ec61Sdh static int iplookup_deltable(data, ifs) 4027c478bd9Sstevel@tonic-gate caddr_t data; 403f4b3ec61Sdh ipf_stack_t *ifs; 4047c478bd9Sstevel@tonic-gate { 4057c478bd9Sstevel@tonic-gate iplookupop_t op; 4067c478bd9Sstevel@tonic-gate int err; 4077c478bd9Sstevel@tonic-gate 408*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 409*bb1d9de5SJohn Ojemann if (err != 0) 410*bb1d9de5SJohn Ojemann return EFAULT; 411*bb1d9de5SJohn Ojemann 4127c478bd9Sstevel@tonic-gate op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate if (op.iplo_arg & IPLT_ANON) 4157c478bd9Sstevel@tonic-gate op.iplo_arg &= IPLT_ANON; 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* 4187c478bd9Sstevel@tonic-gate * create a new pool - fail if one already exists with 4197c478bd9Sstevel@tonic-gate * the same # 4207c478bd9Sstevel@tonic-gate */ 4217c478bd9Sstevel@tonic-gate switch (op.iplo_type) 4227c478bd9Sstevel@tonic-gate { 4237c478bd9Sstevel@tonic-gate case IPLT_POOL : 424f4b3ec61Sdh err = ip_pool_destroy(&op, ifs); 4257c478bd9Sstevel@tonic-gate break; 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate case IPLT_HASH : 428f4b3ec61Sdh err = fr_removehtable(&op, ifs); 4297c478bd9Sstevel@tonic-gate break; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate default : 4327c478bd9Sstevel@tonic-gate err = EINVAL; 4337c478bd9Sstevel@tonic-gate break; 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate return err; 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 4407c478bd9Sstevel@tonic-gate /* Function: iplookup_stats */ 4417c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 4427c478bd9Sstevel@tonic-gate /* Parameters: data(I) - pointer to data from ioctl call */ 4437c478bd9Sstevel@tonic-gate /* */ 4447c478bd9Sstevel@tonic-gate /* Copy statistical information from inside the kernel back to user space. */ 4457c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 446f4b3ec61Sdh static int iplookup_stats(data, ifs) 4477c478bd9Sstevel@tonic-gate caddr_t data; 448f4b3ec61Sdh ipf_stack_t *ifs; 4497c478bd9Sstevel@tonic-gate { 4507c478bd9Sstevel@tonic-gate iplookupop_t op; 4517663b816Sml int err; 4527c478bd9Sstevel@tonic-gate 453*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 454*bb1d9de5SJohn Ojemann if (err != 0) 455*bb1d9de5SJohn Ojemann return EFAULT; 4567c478bd9Sstevel@tonic-gate 4577663b816Sml switch (op.iplo_type) 4587663b816Sml { 4597663b816Sml case IPLT_POOL : 460f4b3ec61Sdh err = ip_pool_statistics(&op, ifs); 4617663b816Sml break; 4627663b816Sml 4637663b816Sml case IPLT_HASH : 464f4b3ec61Sdh err = fr_gethtablestat(&op, ifs); 4657663b816Sml break; 4667c478bd9Sstevel@tonic-gate 4677663b816Sml default : 4687663b816Sml err = EINVAL; 4697663b816Sml break; 4707663b816Sml } 4717c478bd9Sstevel@tonic-gate return err; 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 4767c478bd9Sstevel@tonic-gate /* Function: iplookup_flush */ 4777c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else error */ 4787c478bd9Sstevel@tonic-gate /* Parameters: data(I) - pointer to data from ioctl call */ 4797c478bd9Sstevel@tonic-gate /* */ 4807c478bd9Sstevel@tonic-gate /* A flush is called when we want to flush all the nodes from a particular */ 4817c478bd9Sstevel@tonic-gate /* entry in the hash table/pool or want to remove all groups from those. */ 4827c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 483f4b3ec61Sdh static int iplookup_flush(data, ifs) 4847c478bd9Sstevel@tonic-gate caddr_t data; 485f4b3ec61Sdh ipf_stack_t *ifs; 4867c478bd9Sstevel@tonic-gate { 487ab25eeb5Syz int err, unit, num, type; 488ab25eeb5Syz iplookupflush_t flush; 4897c478bd9Sstevel@tonic-gate 490*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &flush, sizeof(flush)); 491*bb1d9de5SJohn Ojemann if (err != 0) 492*bb1d9de5SJohn Ojemann return EFAULT; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate unit = flush.iplf_unit; 4977c478bd9Sstevel@tonic-gate if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) 4987c478bd9Sstevel@tonic-gate return EINVAL; 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate type = flush.iplf_type; 5017c478bd9Sstevel@tonic-gate err = EINVAL; 5027c478bd9Sstevel@tonic-gate num = 0; 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate if (type == IPLT_POOL || type == IPLT_ALL) { 5057c478bd9Sstevel@tonic-gate err = 0; 506f4b3ec61Sdh num = ip_pool_flush(&flush, ifs); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate if (type == IPLT_HASH || type == IPLT_ALL) { 5107c478bd9Sstevel@tonic-gate err = 0; 511f4b3ec61Sdh num += fr_flushhtable(&flush, ifs); 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate if (err == 0) { 5157c478bd9Sstevel@tonic-gate flush.iplf_count = num; 5167c478bd9Sstevel@tonic-gate err = COPYOUT(&flush, data, sizeof(flush)); 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate return err; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate 522f4b3ec61Sdh 523f4b3ec61Sdh void ip_lookup_deref(type, ptr, ifs) 5247c478bd9Sstevel@tonic-gate int type; 5257c478bd9Sstevel@tonic-gate void *ptr; 526f4b3ec61Sdh ipf_stack_t *ifs; 5277c478bd9Sstevel@tonic-gate { 5287c478bd9Sstevel@tonic-gate if (ptr == NULL) 5297c478bd9Sstevel@tonic-gate return; 5307c478bd9Sstevel@tonic-gate 531f4b3ec61Sdh WRITE_ENTER(&ifs->ifs_ip_poolrw); 5327c478bd9Sstevel@tonic-gate switch (type) 5337c478bd9Sstevel@tonic-gate { 5347c478bd9Sstevel@tonic-gate case IPLT_POOL : 535f4b3ec61Sdh ip_pool_deref(ptr, ifs); 536f4b3ec61Sdh break; 537f4b3ec61Sdh 538f4b3ec61Sdh case IPLT_HASH : 539f4b3ec61Sdh fr_derefhtable(ptr, ifs); 540f4b3ec61Sdh break; 541f4b3ec61Sdh } 542f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 543f4b3ec61Sdh } 544f4b3ec61Sdh 545f4b3ec61Sdh 546f4b3ec61Sdh int ip_lookup_iterate(data, uid, ctx, ifs) 547f4b3ec61Sdh void *data; 548f4b3ec61Sdh int uid; 549f4b3ec61Sdh void *ctx; 550f4b3ec61Sdh ipf_stack_t *ifs; 551f4b3ec61Sdh { 552f4b3ec61Sdh ipflookupiter_t iter; 553f4b3ec61Sdh ipftoken_t *token; 554f4b3ec61Sdh int err; 555f4b3ec61Sdh 556f4b3ec61Sdh err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER); 557f4b3ec61Sdh if (err != 0) { 558f4b3ec61Sdh #ifdef _KERNEL 559f4b3ec61Sdh (void) printf("fr_inobj\n"); 560f4b3ec61Sdh #endif 561f4b3ec61Sdh return err; 562f4b3ec61Sdh } 563f4b3ec61Sdh 564f4b3ec61Sdh if (iter.ili_unit < 0 || iter.ili_unit > IPL_LOGMAX) { 565f4b3ec61Sdh #ifdef _KERNEL 566f4b3ec61Sdh (void) printf("unit=%d\n", iter.ili_unit); 567f4b3ec61Sdh #endif 568f4b3ec61Sdh return EINVAL; 569f4b3ec61Sdh } 570f4b3ec61Sdh 571f4b3ec61Sdh if (iter.ili_ival != IPFGENITER_LOOKUP) { 572f4b3ec61Sdh #ifdef _KERNEL 573f4b3ec61Sdh (void) printf("ival=%d\n", iter.ili_ival); 574f4b3ec61Sdh #endif 575f4b3ec61Sdh return EINVAL; 576f4b3ec61Sdh } 577f4b3ec61Sdh 578f4b3ec61Sdh token = ipf_findtoken(iter.ili_key, uid, ctx, ifs); 579f4b3ec61Sdh if (token == NULL) { 580f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ipf_tokens); 581f4b3ec61Sdh return ESRCH; 582f4b3ec61Sdh } 583f4b3ec61Sdh 584f4b3ec61Sdh switch (iter.ili_type) 585f4b3ec61Sdh { 586f4b3ec61Sdh case IPLT_POOL : 587f4b3ec61Sdh err = ip_pool_getnext(token, &iter, ifs); 588f4b3ec61Sdh break; 589f4b3ec61Sdh case IPLT_HASH : 590f4b3ec61Sdh err = fr_htable_getnext(token, &iter, ifs); 591f4b3ec61Sdh break; 592f4b3ec61Sdh default : 593f4b3ec61Sdh #ifdef _KERNEL 594f4b3ec61Sdh (void) printf("type=%d\n", iter.ili_type); 595f4b3ec61Sdh #endif 596f4b3ec61Sdh err = EINVAL; 5977c478bd9Sstevel@tonic-gate break; 598f4b3ec61Sdh } 599f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ipf_tokens); 600ab25eeb5Syz 601f4b3ec61Sdh return err; 602f4b3ec61Sdh } 603f4b3ec61Sdh 604f4b3ec61Sdh 605f4b3ec61Sdh void ip_lookup_iterderef(type, data, ifs) 606f4b3ec61Sdh u_32_t type; 607f4b3ec61Sdh void *data; 608f4b3ec61Sdh ipf_stack_t *ifs; 609f4b3ec61Sdh { 610f4b3ec61Sdh iplookupiterkey_t key; 611f4b3ec61Sdh 612f4b3ec61Sdh key.ilik_key = type; 613f4b3ec61Sdh 614f4b3ec61Sdh if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP) 615f4b3ec61Sdh return; 616f4b3ec61Sdh 617f4b3ec61Sdh switch (key.ilik_unstr.ilik_type) 618f4b3ec61Sdh { 6197c478bd9Sstevel@tonic-gate case IPLT_HASH : 620f4b3ec61Sdh fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype, 621f4b3ec61Sdh (int)key.ilik_unstr.ilik_unit, data, ifs); 622f4b3ec61Sdh break; 623f4b3ec61Sdh case IPLT_POOL : 624f4b3ec61Sdh ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype, 625f4b3ec61Sdh (int)key.ilik_unstr.ilik_unit, data, ifs); 6267c478bd9Sstevel@tonic-gate break; 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate #else /* IPFILTER_LOOKUP */ 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 634f4b3ec61Sdh int ip_lookup_ioctl(data, cmd, mode, uid, ifs) 6357c478bd9Sstevel@tonic-gate caddr_t data; 636ab25eeb5Syz ioctlcmd_t cmd; 637f4b3ec61Sdh int mode, uid; 638f4b3ec61Sdh ipf_stack_t *ifs; 6397c478bd9Sstevel@tonic-gate { 6407c478bd9Sstevel@tonic-gate return EIO; 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOOKUP */ 643