The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/ip_htable.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ip_htable.c,v 1.1.1.1 2004/03/28 08:56:43 martti Exp $ */
    2 
    3 /*
    4  * Copyright (C) 1993-2001, 2003 by Darren Reed.
    5  *
    6  * See the IPFILTER.LICENCE file for details on licencing.
    7  */
    8 #if defined(KERNEL) || defined(_KERNEL)
    9 # undef KERNEL
   10 # undef _KERNEL
   11 # define        KERNEL  1
   12 # define        _KERNEL 1
   13 #endif
   14 #include <sys/param.h>
   15 #include <sys/types.h>
   16 #include <sys/errno.h>
   17 #include <sys/time.h>
   18 #include <sys/file.h>
   19 #if !defined(_KERNEL)
   20 # include <stdlib.h>
   21 # include <string.h>
   22 # define _KERNEL
   23 # ifdef __OpenBSD__
   24 struct file;
   25 # endif
   26 # include <sys/uio.h>
   27 # undef _KERNEL
   28 #endif
   29 #include <sys/socket.h>
   30 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
   31 # include <sys/malloc.h>
   32 #endif
   33 #if defined(__FreeBSD__)
   34 #  include <sys/cdefs.h>
   35 #  include <sys/proc.h>
   36 #endif
   37 #if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \
   38     !defined(linux)
   39 # include <sys/mbuf.h>
   40 #endif
   41 #if defined(_KERNEL)
   42 # include <sys/systm.h>
   43 #else
   44 # include <stdio.h>
   45 #endif
   46 #include <netinet/in.h>
   47 #include <net/if.h>
   48 
   49 #include "netinet/ip_compat.h"
   50 #include "netinet/ip_fil.h"
   51 #include "netinet/ip_lookup.h"
   52 #include "netinet/ip_htable.h"
   53 /* END OF INCLUDES */
   54 
   55 #if !defined(lint)
   56 static const char rcsid[] = "@(#)Id: ip_htable.c,v 2.34.2.1 2004/03/06 14:32:58 darrenr Exp";
   57 #endif
   58 
   59 #ifdef  IPFILTER_LOOKUP
   60 static iphtent_t *fr_iphmfind __P((iphtable_t *, struct in_addr *));
   61 static  u_long  ipht_nomem[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
   62 static  u_long  ipf_nhtables[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
   63 static  u_long  ipf_nhtnodes[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
   64 
   65 iphtable_t *ipf_htables[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL,
   66                                          NULL, NULL, NULL, NULL };
   67 
   68 
   69 void fr_htable_unload()
   70 {
   71         iplookupflush_t fop;
   72 
   73         fop.iplf_unit = IPL_LOGALL;
   74         (void)fr_flushhtable(&fop);
   75 }
   76 
   77 
   78 int fr_gethtablestat(op)
   79 iplookupop_t *op;
   80 {
   81         iphtstat_t stats;
   82 
   83         if (op->iplo_size != sizeof(stats))
   84                 return EINVAL;
   85 
   86         stats.iphs_tables = ipf_htables[op->iplo_unit];
   87         stats.iphs_numtables = ipf_nhtables[op->iplo_unit];
   88         stats.iphs_numnodes = ipf_nhtnodes[op->iplo_unit];
   89         stats.iphs_nomem = ipht_nomem[op->iplo_unit];
   90 
   91         return COPYOUT(&stats, op->iplo_struct, sizeof(stats));
   92 
   93 }
   94 
   95 
   96 /*
   97  * Create a new hash table using the template passed.
   98  */
   99 int fr_newhtable(op)
  100 iplookupop_t *op;
  101 {
  102         iphtable_t *iph, *oiph;
  103         char name[FR_GROUPLEN];
  104         int err, i, unit;
  105 
  106         KMALLOC(iph, iphtable_t *);
  107         if (iph == NULL)
  108                 return ENOMEM;
  109 
  110         err = COPYIN(op->iplo_struct, iph, sizeof(*iph));
  111         if (err != 0) {
  112                 KFREE(iph);
  113                 return EFAULT;
  114         }
  115 
  116         unit = op->iplo_unit;
  117         if (iph->iph_unit != unit) {
  118                 KFREE(iph);
  119                 return EINVAL;
  120         }
  121 
  122         if ((op->iplo_arg & IPHASH_ANON) == 0) {
  123                 if (fr_findhtable(op->iplo_unit, op->iplo_name) != NULL) {
  124                         KFREE(iph);
  125                         return EEXIST;
  126                 }
  127         } else {
  128                 i = IPHASH_ANON;
  129                 do {
  130                         i++;
  131 #if defined(SNPRINTF) && defined(_KERNEL)
  132                         SNPRINTF(name, sizeof(name), "%u", i);
  133 #else
  134                         (void)sprintf(name, "%u", i);
  135 #endif
  136                         for (oiph = ipf_htables[unit]; oiph != NULL;
  137                              oiph = oiph->iph_next)
  138                                 if (strncmp(oiph->iph_name, name,
  139                                             sizeof(oiph->iph_name)) == 0)
  140                                         break;
  141                 } while (oiph != NULL);
  142                 (void)strncpy(iph->iph_name, name, sizeof(iph->iph_name));
  143                 err = COPYOUT(iph, op->iplo_struct, sizeof(*iph));
  144                 if (err != 0) {
  145                         KFREE(iph);
  146                         return EFAULT;
  147                 }
  148                 iph->iph_type |= IPHASH_ANON;
  149         }
  150 
  151         KMALLOCS(iph->iph_table, iphtent_t **,
  152                  iph->iph_size * sizeof(*iph->iph_table));
  153         if (iph->iph_table == NULL) {
  154                 KFREE(iph);
  155                 ipht_nomem[unit]++;
  156                 return ENOMEM;
  157         }
  158 
  159         bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
  160         iph->iph_masks = 0;
  161 
  162         iph->iph_next = ipf_htables[unit];
  163         iph->iph_pnext = &ipf_htables[unit];
  164         if (ipf_htables[unit] != NULL)
  165                 ipf_htables[unit]->iph_pnext = &iph->iph_next;
  166         ipf_htables[unit] = iph;
  167 
  168         ipf_nhtables[unit]++;
  169 
  170         return 0;
  171 }
  172 
  173 
  174 /*
  175  */
  176 int fr_removehtable(op)
  177 iplookupop_t *op;
  178 {
  179         iphtable_t *iph;
  180 
  181 
  182         iph = fr_findhtable(op->iplo_unit, op->iplo_name);
  183         if (iph == NULL)
  184                 return ESRCH;
  185 
  186         if (iph->iph_unit != op->iplo_unit) {
  187                 return EINVAL;
  188         }
  189 
  190         if (iph->iph_ref != 0) {
  191                 return EBUSY;
  192         }
  193 
  194         fr_delhtable(iph);
  195 
  196         return 0;
  197 }
  198 
  199 
  200 void fr_delhtable(iph)
  201 iphtable_t *iph;
  202 {
  203         iphtent_t *ipe;
  204         int i;
  205 
  206         for (i = 0; i < iph->iph_size; i++)
  207                 while ((ipe = iph->iph_table[i]) != NULL)
  208                         if (fr_delhtent(iph, ipe) != 0)
  209                                 return;
  210 
  211         *iph->iph_pnext = iph->iph_next;
  212         if (iph->iph_next != NULL)
  213                 iph->iph_next->iph_pnext = iph->iph_pnext;
  214 
  215         ipf_nhtables[iph->iph_unit]--;
  216 
  217         if (iph->iph_ref == 0) {
  218                 KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
  219                 KFREE(iph);
  220         }
  221 }
  222 
  223 
  224 void fr_derefhtable(iph)
  225 iphtable_t *iph;
  226 {
  227         iph->iph_ref--;
  228         if (iph->iph_ref == 0)
  229                 fr_delhtable(iph);
  230 }
  231 
  232 
  233 iphtable_t *fr_findhtable(unit, name)
  234 int unit;
  235 char *name;
  236 {
  237         iphtable_t *iph;
  238 
  239         for (iph = ipf_htables[unit]; iph != NULL; iph = iph->iph_next)
  240                 if (strncmp(iph->iph_name, name, sizeof(iph->iph_name)) == 0)
  241                         break;
  242         return iph;
  243 }
  244 
  245 
  246 size_t fr_flushhtable(op)
  247 iplookupflush_t *op;
  248 {
  249         iphtable_t *iph;
  250         size_t freed;
  251         int i;
  252 
  253         freed = 0;
  254 
  255         for (i = 0; i <= IPL_LOGMAX; i++) {
  256                 if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) {
  257                         while ((iph = ipf_htables[i]) != NULL) {
  258                                 fr_delhtable(iph);
  259                                 freed++;
  260                         }
  261                 }
  262         }
  263 
  264         return freed;
  265 }
  266 
  267 
  268 /*
  269  * Add an entry to a hash table.
  270  */
  271 int fr_addhtent(iph, ipeo)
  272 iphtable_t *iph;
  273 iphtent_t *ipeo;
  274 {
  275         iphtent_t *ipe;
  276         u_int hv;
  277         int bits;
  278 
  279         KMALLOC(ipe, iphtent_t *);
  280         if (ipe == NULL)
  281                 return -1;
  282 
  283         bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe));
  284         ipe->ipe_addr.in4_addr &= ipe->ipe_mask.in4_addr;
  285         ipe->ipe_addr.in4_addr = ntohl(ipe->ipe_addr.in4_addr);
  286         bits = count4bits(ipe->ipe_mask.in4_addr);
  287         ipe->ipe_mask.in4_addr = ntohl(ipe->ipe_mask.in4_addr);
  288 
  289         hv = IPE_HASH_FN(ipe->ipe_addr.in4_addr, ipe->ipe_mask.in4_addr,
  290                          iph->iph_size);
  291         ipe->ipe_ref = 0;
  292         ipe->ipe_next = iph->iph_table[hv];
  293         ipe->ipe_pnext = iph->iph_table + hv;
  294 
  295         if (iph->iph_table[hv] != NULL)
  296                 iph->iph_table[hv]->ipe_pnext = &ipe->ipe_next;
  297         iph->iph_table[hv] = ipe;
  298         if ((bits >= 0) && (bits != 32))
  299                 iph->iph_masks |= 1 << bits;
  300 
  301         switch (iph->iph_type & ~IPHASH_ANON)
  302         {
  303         case IPHASH_GROUPMAP :
  304                 ipe->ipe_ptr = fr_addgroup(ipe->ipe_group, NULL,
  305                                            iph->iph_flags, IPL_LOGIPF,
  306                                            fr_active);
  307                 break;
  308 
  309         default :
  310                 ipe->ipe_ptr = NULL;
  311                 ipe->ipe_value = 0;
  312                 break;
  313         }
  314 
  315         ipf_nhtnodes[iph->iph_unit]++;
  316 
  317         return 0;
  318 }
  319 
  320 
  321 /*
  322  * Delete an entry from a hash table.
  323  */
  324 int fr_delhtent(iph, ipe)
  325 iphtable_t *iph;
  326 iphtent_t *ipe;
  327 {
  328 
  329         if (ipe->ipe_ref != 0)
  330                 return EBUSY;
  331 
  332 
  333         *ipe->ipe_pnext = ipe->ipe_next;
  334         if (ipe->ipe_next != NULL)
  335                 ipe->ipe_next->ipe_pnext = ipe->ipe_pnext;
  336 
  337         switch (iph->iph_type & ~IPHASH_ANON)
  338         {
  339         case IPHASH_GROUPMAP :
  340                 if (ipe->ipe_group != NULL)
  341                         fr_delgroup(ipe->ipe_group, IPL_LOGIPF, fr_active);
  342                 break;
  343 
  344         default :
  345                 ipe->ipe_ptr = NULL;
  346                 ipe->ipe_value = 0;
  347                 break;
  348         }
  349 
  350         KFREE(ipe);
  351 
  352         ipf_nhtnodes[iph->iph_unit]--;
  353 
  354         return 0;
  355 }
  356 
  357 
  358 void *fr_iphmfindgroup(tptr, aptr)
  359 void *tptr, *aptr;
  360 {
  361         struct in_addr *addr;
  362         iphtable_t *iph;
  363         iphtent_t *ipe;
  364         void *rval;
  365 
  366         READ_ENTER(&ip_poolrw);
  367         iph = tptr;
  368         addr = aptr;
  369 
  370         ipe = fr_iphmfind(iph, addr);
  371         if (ipe != NULL)
  372                 rval = ipe->ipe_ptr;
  373         else
  374                 rval = NULL;
  375         RWLOCK_EXIT(&ip_poolrw);
  376         return rval;
  377 }
  378 
  379 
  380 int fr_iphmfindip(tptr, version, aptr)
  381 void *tptr, *aptr;
  382 int version;
  383 {
  384         struct in_addr *addr;
  385         iphtable_t *iph;
  386         iphtent_t *ipe;
  387         int rval;
  388 
  389         if (version != 4)
  390                 return 1;
  391 
  392         if (tptr == NULL || aptr == NULL)
  393                 return 1;
  394 
  395         iph = tptr;
  396         addr = aptr;
  397 
  398         READ_ENTER(&ip_poolrw);
  399         ipe = fr_iphmfind(iph, addr);
  400         if (ipe != NULL)
  401                 rval = 0;
  402         else
  403                 rval = 1;
  404         RWLOCK_EXIT(&ip_poolrw);
  405         return rval;
  406 }
  407 
  408 
  409 /* Locks:  ip_poolrw */
  410 static iphtent_t *fr_iphmfind(iph, addr)
  411 iphtable_t *iph;
  412 struct in_addr *addr;
  413 {
  414         u_32_t hmsk, msk, ips;
  415         iphtent_t *ipe;
  416         u_int hv;
  417 
  418         hmsk = iph->iph_masks;
  419         msk = 0xffffffff;
  420 maskloop:
  421         ips = ntohl(addr->s_addr) & msk;
  422         hv = IPE_HASH_FN(ips, msk, iph->iph_size);
  423         for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
  424                 if (ipe->ipe_mask.in4_addr != msk ||
  425                     ipe->ipe_addr.in4_addr != ips) {
  426                         continue;
  427                 }
  428                 break;
  429         }
  430 
  431         if ((ipe == NULL) && (hmsk != 0)) {
  432                 while (hmsk != 0) {
  433                         msk <<= 1;
  434                         if (hmsk & 0x80000000)
  435                                 break;
  436                         hmsk <<= 1;
  437                 }
  438                 if (hmsk != 0) {
  439                         hmsk <<= 1;
  440                         goto maskloop;
  441                 }
  442         }
  443         return ipe;
  444 }
  445 
  446 #endif /* IPFILTER_LOOKUP */

Cache object: 0f97b24c2c9edd66b39fdf51f43f3e81


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.