|  | /* | 
|  | * Copyright (C) 2002-2003 by Darren Reed. | 
|  | * | 
|  | * See the IPFILTER.LICENCE file for details on licencing. | 
|  | */ | 
|  | #if defined(KERNEL) || defined(_KERNEL) | 
|  | # undef KERNEL | 
|  | # undef _KERNEL | 
|  | # define        KERNEL	1 | 
|  | # define        _KERNEL	1 | 
|  | #endif | 
|  | #if defined(__osf__) | 
|  | # define _PROTO_NET_H_ | 
|  | #endif | 
|  | #include <sys/param.h> | 
|  | #include <sys/errno.h> | 
|  | #include <sys/types.h> | 
|  | #include <sys/time.h> | 
|  | #include <sys/file.h> | 
|  | #if __FreeBSD_version >= 220000 && defined(_KERNEL) | 
|  | # include <sys/fcntl.h> | 
|  | # include <sys/filio.h> | 
|  | #else | 
|  | # include <sys/ioctl.h> | 
|  | #endif | 
|  | #if !defined(_KERNEL) | 
|  | # include <string.h> | 
|  | # define _KERNEL | 
|  | # ifdef __OpenBSD__ | 
|  | struct file; | 
|  | # endif | 
|  | # include <sys/uio.h> | 
|  | # undef _KERNEL | 
|  | #endif | 
|  | #include <sys/socket.h> | 
|  | #if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) | 
|  | # include "radix_ipf_local.h" | 
|  | # define _RADIX_H_ | 
|  | #endif | 
|  | #include <net/if.h> | 
|  | #if defined(__FreeBSD__) | 
|  | #  include <sys/cdefs.h> | 
|  | #  include <sys/proc.h> | 
|  | #endif | 
|  | #if defined(_KERNEL) | 
|  | # include <sys/systm.h> | 
|  | # if !defined(__SVR4) && !defined(__svr4__) | 
|  | #  include <sys/mbuf.h> | 
|  | # endif | 
|  | #endif | 
|  | #include <netinet/in.h> | 
|  |  | 
|  | #include "netinet/ip_compat.h" | 
|  | #include "netinet/ip_fil.h" | 
|  | #include "netinet/ip_pool.h" | 
|  | #include "netinet/ip_htable.h" | 
|  | #include "netinet/ip_lookup.h" | 
|  | /* END OF INCLUDES */ | 
|  |  | 
|  | #if !defined(lint) | 
|  | static const char rcsid[] = "@(#)$Id$"; | 
|  | #endif | 
|  |  | 
|  | #ifdef	IPFILTER_LOOKUP | 
|  | int	ip_lookup_inited = 0; | 
|  |  | 
|  | static int iplookup_addnode __P((caddr_t)); | 
|  | static int iplookup_delnode __P((caddr_t data)); | 
|  | static int iplookup_addtable __P((caddr_t)); | 
|  | static int iplookup_deltable __P((caddr_t)); | 
|  | static int iplookup_stats __P((caddr_t)); | 
|  | static int iplookup_flush __P((caddr_t)); | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_init                                               */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  Nil                                                         */ | 
|  | /*                                                                          */ | 
|  | /* Initialise all of the subcomponents of the lookup infrstructure.         */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | int ip_lookup_init() | 
|  | { | 
|  |  | 
|  | if (ip_pool_init() == -1) | 
|  | return -1; | 
|  |  | 
|  | RWLOCK_INIT(&ip_poolrw, "ip pool rwlock"); | 
|  |  | 
|  | ip_lookup_inited = 1; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_unload                                             */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  Nil                                                         */ | 
|  | /*                                                                          */ | 
|  | /* Free up all pool related memory that has been allocated whilst IPFilter  */ | 
|  | /* has been running.  Also, do any other deinitialisation required such     */ | 
|  | /* ip_lookup_init() can be called again, safely.                            */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | void ip_lookup_unload() | 
|  | { | 
|  | ip_pool_fini(); | 
|  | fr_htable_unload(); | 
|  |  | 
|  | if (ip_lookup_inited == 1) { | 
|  | RW_DESTROY(&ip_poolrw); | 
|  | ip_lookup_inited = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_ioctl                                              */ | 
|  | /* Returns:     int      - 0 = success, else error                          */ | 
|  | /* Parameters:  data(IO) - pointer to ioctl data to be copied to/from user  */ | 
|  | /*                         space.                                           */ | 
|  | /*              cmd(I)   - ioctl command number                             */ | 
|  | /*              mode(I)  - file mode bits used with open                    */ | 
|  | /*                                                                          */ | 
|  | /* Handle ioctl commands sent to the ioctl device.  For the most part, this */ | 
|  | /* involves just calling another function to handle the specifics of each   */ | 
|  | /* command.                                                                 */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | int ip_lookup_ioctl(data, cmd, mode, uid, ctx) | 
|  | caddr_t data; | 
|  | ioctlcmd_t cmd; | 
|  | int mode, uid; | 
|  | void *ctx; | 
|  | { | 
|  | int err; | 
|  | SPL_INT(s); | 
|  |  | 
|  | mode = mode;	/* LINT */ | 
|  |  | 
|  | SPL_NET(s); | 
|  |  | 
|  | switch (cmd) | 
|  | { | 
|  | case SIOCLOOKUPADDNODE : | 
|  | case SIOCLOOKUPADDNODEW : | 
|  | WRITE_ENTER(&ip_poolrw); | 
|  | err = iplookup_addnode(data); | 
|  | RWLOCK_EXIT(&ip_poolrw); | 
|  | break; | 
|  |  | 
|  | case SIOCLOOKUPDELNODE : | 
|  | case SIOCLOOKUPDELNODEW : | 
|  | WRITE_ENTER(&ip_poolrw); | 
|  | err = iplookup_delnode(data); | 
|  | RWLOCK_EXIT(&ip_poolrw); | 
|  | break; | 
|  |  | 
|  | case SIOCLOOKUPADDTABLE : | 
|  | WRITE_ENTER(&ip_poolrw); | 
|  | err = iplookup_addtable(data); | 
|  | RWLOCK_EXIT(&ip_poolrw); | 
|  | break; | 
|  |  | 
|  | case SIOCLOOKUPDELTABLE : | 
|  | WRITE_ENTER(&ip_poolrw); | 
|  | err = iplookup_deltable(data); | 
|  | RWLOCK_EXIT(&ip_poolrw); | 
|  | break; | 
|  |  | 
|  | case SIOCLOOKUPSTAT : | 
|  | case SIOCLOOKUPSTATW : | 
|  | WRITE_ENTER(&ip_poolrw); | 
|  | err = iplookup_stats(data); | 
|  | RWLOCK_EXIT(&ip_poolrw); | 
|  | break; | 
|  |  | 
|  | case SIOCLOOKUPFLUSH : | 
|  | WRITE_ENTER(&ip_poolrw); | 
|  | err = iplookup_flush(data); | 
|  | RWLOCK_EXIT(&ip_poolrw); | 
|  | break; | 
|  |  | 
|  | case SIOCLOOKUPITER : | 
|  | err = ip_lookup_iterate(data, uid, ctx); | 
|  | break; | 
|  |  | 
|  | default : | 
|  | err = EINVAL; | 
|  | break; | 
|  | } | 
|  | SPL_X(s); | 
|  | return err; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_addnode                                            */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  data(I) - pointer to data from ioctl call                   */ | 
|  | /*                                                                          */ | 
|  | /* Add a new data node to a lookup structure.  First, check to see if the   */ | 
|  | /* parent structure refered to by name exists and if it does, then go on to */ | 
|  | /* add a node to it.                                                        */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | static int iplookup_addnode(data) | 
|  | caddr_t data; | 
|  | { | 
|  | ip_pool_node_t node, *m; | 
|  | iplookupop_t op; | 
|  | iphtable_t *iph; | 
|  | iphtent_t hte; | 
|  | ip_pool_t *p; | 
|  | int err; | 
|  |  | 
|  | err = BCOPYIN(data, &op, sizeof(op)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) | 
|  | return EINVAL; | 
|  |  | 
|  | op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; | 
|  |  | 
|  | switch (op.iplo_type) | 
|  | { | 
|  | case IPLT_POOL : | 
|  | if (op.iplo_size != sizeof(node)) | 
|  | return EINVAL; | 
|  |  | 
|  | err = COPYIN(op.iplo_struct, &node, sizeof(node)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | p = ip_pool_find(op.iplo_unit, op.iplo_name); | 
|  | if (p == NULL) | 
|  | return ESRCH; | 
|  |  | 
|  | /* | 
|  | * add an entry to a pool - return an error if it already | 
|  | * exists remove an entry from a pool - if it exists | 
|  | * - in both cases, the pool *must* exist! | 
|  | */ | 
|  | m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask); | 
|  | if (m) | 
|  | return EEXIST; | 
|  | err = ip_pool_insert(p, &node.ipn_addr.adf_addr, | 
|  | &node.ipn_mask.adf_addr, node.ipn_info); | 
|  | break; | 
|  |  | 
|  | case IPLT_HASH : | 
|  | if (op.iplo_size != sizeof(hte)) | 
|  | return EINVAL; | 
|  |  | 
|  | err = COPYIN(op.iplo_struct, &hte, sizeof(hte)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | iph = fr_findhtable(op.iplo_unit, op.iplo_name); | 
|  | if (iph == NULL) | 
|  | return ESRCH; | 
|  | err = fr_addhtent(iph, &hte); | 
|  | break; | 
|  |  | 
|  | default : | 
|  | err = EINVAL; | 
|  | break; | 
|  | } | 
|  | return err; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_delnode                                            */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  data(I) - pointer to data from ioctl call                   */ | 
|  | /*                                                                          */ | 
|  | /* Delete a node from a lookup table by first looking for the table it is   */ | 
|  | /* in and then deleting the entry that gets found.                          */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | static int iplookup_delnode(data) | 
|  | caddr_t data; | 
|  | { | 
|  | ip_pool_node_t node, *m; | 
|  | iplookupop_t op; | 
|  | iphtable_t *iph; | 
|  | iphtent_t hte; | 
|  | ip_pool_t *p; | 
|  | int err; | 
|  |  | 
|  | err = BCOPYIN(data, &op, sizeof(op)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) | 
|  | return EINVAL; | 
|  |  | 
|  | op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; | 
|  |  | 
|  | switch (op.iplo_type) | 
|  | { | 
|  | case IPLT_POOL : | 
|  | if (op.iplo_size != sizeof(node)) | 
|  | return EINVAL; | 
|  |  | 
|  | err = COPYIN(op.iplo_struct, &node, sizeof(node)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | p = ip_pool_find(op.iplo_unit, op.iplo_name); | 
|  | if (!p) | 
|  | return ESRCH; | 
|  |  | 
|  | m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask); | 
|  | if (m == NULL) | 
|  | return ENOENT; | 
|  | err = ip_pool_remove(p, m); | 
|  | break; | 
|  |  | 
|  | case IPLT_HASH : | 
|  | if (op.iplo_size != sizeof(hte)) | 
|  | return EINVAL; | 
|  |  | 
|  | err = COPYIN(op.iplo_struct, &hte, sizeof(hte)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | iph = fr_findhtable(op.iplo_unit, op.iplo_name); | 
|  | if (iph == NULL) | 
|  | return ESRCH; | 
|  | err = fr_delhtent(iph, &hte); | 
|  | break; | 
|  |  | 
|  | default : | 
|  | err = EINVAL; | 
|  | break; | 
|  | } | 
|  | return err; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_addtable                                           */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  data(I) - pointer to data from ioctl call                   */ | 
|  | /*                                                                          */ | 
|  | /* Create a new lookup table, if one doesn't already exist using the name   */ | 
|  | /* for this one.                                                            */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | static int iplookup_addtable(data) | 
|  | caddr_t data; | 
|  | { | 
|  | iplookupop_t op; | 
|  | int err; | 
|  |  | 
|  | err = BCOPYIN(data, &op, sizeof(op)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) | 
|  | return EINVAL; | 
|  |  | 
|  | op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; | 
|  |  | 
|  | switch (op.iplo_type) | 
|  | { | 
|  | case IPLT_POOL : | 
|  | if (ip_pool_find(op.iplo_unit, op.iplo_name) != NULL) | 
|  | err = EEXIST; | 
|  | else | 
|  | err = ip_pool_create(&op); | 
|  | break; | 
|  |  | 
|  | case IPLT_HASH : | 
|  | if (fr_findhtable(op.iplo_unit, op.iplo_name) != NULL) | 
|  | err = EEXIST; | 
|  | else | 
|  | err = fr_newhtable(&op); | 
|  | break; | 
|  |  | 
|  | default : | 
|  | err = EINVAL; | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * For anonymous pools, copy back the operation struct because in the | 
|  | * case of success it will contain the new table's name. | 
|  | */ | 
|  | if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) { | 
|  | err = BCOPYOUT(&op, data, sizeof(op)); | 
|  | if (err != 0) | 
|  | err = EFAULT; | 
|  | } | 
|  |  | 
|  | return err; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_deltable                                           */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  data(I) - pointer to data from ioctl call                   */ | 
|  | /*                                                                          */ | 
|  | /* Decodes ioctl request to remove a particular hash table or pool and      */ | 
|  | /* calls the relevant function to do the cleanup.                           */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | static int iplookup_deltable(data) | 
|  | caddr_t data; | 
|  | { | 
|  | iplookupop_t op; | 
|  | int err; | 
|  |  | 
|  | err = BCOPYIN(data, &op, sizeof(op)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) | 
|  | return EINVAL; | 
|  |  | 
|  | op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; | 
|  |  | 
|  | /* | 
|  | * create a new pool - fail if one already exists with | 
|  | * the same # | 
|  | */ | 
|  | switch (op.iplo_type) | 
|  | { | 
|  | case IPLT_POOL : | 
|  | err = ip_pool_destroy(op.iplo_unit, op.iplo_name); | 
|  | break; | 
|  |  | 
|  | case IPLT_HASH : | 
|  | err = fr_removehtable(op.iplo_unit, op.iplo_name); | 
|  | break; | 
|  |  | 
|  | default : | 
|  | err = EINVAL; | 
|  | break; | 
|  | } | 
|  | return err; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_stats                                              */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  data(I) - pointer to data from ioctl call                   */ | 
|  | /*                                                                          */ | 
|  | /* Copy statistical information from inside the kernel back to user space.  */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | static int iplookup_stats(data) | 
|  | caddr_t data; | 
|  | { | 
|  | iplookupop_t op; | 
|  | int err; | 
|  |  | 
|  | err = BCOPYIN(data, &op, sizeof(op)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) | 
|  | return EINVAL; | 
|  |  | 
|  | switch (op.iplo_type) | 
|  | { | 
|  | case IPLT_POOL : | 
|  | err = ip_pool_statistics(&op); | 
|  | break; | 
|  |  | 
|  | case IPLT_HASH : | 
|  | err = fr_gethtablestat(&op); | 
|  | break; | 
|  |  | 
|  | default : | 
|  | err = EINVAL; | 
|  | break; | 
|  | } | 
|  | return err; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_flush                                              */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  data(I) - pointer to data from ioctl call                   */ | 
|  | /*                                                                          */ | 
|  | /* A flush is called when we want to flush all the nodes from a particular  */ | 
|  | /* entry in the hash table/pool or want to remove all groups from those.    */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | static int iplookup_flush(data) | 
|  | caddr_t data; | 
|  | { | 
|  | int err, unit, num, type; | 
|  | iplookupflush_t flush; | 
|  |  | 
|  | err = BCOPYIN(data, &flush, sizeof(flush)); | 
|  | if (err != 0) | 
|  | return EFAULT; | 
|  |  | 
|  | unit = flush.iplf_unit; | 
|  | if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) | 
|  | return EINVAL; | 
|  |  | 
|  | flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; | 
|  |  | 
|  | type = flush.iplf_type; | 
|  | err = EINVAL; | 
|  | num = 0; | 
|  |  | 
|  | if (type == IPLT_POOL || type == IPLT_ALL) { | 
|  | err = 0; | 
|  | num = ip_pool_flush(&flush); | 
|  | } | 
|  |  | 
|  | if (type == IPLT_HASH  || type == IPLT_ALL) { | 
|  | err = 0; | 
|  | num += fr_flushhtable(&flush); | 
|  | } | 
|  |  | 
|  | if (err == 0) { | 
|  | flush.iplf_count = num; | 
|  | err = BCOPYOUT(&flush, data, sizeof(flush)); | 
|  | if (err != 0) | 
|  | err = EFAULT; | 
|  | } | 
|  | return err; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    ip_lookup_delref                                            */ | 
|  | /* Returns:     void                                                        */ | 
|  | /* Parameters:  type(I) - table type to operate on                          */ | 
|  | /*              ptr(I)  - pointer to object to remove reference for         */ | 
|  | /*                                                                          */ | 
|  | /* This function organises calling the correct deref function for a given   */ | 
|  | /* type of object being passed into it.                                     */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | void ip_lookup_deref(type, ptr) | 
|  | int type; | 
|  | void *ptr; | 
|  | { | 
|  | if (ptr == NULL) | 
|  | return; | 
|  |  | 
|  | WRITE_ENTER(&ip_poolrw); | 
|  | switch (type) | 
|  | { | 
|  | case IPLT_POOL : | 
|  | ip_pool_deref(ptr); | 
|  | break; | 
|  |  | 
|  | case IPLT_HASH : | 
|  | fr_derefhtable(ptr); | 
|  | break; | 
|  | } | 
|  | RWLOCK_EXIT(&ip_poolrw); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    ip_lookup_iterate                                           */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  data(I) - pointer to data from ioctl call                   */ | 
|  | /*                                                                          */ | 
|  | /* Decodes ioctl request to step through either hash tables or pools.       */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | int ip_lookup_iterate(data, uid, ctx) | 
|  | void *data; | 
|  | int uid; | 
|  | void *ctx; | 
|  | { | 
|  | ipflookupiter_t iter; | 
|  | ipftoken_t *token; | 
|  | int err; | 
|  | SPL_INT(s); | 
|  |  | 
|  | err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER); | 
|  | if (err != 0) | 
|  | return err; | 
|  |  | 
|  | if (iter.ili_unit > IPL_LOGMAX) | 
|  | return EINVAL; | 
|  |  | 
|  | if (iter.ili_ival != IPFGENITER_LOOKUP) | 
|  | return EINVAL; | 
|  |  | 
|  | SPL_SCHED(s); | 
|  | token = ipf_findtoken(iter.ili_key, uid, ctx); | 
|  | if (token == NULL) { | 
|  | RWLOCK_EXIT(&ipf_tokens); | 
|  | SPL_X(s); | 
|  | return ESRCH; | 
|  | } | 
|  |  | 
|  | switch (iter.ili_type) | 
|  | { | 
|  | case IPLT_POOL : | 
|  | err = ip_pool_getnext(token, &iter); | 
|  | break; | 
|  | case IPLT_HASH : | 
|  | err = fr_htable_getnext(token, &iter); | 
|  | break; | 
|  | default : | 
|  | err = EINVAL; | 
|  | break; | 
|  | } | 
|  | RWLOCK_EXIT(&ipf_tokens); | 
|  | SPL_X(s); | 
|  |  | 
|  | return err; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | /* Function:    iplookup_iterderef                                          */ | 
|  | /* Returns:     int     - 0 = success, else error                           */ | 
|  | /* Parameters:  data(I) - pointer to data from ioctl call                   */ | 
|  | /*                                                                          */ | 
|  | /* Decodes ioctl request to remove a particular hash table or pool and      */ | 
|  | /* calls the relevant function to do the cleanup.                           */ | 
|  | /* ------------------------------------------------------------------------ */ | 
|  | void ip_lookup_iterderef(type, data) | 
|  | u_32_t type; | 
|  | void *data; | 
|  | { | 
|  | iplookupiterkey_t	key; | 
|  |  | 
|  | key.ilik_key = type; | 
|  |  | 
|  | if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP) | 
|  | return; | 
|  |  | 
|  | switch (key.ilik_unstr.ilik_type) | 
|  | { | 
|  | case IPLT_HASH : | 
|  | fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype, | 
|  | (int)key.ilik_unstr.ilik_unit, data); | 
|  | break; | 
|  | case IPLT_POOL : | 
|  | ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype, | 
|  | (int)key.ilik_unstr.ilik_unit, data); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | #else /* IPFILTER_LOOKUP */ | 
|  |  | 
|  | /*ARGSUSED*/ | 
|  | int ip_lookup_ioctl(data, cmd, mode, uid, ctx) | 
|  | caddr_t data; | 
|  | ioctlcmd_t cmd; | 
|  | int mode, uid; | 
|  | void *ctx; | 
|  | { | 
|  | return EIO; | 
|  | } | 
|  | #endif /* IPFILTER_LOOKUP */ |