git: c92983b03f0a - stable/13 - ipfilter: ipf_dstlist is a kernel source file
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 21 Dec 2021 23:35:27 UTC
The branch stable/13 has been updated by cy: URL: https://cgit.FreeBSD.org/src/commit/?id=c92983b03f0a29a70adcd9a1ca6f68ec7e1b2a2b commit c92983b03f0a29a70adcd9a1ca6f68ec7e1b2a2b Author: Cy Schubert <cy@FreeBSD.org> AuthorDate: 2021-12-15 21:50:38 +0000 Commit: Cy Schubert <cy@FreeBSD.org> CommitDate: 2021-12-21 23:34:41 +0000 ipfilter: ipf_dstlist is a kernel source file Remove duplicate ipf_dstlist.* files. They live in sys/. (cherry picked from commit 7aec934fffde73f7d22450b18e04436aa77b1148) --- contrib/ipfilter/ip_dstlist.c | 1343 ----------------------------------------- contrib/ipfilter/ip_dstlist.h | 68 --- 2 files changed, 1411 deletions(-) diff --git a/contrib/ipfilter/ip_dstlist.c b/contrib/ipfilter/ip_dstlist.c deleted file mode 100644 index 2802ef694aa9..000000000000 --- a/contrib/ipfilter/ip_dstlist.c +++ /dev/null @@ -1,1343 +0,0 @@ -/* - * Copyright (C) 2012 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 -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/file.h> -#if !defined(_KERNEL) && !defined(__KERNEL__) -# include <stdio.h> -# include <stdlib.h> -# include <string.h> -# define _KERNEL -# include <sys/uio.h> -# undef _KERNEL -#else -# include <sys/systm.h> -# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) -# include <sys/proc.h> -# endif -#endif -#include <sys/time.h> -# include <sys/protosw.h> -#include <sys/socket.h> -#if defined(_KERNEL) && !defined(__SVR4) -# include <sys/mbuf.h> -#endif -#if defined(__SVR4) -# include <sys/filio.h> -# include <sys/byteorder.h> -# ifdef _KERNEL -# include <sys/dditypes.h> -# endif -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#if defined(__FreeBSD__) -# include <sys/malloc.h> -#endif - -#include <net/if.h> -#include <netinet/in.h> - -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_lookup.h" -#include "netinet/ip_dstlist.h" - -/* END OF INCLUDES */ - -#ifdef HAS_SYS_MD5_H -# include <sys/md5.h> -#else -# include "md5.h" -#endif - -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_dstlist.c,v 1.13.2.12 2012/07/20 08:40:19 darren_r Exp $"; -#endif - -typedef struct ipf_dstl_softc_s { - ippool_dst_t *dstlist[LOOKUP_POOL_SZ]; - ippool_dst_t **tails[LOOKUP_POOL_SZ]; - ipf_dstl_stat_t stats; -} ipf_dstl_softc_t; - - -static void *ipf_dstlist_soft_create(ipf_main_softc_t *); -static void ipf_dstlist_soft_destroy(ipf_main_softc_t *, void *); -static int ipf_dstlist_soft_init(ipf_main_softc_t *, void *); -static void ipf_dstlist_soft_fini(ipf_main_softc_t *, void *); -static int ipf_dstlist_addr_find(ipf_main_softc_t *, void *, int, - void *, u_int); -static size_t ipf_dstlist_flush(ipf_main_softc_t *, void *, - iplookupflush_t *); -static int ipf_dstlist_iter_deref(ipf_main_softc_t *, void *, int, int, - void *); -static int ipf_dstlist_iter_next(ipf_main_softc_t *, void *, ipftoken_t *, - ipflookupiter_t *); -static int ipf_dstlist_node_add(ipf_main_softc_t *, void *, - iplookupop_t *, int); -static int ipf_dstlist_node_del(ipf_main_softc_t *, void *, - iplookupop_t *, int); -static int ipf_dstlist_stats_get(ipf_main_softc_t *, void *, - iplookupop_t *); -static int ipf_dstlist_table_add(ipf_main_softc_t *, void *, - iplookupop_t *); -static int ipf_dstlist_table_del(ipf_main_softc_t *, void *, - iplookupop_t *); -static int ipf_dstlist_table_deref(ipf_main_softc_t *, void *, void *); -static void *ipf_dstlist_table_find(void *, int, char *); -static void ipf_dstlist_table_free(ipf_dstl_softc_t *, ippool_dst_t *); -static void ipf_dstlist_table_remove(ipf_main_softc_t *, - ipf_dstl_softc_t *, ippool_dst_t *); -static void ipf_dstlist_table_clearnodes(ipf_dstl_softc_t *, - ippool_dst_t *); -static ipf_dstnode_t *ipf_dstlist_select(fr_info_t *, ippool_dst_t *); -static void *ipf_dstlist_select_ref(void *, int, char *); -static void ipf_dstlist_node_free(ipf_dstl_softc_t *, ippool_dst_t *, ipf_dstnode_t *); -static int ipf_dstlist_node_deref(void *, ipf_dstnode_t *); -static void ipf_dstlist_expire(ipf_main_softc_t *, void *); -static void ipf_dstlist_sync(ipf_main_softc_t *, void *); - -ipf_lookup_t ipf_dstlist_backend = { - IPLT_DSTLIST, - ipf_dstlist_soft_create, - ipf_dstlist_soft_destroy, - ipf_dstlist_soft_init, - ipf_dstlist_soft_fini, - ipf_dstlist_addr_find, - ipf_dstlist_flush, - ipf_dstlist_iter_deref, - ipf_dstlist_iter_next, - ipf_dstlist_node_add, - ipf_dstlist_node_del, - ipf_dstlist_stats_get, - ipf_dstlist_table_add, - ipf_dstlist_table_del, - ipf_dstlist_table_deref, - ipf_dstlist_table_find, - ipf_dstlist_select_ref, - ipf_dstlist_select_node, - ipf_dstlist_expire, - ipf_dstlist_sync -}; - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_soft_create */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* */ -/* Allocating a chunk of memory filled with 0's is enough for the current */ -/* soft context used with destination lists. */ -/* ------------------------------------------------------------------------ */ -static void * -ipf_dstlist_soft_create(softc) - ipf_main_softc_t *softc; -{ - ipf_dstl_softc_t *softd; - int i; - - KMALLOC(softd, ipf_dstl_softc_t *); - if (softd == NULL) { - IPFERROR(120028); - return NULL; - } - - bzero((char *)softd, sizeof(*softd)); - for (i = 0; i <= IPL_LOGMAX; i++) - softd->tails[i] = &softd->dstlist[i]; - - return softd; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_soft_destroy */ -/* Returns: Nil */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* */ -/* For destination lists, the only thing we have to do when destroying the */ -/* soft context is free it! */ -/* ------------------------------------------------------------------------ */ -static void -ipf_dstlist_soft_destroy(softc, arg) - ipf_main_softc_t *softc; - void *arg; -{ - ipf_dstl_softc_t *softd = arg; - - KFREE(softd); -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_soft_init */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* */ -/* There is currently no soft context for destination list management. */ -/* ------------------------------------------------------------------------ */ -static int -ipf_dstlist_soft_init(softc, arg) - ipf_main_softc_t *softc; - void *arg; -{ - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_soft_fini */ -/* Returns: Nil */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* */ -/* There is currently no soft context for destination list management. */ -/* ------------------------------------------------------------------------ */ -static void -ipf_dstlist_soft_fini(softc, arg) - ipf_main_softc_t *softc; - void *arg; -{ - ipf_dstl_softc_t *softd = arg; - int i; - - for (i = -1; i <= IPL_LOGMAX; i++) { - while (softd->dstlist[i + 1] != NULL) { - ipf_dstlist_table_remove(softc, softd, - softd->dstlist[i + 1]); - } - } - - ASSERT(softd->stats.ipls_numderefnodes == 0); -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_addr_find */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg1(I) - pointer to local context to use */ -/* arg2(I) - pointer to local context to use */ -/* arg3(I) - pointer to local context to use */ -/* arg4(I) - pointer to local context to use */ -/* */ -/* There is currently no such thing as searching a destination list for an */ -/* address so this function becomes a no-op. Its presence is required as */ -/* ipf_lookup_res_name() stores the "addr_find" function pointer in the */ -/* pointer passed in to it as funcptr, although it could be a generic null- */ -/* op function rather than a specific one. */ -/* ------------------------------------------------------------------------ */ -/*ARGSUSED*/ -static int -ipf_dstlist_addr_find(softc, arg1, arg2, arg3, arg4) - ipf_main_softc_t *softc; - void *arg1, *arg3; - int arg2; - u_int arg4; -{ - return -1; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_flush */ -/* Returns: int - number of objects deleted */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* fop(I) - pointer to lookup flush operation data */ -/* */ -/* Flush all of the destination tables that match the data passed in with */ -/* the iplookupflush_t. There are two ways to match objects: the device for */ -/* which they are to be used with and their name. */ -/* ------------------------------------------------------------------------ */ -static size_t -ipf_dstlist_flush(softc, arg, fop) - ipf_main_softc_t *softc; - void *arg; - iplookupflush_t *fop; -{ - ipf_dstl_softc_t *softd = arg; - ippool_dst_t *node, *next; - int n, i; - - for (n = 0, i = -1; i <= IPL_LOGMAX; i++) { - if (fop->iplf_unit != IPLT_ALL && fop->iplf_unit != i) - continue; - for (node = softd->dstlist[i + 1]; node != NULL; node = next) { - next = node->ipld_next; - - if ((*fop->iplf_name != '\0') && - strncmp(fop->iplf_name, node->ipld_name, - FR_GROUPLEN)) - continue; - - ipf_dstlist_table_remove(softc, softd, node); - n++; - } - } - return n; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_iter_deref */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* otype(I) - type of data structure to iterate through */ -/* unit(I) - device we are working with */ -/* data(I) - address of object in kernel space */ -/* */ -/* This function is called when the iteration token is being free'd and is */ -/* responsible for dropping the reference count of the structure it points */ -/* to. */ -/* ------------------------------------------------------------------------ */ -static int -ipf_dstlist_iter_deref(softc, arg, otype, unit, data) - ipf_main_softc_t *softc; - void *arg; - int otype, unit; - void *data; -{ - if (data == NULL) { - IPFERROR(120001); - return EINVAL; - } - - if (unit < -1 || unit > IPL_LOGMAX) { - IPFERROR(120002); - return EINVAL; - } - - switch (otype) - { - case IPFLOOKUPITER_LIST : - ipf_dstlist_table_deref(softc, arg, (ippool_dst_t *)data); - break; - - case IPFLOOKUPITER_NODE : - ipf_dstlist_node_deref(arg, (ipf_dstnode_t *)data); - break; - } - - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_iter_next */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* op(I) - pointer to lookup operation data */ -/* uid(I) - uid of process doing the ioctl */ -/* */ -/* This function is responsible for either selecting the next destination */ -/* list or node on a destination list to be returned as a user process */ -/* iterates through the list of destination lists or nodes. */ -/* ------------------------------------------------------------------------ */ -static int -ipf_dstlist_iter_next(softc, arg, token, iter) - ipf_main_softc_t *softc; - void *arg; - ipftoken_t *token; - ipflookupiter_t *iter; -{ - ipf_dstnode_t zn, *nextnode = NULL, *node = NULL; - ippool_dst_t zero, *next = NULL, *dsttab = NULL; - ipf_dstl_softc_t *softd = arg; - int err = 0; - void *hint; - - switch (iter->ili_otype) - { - case IPFLOOKUPITER_LIST : - dsttab = token->ipt_data; - if (dsttab == NULL) { - next = softd->dstlist[(int)iter->ili_unit + 1]; - } else { - next = dsttab->ipld_next; - } - - if (next != NULL) { - ATOMIC_INC32(next->ipld_ref); - token->ipt_data = next; - hint = next->ipld_next; - } else { - bzero((char *)&zero, sizeof(zero)); - next = &zero; - token->ipt_data = NULL; - hint = NULL; - } - break; - - case IPFLOOKUPITER_NODE : - node = token->ipt_data; - if (node == NULL) { - dsttab = ipf_dstlist_table_find(arg, iter->ili_unit, - iter->ili_name); - if (dsttab == NULL) { - IPFERROR(120004); - err = ESRCH; - nextnode = NULL; - } else { - if (dsttab->ipld_dests == NULL) - nextnode = NULL; - else - nextnode = *dsttab->ipld_dests; - dsttab = NULL; - } - } else { - nextnode = node->ipfd_next; - } - - if (nextnode != NULL) { - MUTEX_ENTER(&nextnode->ipfd_lock); - nextnode->ipfd_ref++; - MUTEX_EXIT(&nextnode->ipfd_lock); - token->ipt_data = nextnode; - hint = nextnode->ipfd_next; - } else { - bzero((char *)&zn, sizeof(zn)); - nextnode = &zn; - token->ipt_data = NULL; - hint = NULL; - } - break; - default : - IPFERROR(120003); - err = EINVAL; - break; - } - - if (err != 0) - return err; - - switch (iter->ili_otype) - { - case IPFLOOKUPITER_LIST : - if (dsttab != NULL) - ipf_dstlist_table_deref(softc, arg, dsttab); - err = COPYOUT(next, iter->ili_data, sizeof(*next)); - if (err != 0) { - IPFERROR(120005); - err = EFAULT; - } - break; - - case IPFLOOKUPITER_NODE : - if (node != NULL) - ipf_dstlist_node_deref(arg, node); - err = COPYOUT(nextnode, iter->ili_data, sizeof(*nextnode)); - if (err != 0) { - IPFERROR(120006); - err = EFAULT; - } - break; - } - - if (hint == NULL) - ipf_token_mark_complete(token); - - return err; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_node_add */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* op(I) - pointer to lookup operation data */ -/* uid(I) - uid of process doing the ioctl */ -/* Locks: WRITE(ipf_poolrw) */ -/* */ -/* Add a new node to a destination list. To do this, we only copy in the */ -/* frdest_t structure because that contains the only data required from the */ -/* application to create a new node. The frdest_t doesn't contain the name */ -/* itself. When loading filter rules, fd_name is a 'pointer' to the name. */ -/* In this case, the 'pointer' does not work, instead it is the length of */ -/* the name and the name is immediately following the frdest_t structure. */ -/* fd_name must include the trailing \0, so it should be strlen(str) + 1. */ -/* For simple sanity checking, an upper bound on the size of fd_name is */ -/* imposed - 128. */ -/* ------------------------------------------------------------------------ */ -static int -ipf_dstlist_node_add(softc, arg, op, uid) - ipf_main_softc_t *softc; - void *arg; - iplookupop_t *op; - int uid; -{ - ipf_dstl_softc_t *softd = arg; - ipf_dstnode_t *node, **nodes; - ippool_dst_t *d; - frdest_t dest; - int err; - - if (op->iplo_size < sizeof(frdest_t)) { - IPFERROR(120007); - return EINVAL; - } - - err = COPYIN(op->iplo_struct, &dest, sizeof(dest)); - if (err != 0) { - IPFERROR(120009); - return EFAULT; - } - - d = ipf_dstlist_table_find(arg, op->iplo_unit, op->iplo_name); - if (d == NULL) { - IPFERROR(120010); - return ESRCH; - } - - switch (dest.fd_addr.adf_family) - { - case AF_INET : - case AF_INET6 : - break; - default : - IPFERROR(120019); - return EINVAL; - } - - if (dest.fd_name < -1 || dest.fd_name > 128) { - IPFERROR(120018); - return EINVAL; - } - - KMALLOCS(node, ipf_dstnode_t *, sizeof(*node) + dest.fd_name); - if (node == NULL) { - softd->stats.ipls_nomem++; - IPFERROR(120008); - return ENOMEM; - } - bzero((char *)node, sizeof(*node) + dest.fd_name); - - bcopy(&dest, &node->ipfd_dest, sizeof(dest)); - node->ipfd_size = sizeof(*node) + dest.fd_name; - - if (dest.fd_name > 0) { - /* - * fd_name starts out as the length of the string to copy - * in (including \0) and ends up being the offset from - * fd_names (0). - */ - err = COPYIN((char *)op->iplo_struct + sizeof(dest), - node->ipfd_names, dest.fd_name); - if (err != 0) { - IPFERROR(120017); - KFREES(node, node->ipfd_size); - return EFAULT; - } - node->ipfd_dest.fd_name = 0; - } else { - node->ipfd_dest.fd_name = -1; - } - - if (d->ipld_nodes == d->ipld_maxnodes) { - KMALLOCS(nodes, ipf_dstnode_t **, - sizeof(*nodes) * (d->ipld_maxnodes + 1)); - if (nodes == NULL) { - softd->stats.ipls_nomem++; - IPFERROR(120022); - KFREES(node, node->ipfd_size); - return ENOMEM; - } - if (d->ipld_dests != NULL) { - bcopy(d->ipld_dests, nodes, - sizeof(*nodes) * d->ipld_maxnodes); - KFREES(d->ipld_dests, sizeof(*nodes) * d->ipld_nodes); - nodes[0]->ipfd_pnext = nodes; - } - d->ipld_dests = nodes; - d->ipld_maxnodes++; - } - d->ipld_dests[d->ipld_nodes] = node; - d->ipld_nodes++; - - if (d->ipld_nodes == 1) { - node->ipfd_pnext = d->ipld_dests; - } else if (d->ipld_nodes > 1) { - node->ipfd_pnext = &d->ipld_dests[d->ipld_nodes - 2]->ipfd_next; - } - *node->ipfd_pnext = node; - - MUTEX_INIT(&node->ipfd_lock, "ipf dst node lock"); - node->ipfd_uid = uid; - node->ipfd_ref = 1; - if (node->ipfd_dest.fd_name == 0) - (void) ipf_resolvedest(softc, node->ipfd_names, - &node->ipfd_dest, AF_INET); -#ifdef USE_INET6 - if (node->ipfd_dest.fd_name == 0 && - node->ipfd_dest.fd_ptr == (void *)-1) - (void) ipf_resolvedest(softc, node->ipfd_names, - &node->ipfd_dest, AF_INET6); -#endif - - softd->stats.ipls_numnodes++; - - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_node_deref */ -/* Returns: int - 0 = success, else error */ -/* Parameters: arg(I) - pointer to local context to use */ -/* node(I) - pointer to destionation node to free */ -/* */ -/* Dereference the use count by one. If it drops to zero then we can assume */ -/* that it has been removed from any lists/tables and is ripe for freeing. */ -/* The pointer to context is required for the purpose of maintaining */ -/* statistics. */ -/* ------------------------------------------------------------------------ */ -static int -ipf_dstlist_node_deref(arg, node) - void *arg; - ipf_dstnode_t *node; -{ - ipf_dstl_softc_t *softd = arg; - int ref; - - MUTEX_ENTER(&node->ipfd_lock); - ref = --node->ipfd_ref; - MUTEX_EXIT(&node->ipfd_lock); - - if (ref > 0) - return 0; - - if ((node->ipfd_flags & IPDST_DELETE) != 0) - softd->stats.ipls_numderefnodes--; - MUTEX_DESTROY(&node->ipfd_lock); - KFREES(node, node->ipfd_size); - softd->stats.ipls_numnodes--; - - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_node_del */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* op(I) - pointer to lookup operation data */ -/* uid(I) - uid of process doing the ioctl */ -/* */ -/* Look for a matching destination node on the named table and free it if */ -/* found. Because the name embedded in the frdest_t is variable in length, */ -/* it is necessary to allocate some memory locally, to complete this op. */ -/* ------------------------------------------------------------------------ */ -static int -ipf_dstlist_node_del(softc, arg, op, uid) - ipf_main_softc_t *softc; - void *arg; - iplookupop_t *op; - int uid; -{ - ipf_dstl_softc_t *softd = arg; - ipf_dstnode_t *node; - frdest_t frd, *temp; - ippool_dst_t *d; - size_t size; - int err; - - d = ipf_dstlist_table_find(arg, op->iplo_unit, op->iplo_name); - if (d == NULL) { - IPFERROR(120012); - return ESRCH; - } - - err = COPYIN(op->iplo_struct, &frd, sizeof(frd)); - if (err != 0) { - IPFERROR(120011); - return EFAULT; - } - - size = sizeof(*temp) + frd.fd_name; - KMALLOCS(temp, frdest_t *, size); - if (temp == NULL) { - softd->stats.ipls_nomem++; - IPFERROR(120026); - return ENOMEM; - } - - err = COPYIN(op->iplo_struct, temp, size); - if (err != 0) { - IPFERROR(120027); - return EFAULT; - } - - MUTEX_ENTER(&d->ipld_lock); - for (node = *d->ipld_dests; node != NULL; node = node->ipfd_next) { - if ((uid != 0) && (node->ipfd_uid != uid)) - continue; - if (node->ipfd_size != size) - continue; - if (!bcmp(&node->ipfd_dest.fd_ip6, &frd.fd_ip6, - size - offsetof(frdest_t, fd_ip6))) { - ipf_dstlist_node_free(softd, d, node); - MUTEX_EXIT(&d->ipld_lock); - KFREES(temp, size); - return 0; - } - } - MUTEX_EXIT(&d->ipld_lock); - KFREES(temp, size); - - return ESRCH; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_node_free */ -/* Returns: Nil */ -/* Parameters: softd(I) - pointer to the destination list context */ -/* d(I) - pointer to destination list */ -/* node(I) - pointer to node to free */ -/* Locks: MUTEX(ipld_lock) or WRITE(ipf_poolrw) */ -/* */ -/* Free the destination node by first removing it from any lists and then */ -/* checking if this was the last reference held to the object. While the */ -/* array of pointers to nodes is compacted, its size isn't reduced (by way */ -/* of allocating a new smaller one and copying) because the belief is that */ -/* it is likely the array will again reach that size. */ -/* ------------------------------------------------------------------------ */ -static void -ipf_dstlist_node_free(softd, d, node) - ipf_dstl_softc_t *softd; - ippool_dst_t *d; - ipf_dstnode_t *node; -{ - int i; - - /* - * Compact the array of pointers to nodes. - */ - for (i = 0; i < d->ipld_nodes; i++) - if (d->ipld_dests[i] == node) - break; - if (d->ipld_nodes - i > 1) { - bcopy(&d->ipld_dests[i + 1], &d->ipld_dests[i], - sizeof(*d->ipld_dests) * (d->ipld_nodes - i - 1)); - } - d->ipld_nodes--; - - if (node->ipfd_pnext != NULL) - *node->ipfd_pnext = node->ipfd_next; - if (node->ipfd_next != NULL) - node->ipfd_next->ipfd_pnext = node->ipfd_pnext; - node->ipfd_pnext = NULL; - node->ipfd_next = NULL; - - if ((node->ipfd_flags & IPDST_DELETE) == 0) { - softd->stats.ipls_numderefnodes++; - node->ipfd_flags |= IPDST_DELETE; - } - - ipf_dstlist_node_deref(softd, node); -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_stats_get */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* op(I) - pointer to lookup operation data */ -/* */ -/* Return the current statistics for destination lists. This may be for all */ -/* of them or just information pertaining to a particular table. */ -/* ------------------------------------------------------------------------ */ -/*ARGSUSED*/ -static int -ipf_dstlist_stats_get(softc, arg, op) - ipf_main_softc_t *softc; - void *arg; - iplookupop_t *op; -{ - ipf_dstl_softc_t *softd = arg; - ipf_dstl_stat_t stats; - int unit, i, err = 0; - - if (op->iplo_size != sizeof(ipf_dstl_stat_t)) { - IPFERROR(120023); - return EINVAL; - } - - stats = softd->stats; - unit = op->iplo_unit; - if (unit == IPL_LOGALL) { - for (i = 0; i <= IPL_LOGMAX; i++) - stats.ipls_list[i] = softd->dstlist[i]; - } else if (unit >= 0 && unit <= IPL_LOGMAX) { - void *ptr; - - if (op->iplo_name[0] != '\0') - ptr = ipf_dstlist_table_find(softd, unit, - op->iplo_name); - else - ptr = softd->dstlist[unit + 1]; - stats.ipls_list[unit] = ptr; - } else { - IPFERROR(120024); - err = EINVAL; - } - - if (err == 0) { - err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); - if (err != 0) { - IPFERROR(120025); - return EFAULT; - } - } - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_table_add */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* op(I) - pointer to lookup operation data */ -/* */ -/* Add a new destination table to the list of those available for the given */ -/* device. Because we seldom operate on these objects (find/add/delete), */ -/* they are just kept in a simple linked list. */ -/* ------------------------------------------------------------------------ */ -static int -ipf_dstlist_table_add(softc, arg, op) - ipf_main_softc_t *softc; - void *arg; - iplookupop_t *op; -{ - ipf_dstl_softc_t *softd = arg; - ippool_dst_t user, *d, *new; - int unit, err; - - d = ipf_dstlist_table_find(arg, op->iplo_unit, op->iplo_name); - if (d != NULL) { - IPFERROR(120013); - return EEXIST; - } - - err = COPYIN(op->iplo_struct, &user, sizeof(user)); - if (err != 0) { - IPFERROR(120021); - return EFAULT; - } - - KMALLOC(new, ippool_dst_t *); - if (new == NULL) { - softd->stats.ipls_nomem++; - IPFERROR(120014); - return ENOMEM; - } - bzero((char *)new, sizeof(*new)); - - MUTEX_INIT(&new->ipld_lock, "ipf dst table lock"); - - strncpy(new->ipld_name, op->iplo_name, FR_GROUPLEN); - unit = op->iplo_unit; - new->ipld_unit = unit; - new->ipld_policy = user.ipld_policy; - new->ipld_seed = ipf_random(); - new->ipld_ref = 1; - - new->ipld_pnext = softd->tails[unit + 1]; - *softd->tails[unit + 1] = new; - softd->tails[unit + 1] = &new->ipld_next; - softd->stats.ipls_numlists++; - - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_table_del */ -/* Returns: int - 0 = success, else error */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* arg(I) - pointer to local context to use */ -/* op(I) - pointer to lookup operation data */ -/* */ -/* Find a named destinstion list table and delete it. If there are other */ -/* references to it, the caller isn't told. */ -/* ------------------------------------------------------------------------ */ -static int -ipf_dstlist_table_del(softc, arg, op) - ipf_main_softc_t *softc; - void *arg; - iplookupop_t *op; -{ - ippool_dst_t *d; - - d = ipf_dstlist_table_find(arg, op->iplo_unit, op->iplo_name); - if (d == NULL) { - IPFERROR(120015); - return ESRCH; - } - - if (d->ipld_dests != NULL) { - IPFERROR(120016); - return EBUSY; - } - - ipf_dstlist_table_remove(softc, arg, d); - - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_table_remove */ -/* Returns: Nil */ -/* Parameters: softc(I) - pointer to soft context main structure */ -/* softd(I) - pointer to the destination list context */ -/* d(I) - pointer to destination list */ -/* */ -/* Remove a given destination list from existance. While the IPDST_DELETE */ -/* flag is set every time we call this function and the reference count is */ -/* non-zero, the "numdereflists" counter is always incremented because the */ -/* decision about whether it will be freed or not is not made here. This */ -/* means that the only action the code can take here is to treat it as if */ -/* it will become a detached. */ -/* ------------------------------------------------------------------------ */ -static void -ipf_dstlist_table_remove(softc, softd, d) - ipf_main_softc_t *softc; - ipf_dstl_softc_t *softd; - ippool_dst_t *d; -{ - - if (softd->tails[d->ipld_unit + 1] == &d->ipld_next) - softd->tails[d->ipld_unit + 1] = d->ipld_pnext; - - if (d->ipld_pnext != NULL) - *d->ipld_pnext = d->ipld_next; - if (d->ipld_next != NULL) - d->ipld_next->ipld_pnext = d->ipld_pnext; - d->ipld_pnext = NULL; - d->ipld_next = NULL; - - ipf_dstlist_table_clearnodes(softd, d); - - softd->stats.ipls_numdereflists++; - d->ipld_flags |= IPDST_DELETE; - - ipf_dstlist_table_deref(softc, softd, d); -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ipf_dstlist_table_free */ -/* Returns: Nil */ -/* Parameters: softd(I) - pointer to the destination list context */ -/* d(I) - pointer to destination list */ -/* */ -/* Free up a destination list data structure and any other memory that was */ -/* directly allocated as part of creating it. Individual destination list */ -/* nodes are not freed. It is assumed the caller will have already emptied */ -/* the destination list. */ -/* ------------------------------------------------------------------------ */ -static void -ipf_dstlist_table_free(softd, d) *** 456 LINES SKIPPED ***