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@localhost>; Mon, 8 Jul 2013 06:53:40 -0700 (PDT)
+       (envelope-from cy.schub...@komquats.com)
+X-Original-To: slippy
+Delivered-To: sli...@komquats.com
+Received: from cwfw [10.1.1.254]
+       by slippy with POP3 (fetchmail-6.3.22)
+       for <cy@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.schub...@komquats.com
+Delivered-To: cy.schub...@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.schub...@komquats.com>; Mon,  8 Jul 2013 06:53:31 -0700 (PDT)
+Received: (from root@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.1050...@reed.wattle.id.au>
+Date: Mon, 08 Jul 2013 23:54:16 +1000
+From: Darren Reed <darr...@reed.wattle.id.au>
+Reply-To: darr...@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.schub...@komquats.com>
+CC: Gleb Smirnoff <gleb...@freebsd.org>, Andre Oppermann <an...@freebsd.org>,
+        Pedro Giffuni <p...@freebsd.org>
+Subject: Re: IP Filter 5.1.2 License
+References: <201307011513.r61fd9ik005...@slippy.cwsent.com>
+In-Reply-To: <201307011513.r61fd9ik005...@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.2090...@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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to