svn commit: r254564 - vendor-sys/ipfilter/5-1-2/netinet

Cy Schubert cy at FreeBSD.org
Tue Aug 20 13:50:37 UTC 2013


Author: cy
Date: Tue Aug 20 13:50:36 2013
New Revision: 254564
URL: http://svnweb.freebsd.org/changeset/base/254564

Log:
  Tag authorization to use IP-Filter under old license.
  
  Tag additional kernel sources from IP-Filter 5.1.2 tarball.
  
  Approved by:	glebius

Added:
  vendor-sys/ipfilter/5-1-2/netinet/IPFILTER.LICENCE.FreeBSD
     - copied unchanged from r254563, vendor-sys/ipfilter/dist/netinet/IPFILTER.LICENCE.FreeBSD
  vendor-sys/ipfilter/5-1-2/netinet/ip_dstlist.c
     - copied unchanged from r254563, vendor-sys/ipfilter/dist/netinet/ip_dstlist.c
  vendor-sys/ipfilter/5-1-2/netinet/ip_dstlist.h
     - copied unchanged from r254563, vendor-sys/ipfilter/dist/netinet/ip_dstlist.h
  vendor-sys/ipfilter/5-1-2/netinet/ipf_rb.h
     - copied unchanged from r254563, vendor-sys/ipfilter/dist/netinet/ipf_rb.h
  vendor-sys/ipfilter/5-1-2/netinet/radix_ipf.c
     - copied unchanged from r254563, vendor-sys/ipfilter/dist/netinet/radix_ipf.c
  vendor-sys/ipfilter/5-1-2/netinet/radix_ipf.h
     - copied unchanged from r254563, vendor-sys/ipfilter/dist/netinet/radix_ipf.h

Copied: vendor-sys/ipfilter/5-1-2/netinet/IPFILTER.LICENCE.FreeBSD (from r254563, vendor-sys/ipfilter/dist/netinet/IPFILTER.LICENCE.FreeBSD)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ vendor-sys/ipfilter/5-1-2/netinet/IPFILTER.LICENCE.FreeBSD	Tue Aug 20 13:50:36 2013	(r254564, copy of r254563, vendor-sys/ipfilter/dist/netinet/IPFILTER.LICENCE.FreeBSD)
@@ -0,0 +1,83 @@
+Received: from slippy (localhost [127.0.0.1])
+	by slippy.cwsent.com (8.14.7/8.14.7) with ESMTP id r68DreQv004291
+	for <cy at localhost>; Mon, 8 Jul 2013 06:53:40 -0700 (PDT)
+	(envelope-from Cy.Schubert at komquats.com)
+X-Original-To: slippy
+Delivered-To: slippy at komquats.com
+Received: from cwfw [10.1.1.254]
+	by slippy with POP3 (fetchmail-6.3.22)
+	for <cy at localhost> (single-drop); Mon, 08 Jul 2013 06:53:40 -0700 (PDT)
+Received: by spqr.komquats.com (Postfix, from userid 1000)
+	id 377821BC; Mon,  8 Jul 2013 06:53:38 -0700 (PDT)
+X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on cwfw.cwsent.com
+X-Spam-Level: 
+X-Spam-Status: No, score=-1.6 required=5.0 tests=BAYES_00,MY_DSL,SMILEY
+	autolearn=no version=3.3.2
+X-Original-To: Cy.Schubert at komquats.com
+Delivered-To: Cy.Schubert at komquats.com
+Received: from mail.ipfilter.com.au (dsl-202-45-110-141-static.VIC.netspace.net.au [202.45.110.141])
+	by spqr.komquats.com (Postfix) with ESMTP id C69AE18D
+	for <Cy.Schubert at komquats.com>; Mon,  8 Jul 2013 06:53:31 -0700 (PDT)
+Received: (from root at localhost)
+	by firewall.reed.wattle.id.au (8.12.10/8.11.0) id r68DrJF8001558;
+	Mon, 8 Jul 2013 23:53:19 +1000 (EST)
+Message-ID: <51DAC488.1050700 at reed.wattle.id.au>
+Date: Mon, 08 Jul 2013 23:54:16 +1000
+From: Darren Reed <darrenr at reed.wattle.id.au>
+Reply-To: darrenr at reed.wattle.id.au
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130620 Thunderbird/17.0.7
+MIME-Version: 1.0
+To: Cy Schubert <Cy.Schubert at komquats.com>
+CC: Gleb Smirnoff <glebius at FreeBSD.org>, Andre Oppermann <andre at FreeBSD.org>,
+        Pedro Giffuni <pfg at FreeBSD.org>
+Subject: Re: IP Filter 5.1.2 License
+References: <201307011513.r61FD9IK005944 at slippy.cwsent.com>
+In-Reply-To: <201307011513.r61FD9IK005944 at slippy.cwsent.com>
+X-Enigmail-Version: 1.5.1
+Content-Type: text/plain; charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-UIDL: NC"#!o_F!!BlL!!bL6!!
+
+On 2/07/2013 1:13 AM, Cy Schubert wrote:
+> In message <51D19503.2090805 at reed.wattle.id.au>, Darren Reed writes:
+>> On 25/06/2013 11:03 AM, Cy Schubert wrote:
+>>> Hi Darren,
+>>>
+>>> I'm not sure if you remember me or not but I'm a committer at the FreeBSD 
+>>> Project. I've been a long time IPF user, both under FreeBSD and Solaris. 
+>>> I've volunteered to maintain IP Filter in the src/ tree. I noticed that the
+>>  
+>>> IP Filter license changed from the previous IP Filter license to GPLv2 
+>>> somewhere between 4.1.34 and 4.1.35. I was planning on importing 5.1.2 
+>>> however upon discovering it was GPL I decided to update the FreeBSD IPF 
+>>> from 4.1.28 to 4.1.34 until it was brought to my attention a few days ago 
+>>> that IPF 5.1.2 was imported into NetBSD. I'm not sure what kind of policy 
+>>> the NetBSD folks have toward GPL so I thought it best to ask you directly 
+>>> under what license you imported IPF into NetBSD? If I can I'd like to 
+>>> import 5.1.2. As IPF author and owner of the code, what are your thoughts. 
+>>  
+>>> Can I import IPF 5.1.2 into FreeBSD under a different license from GPL?
+>> I imported IPF into NetBSD under the same license that has had previously.
+>> When I eventually update FreeBSD, I'll publish the code under the same
+>> license that it has now.
+>>
+
+[...]
+
+>
+> When we import into FreeBSD we will not touch the IPFILTER.LICENSE file 
+> keeping the license as before in our tree.
+>
+> I don't mind doing the work if you won't mind.
+
+Not at all.
+
+Ok, I think there's one important thing for me to say here:
+
+I, Darren Reed, authorise Cy Schubert to use the IP-Filter source code from CVS on sourceforge in the FreeBSD source code tree using the existing license that currently covers IP-Filter in FreeBSD .
+
+I think something like that should cover you.
+
+Cheers,
+Darren
+

Copied: vendor-sys/ipfilter/5-1-2/netinet/ip_dstlist.c (from r254563, vendor-sys/ipfilter/dist/netinet/ip_dstlist.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ vendor-sys/ipfilter/5-1-2/netinet/ip_dstlist.c	Tue Aug 20 13:50:36 2013	(r254564, copy of r254563, vendor-sys/ipfilter/dist/netinet/ip_dstlist.c)
@@ -0,0 +1,1351 @@
+/*
+ * 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
+#if defined(__osf__)
+# define _PROTO_NET_H_
+#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
+# ifdef __OpenBSD__
+struct file;
+# endif
+# 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>
+#if !defined(linux)
+# include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
+# include <sys/mbuf.h>
+#endif
+#if defined(__SVR4) || 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_version) && (__FreeBSD_version >= 300000)
+# 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 __P((ipf_main_softc_t *));
+static void ipf_dstlist_soft_destroy __P((ipf_main_softc_t *, void *));
+static int ipf_dstlist_soft_init __P((ipf_main_softc_t *, void *));
+static void ipf_dstlist_soft_fini __P((ipf_main_softc_t *, void *));
+static int ipf_dstlist_addr_find __P((ipf_main_softc_t *, void *, int,
+				      void *, u_int));
+static size_t ipf_dstlist_flush __P((ipf_main_softc_t *, void *,
+				     iplookupflush_t *));
+static int ipf_dstlist_iter_deref __P((ipf_main_softc_t *, void *, int, int,
+				       void *));
+static int ipf_dstlist_iter_next __P((ipf_main_softc_t *, void *, ipftoken_t *,
+				      ipflookupiter_t *));
+static int ipf_dstlist_node_add __P((ipf_main_softc_t *, void *,
+				     iplookupop_t *, int));
+static int ipf_dstlist_node_del __P((ipf_main_softc_t *, void *,
+				     iplookupop_t *, int));
+static int ipf_dstlist_stats_get __P((ipf_main_softc_t *, void *,
+				      iplookupop_t *));
+static int ipf_dstlist_table_add __P((ipf_main_softc_t *, void *,
+				      iplookupop_t *));
+static int ipf_dstlist_table_del __P((ipf_main_softc_t *, void *,
+				      iplookupop_t *));
+static int ipf_dstlist_table_deref __P((ipf_main_softc_t *, void *, void *));
+static void *ipf_dstlist_table_find __P((void *, int, char *));
+static void ipf_dstlist_table_free __P((ipf_dstl_softc_t *, ippool_dst_t *));
+static void ipf_dstlist_table_remove __P((ipf_main_softc_t *,
+					  ipf_dstl_softc_t *, ippool_dst_t *));
+static void ipf_dstlist_table_clearnodes __P((ipf_dstl_softc_t *,
+					      ippool_dst_t *));
+static ipf_dstnode_t *ipf_dstlist_select __P((fr_info_t *, ippool_dst_t *));
+static void *ipf_dstlist_select_ref __P((void *, int, char *));
+static void ipf_dstlist_node_free __P((ipf_dstl_softc_t *, ippool_dst_t *, ipf_dstnode_t *));
+static int ipf_dstlist_node_deref __P((void *, ipf_dstnode_t *));
+static void ipf_dstlist_expire __P((ipf_main_softc_t *, void *));
+static void ipf_dstlist_sync __P((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);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list