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/netpfil/ipfw/ip_fw_table_algo.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 /*-
    2  * Copyright (c) 2014 Yandex LLC
    3  * Copyright (c) 2014 Alexander V. Chernikov
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 /*
   31  * Lookup table algorithms.
   32  *
   33  */
   34 
   35 #include "opt_ipfw.h"
   36 #include "opt_inet.h"
   37 #ifndef INET
   38 #error IPFIREWALL requires INET.
   39 #endif /* INET */
   40 #include "opt_inet6.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/malloc.h>
   45 #include <sys/kernel.h>
   46 #include <sys/lock.h>
   47 #include <sys/rwlock.h>
   48 #include <sys/rmlock.h>
   49 #include <sys/socket.h>
   50 #include <sys/queue.h>
   51 #include <net/ethernet.h>
   52 #include <net/if.h>     /* ip_fw.h requires IFNAMSIZ */
   53 #include <net/radix.h>
   54 #include <net/route.h>
   55 #include <net/route/nhop.h>
   56 #include <net/route/route_ctl.h>
   57 
   58 #include <netinet/in.h>
   59 #include <netinet/in_fib.h>
   60 #include <netinet/ip_var.h>     /* struct ipfw_rule_ref */
   61 #include <netinet/ip_fw.h>
   62 #include <netinet6/in6_fib.h>
   63 
   64 #include <netpfil/ipfw/ip_fw_private.h>
   65 #include <netpfil/ipfw/ip_fw_table.h>
   66 
   67 /*
   68  * IPFW table lookup algorithms.
   69  *
   70  * What is needed to add another table algo?
   71  *
   72  * Algo init:
   73  * * struct table_algo has to be filled with:
   74  *   name: "type:algoname" format, e.g. "addr:radix". Currently
   75  *     there are the following types: "addr", "iface", "number" and "flow".
   76  *   type: one of IPFW_TABLE_* types
   77  *   flags: one or more TA_FLAGS_*
   78  *   ta_buf_size: size of structure used to store add/del item state.
   79  *     Needs to be less than TA_BUF_SZ.
   80  *   callbacks: see below for description.
   81  * * ipfw_add_table_algo / ipfw_del_table_algo has to be called
   82  *
   83  * Callbacks description:
   84  *
   85  * -init: request to initialize new table instance.
   86  * typedef int (ta_init)(struct ip_fw_chain *ch, void **ta_state,
   87  *     struct table_info *ti, char *data, uint8_t tflags);
   88  * MANDATORY, unlocked. (M_WAITOK). Returns 0 on success.
   89  *
   90  *  Allocate all structures needed for normal operations.
   91  *  * Caller may want to parse @data for some algo-specific
   92  *    options provided by userland.
   93  *  * Caller may want to save configuration state pointer to @ta_state
   94  *  * Caller needs to save desired runtime structure pointer(s)
   95  *    inside @ti fields. Note that it is not correct to save
   96  *    @ti pointer at this moment. Use -change_ti hook for that.
   97  *  * Caller has to fill in ti->lookup to appropriate function
   98  *    pointer.
   99  *
  100  *
  101  *
  102  * -destroy: request to destroy table instance.
  103  * typedef void (ta_destroy)(void *ta_state, struct table_info *ti);
  104  * MANDATORY, unlocked. (M_WAITOK).
  105  *
  106  * Frees all table entries and all tables structures allocated by -init.
  107  *
  108  *
  109  *
  110  * -prepare_add: request to allocate state for adding new entry.
  111  * typedef int (ta_prepare_add)(struct ip_fw_chain *ch, struct tentry_info *tei,
  112  *     void *ta_buf);
  113  * MANDATORY, unlocked. (M_WAITOK). Returns 0 on success.
  114  *
  115  * Allocates state and fills it in with all necessary data (EXCEPT value)
  116  * from @tei to minimize operations needed to be done under WLOCK.
  117  * "value" field has to be copied to new entry in @add callback.
  118  * Buffer ta_buf of size ta->ta_buf_sz may be used to store
  119  * allocated state.
  120  *
  121  *
  122  *
  123  * -prepare_del: request to set state for deleting existing entry.
  124  * typedef int (ta_prepare_del)(struct ip_fw_chain *ch, struct tentry_info *tei,
  125  *     void *ta_buf);
  126  * MANDATORY, locked, UH. (M_NOWAIT). Returns 0 on success.
  127  *
  128  * Buffer ta_buf of size ta->ta_buf_sz may be used to store
  129  * allocated state. Caller should use on-stack ta_buf allocation
  130  * instead of doing malloc().
  131  *
  132  *
  133  *
  134  * -add: request to insert new entry into runtime/config structures.
  135  *  typedef int (ta_add)(void *ta_state, struct table_info *ti,
  136  *     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
  137  * MANDATORY, UH+WLOCK. (M_NOWAIT). Returns 0 on success.
  138  *
  139  * Insert new entry using previously-allocated state in @ta_buf.
  140  * * @tei may have the following flags:
  141  *   TEI_FLAGS_UPDATE: request to add or update entry.
  142  *   TEI_FLAGS_DONTADD: request to update (but not add) entry.
  143  * * Caller is required to do the following:
  144  *   copy real entry value from @tei
  145  *   entry added: return 0, set 1 to @pnum
  146  *   entry updated: return 0, store 0 to @pnum, store old value in @tei,
  147  *     add TEI_FLAGS_UPDATED flag to @tei.
  148  *   entry exists: return EEXIST
  149  *   entry not found: return ENOENT
  150  *   other error: return non-zero error code.
  151  *
  152  *
  153  *
  154  * -del: request to delete existing entry from runtime/config structures.
  155  *  typedef int (ta_del)(void *ta_state, struct table_info *ti,
  156  *     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
  157  *  MANDATORY, UH+WLOCK. (M_NOWAIT). Returns 0 on success.
  158  *
  159  *  Delete entry using previously set up in @ta_buf.
  160  * * Caller is required to do the following:
  161  *   entry deleted: return 0, set 1 to @pnum, store old value in @tei.
  162  *   entry not found: return ENOENT
  163  *   other error: return non-zero error code.
  164  *
  165  *
  166  *
  167  * -flush_entry: flush entry state created by -prepare_add / -del / others
  168  *  typedef void (ta_flush_entry)(struct ip_fw_chain *ch,
  169  *      struct tentry_info *tei, void *ta_buf);
  170  *  MANDATORY, may be locked. (M_NOWAIT).
  171  *
  172  *  Delete state allocated by:
  173  *  -prepare_add (-add returned EEXIST|UPDATED)
  174  *  -prepare_del (if any)
  175  *  -del
  176  *  * Caller is required to handle empty @ta_buf correctly.
  177  *
  178  *
  179  * -find_tentry: finds entry specified by key @tei
  180  *  typedef int ta_find_tentry(void *ta_state, struct table_info *ti,
  181  *      ipfw_obj_tentry *tent);
  182  *  OPTIONAL, locked (UH). (M_NOWAIT). Returns 0 on success.
  183  *
  184  *  Finds entry specified by given key.
  185  *  * Caller is required to do the following:
  186  *    entry found: returns 0, export entry to @tent
  187  *    entry not found: returns ENOENT
  188  *
  189  *
  190  * -need_modify: checks if @ti has enough space to hold another @count items.
  191  *  typedef int (ta_need_modify)(void *ta_state, struct table_info *ti,
  192  *      uint32_t count, uint64_t *pflags);
  193  *  OPTIONAL, locked (UH). (M_NOWAIT). Returns 0 if has.
  194  *
  195  *  Checks if given table has enough space to add @count items without
  196  *  resize. Caller may use @pflags to store desired modification data.
  197  *
  198  *
  199  *
  200  * -prepare_mod: allocate structures for table modification.
  201  *  typedef int (ta_prepare_mod)(void *ta_buf, uint64_t *pflags);
  202  * OPTIONAL(need_modify), unlocked. (M_WAITOK). Returns 0 on success.
  203  *
  204  * Allocate all needed state for table modification. Caller
  205  * should use `struct mod_item` to store new state in @ta_buf.
  206  * Up to TA_BUF_SZ (128 bytes) can be stored in @ta_buf.
  207  * 
  208  *
  209  *
  210  * -fill_mod: copy some data to new state/
  211  *  typedef int (ta_fill_mod)(void *ta_state, struct table_info *ti,
  212  *      void *ta_buf, uint64_t *pflags);
  213  * OPTIONAL(need_modify), locked (UH). (M_NOWAIT). Returns 0 on success.
  214  *
  215  * Copy as much data as we can to minimize changes under WLOCK.
  216  * For example, array can be merged inside this callback.
  217  *
  218  *
  219  *
  220  * -modify: perform final modification.
  221  *  typedef void (ta_modify)(void *ta_state, struct table_info *ti,
  222  *      void *ta_buf, uint64_t pflags);
  223  * OPTIONAL(need_modify), locked (UH+WLOCK). (M_NOWAIT). 
  224  *
  225  * Performs all changes necessary to switch to new structures.
  226  * * Caller should save old pointers to @ta_buf storage.
  227  *
  228  *
  229  *
  230  * -flush_mod: flush table modification state.
  231  *  typedef void (ta_flush_mod)(void *ta_buf);
  232  * OPTIONAL(need_modify), unlocked. (M_WAITOK).
  233  *
  234  * Performs flush for the following:
  235  *   - prepare_mod (modification was not necessary)
  236  *   - modify (for the old state)
  237  *
  238  *
  239  *
  240  * -change_gi: monitor table info pointer changes
  241  * typedef void (ta_change_ti)(void *ta_state, struct table_info *ti);
  242  * OPTIONAL, locked (UH). (M_NOWAIT).
  243  *
  244  * Called on @ti pointer changed. Called immediately after -init
  245  * to set initial state.
  246  *
  247  *
  248  *
  249  * -foreach: calls @f for each table entry
  250  *  typedef void ta_foreach(void *ta_state, struct table_info *ti,
  251  *      ta_foreach_f *f, void *arg);
  252  * MANDATORY, locked(UH). (M_NOWAIT).
  253  *
  254  * Runs callback with specified argument for each table entry,
  255  * Typically used for dumping table entries.
  256  *
  257  *
  258  *
  259  * -dump_tentry: dump table entry in current @tentry format.
  260  *  typedef int ta_dump_tentry(void *ta_state, struct table_info *ti, void *e,
  261  *      ipfw_obj_tentry *tent);
  262  * MANDATORY, locked(UH). (M_NOWAIT). Returns 0 on success.
  263  *
  264  * Dumps entry @e to @tent.
  265  *
  266  *
  267  * -print_config: prints custom algorithm options into buffer.
  268  *  typedef void (ta_print_config)(void *ta_state, struct table_info *ti,
  269  *      char *buf, size_t bufsize);
  270  * OPTIONAL. locked(UH). (M_NOWAIT).
  271  *
  272  * Prints custom algorithm options in the format suitable to pass
  273  * back to -init callback.
  274  *
  275  *
  276  *
  277  * -dump_tinfo: dumps algo-specific info.
  278  *  typedef void ta_dump_tinfo(void *ta_state, struct table_info *ti,
  279  *      ipfw_ta_tinfo *tinfo);
  280  * OPTIONAL. locked(UH). (M_NOWAIT).
  281  *
  282  * Dumps options like items size/hash size, etc.
  283  */
  284 
  285 MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables");
  286 
  287 /*
  288  * Utility structures/functions common to more than one algo
  289  */
  290 
  291 struct mod_item {
  292         void    *main_ptr;
  293         size_t  size;
  294         void    *main_ptr6;
  295         size_t  size6;
  296 };
  297 
  298 static int badd(const void *key, void *item, void *base, size_t nmemb,
  299     size_t size, int (*compar) (const void *, const void *));
  300 static int bdel(const void *key, void *base, size_t nmemb, size_t size,
  301     int (*compar) (const void *, const void *));
  302 
  303 /*
  304  * ADDR implementation using radix
  305  *
  306  */
  307 
  308 /*
  309  * The radix code expects addr and mask to be array of bytes,
  310  * with the first byte being the length of the array. rn_inithead
  311  * is called with the offset in bits of the lookup key within the
  312  * array. If we use a sockaddr_in as the underlying type,
  313  * sin_len is conveniently located at offset 0, sin_addr is at
  314  * offset 4 and normally aligned.
  315  * But for portability, let's avoid assumption and make the code explicit
  316  */
  317 #define KEY_LEN(v)      *((uint8_t *)&(v))
  318 /*
  319  * Do not require radix to compare more than actual IPv4/IPv6/MAC address
  320  */
  321 #define KEY_LEN_INET    (offsetof(struct sockaddr_in, sin_addr) + sizeof(in_addr_t))
  322 #define KEY_LEN_INET6   (offsetof(struct sa_in6, sin6_addr) + sizeof(struct in6_addr))
  323 #define KEY_LEN_MAC     (offsetof(struct sa_mac, mac_addr) + ETHER_ADDR_LEN)
  324 
  325 #define OFF_LEN_INET    (8 * offsetof(struct sockaddr_in, sin_addr))
  326 #define OFF_LEN_INET6   (8 * offsetof(struct sa_in6, sin6_addr))
  327 #define OFF_LEN_MAC     (8 * offsetof(struct sa_mac, mac_addr))
  328 
  329 struct addr_radix_entry {
  330         struct radix_node       rn[2];
  331         struct sockaddr_in      addr;
  332         uint32_t                value;
  333         uint8_t                 masklen;
  334 };
  335 
  336 struct sa_in6 {
  337         uint8_t                 sin6_len;
  338         uint8_t                 sin6_family;
  339         uint8_t                 pad[2];
  340         struct in6_addr         sin6_addr;
  341 };
  342 
  343 struct addr_radix_xentry {
  344         struct radix_node       rn[2];
  345         struct sa_in6           addr6;
  346         uint32_t                value;
  347         uint8_t                 masklen;
  348 };
  349 
  350 struct addr_radix_cfg {
  351         struct radix_node_head  *head4;
  352         struct radix_node_head  *head6;
  353         size_t                  count4;
  354         size_t                  count6;
  355 };
  356 
  357 struct sa_mac {
  358         uint8_t                 mac_len;
  359         struct ether_addr       mac_addr;
  360 };
  361 
  362 struct ta_buf_radix
  363 {
  364         void *ent_ptr;
  365         struct sockaddr *addr_ptr;
  366         struct sockaddr *mask_ptr;
  367         union {
  368                 struct {
  369                         struct sockaddr_in sa;
  370                         struct sockaddr_in ma;
  371                 } a4;
  372                 struct {
  373                         struct sa_in6 sa;
  374                         struct sa_in6 ma;
  375                 } a6;
  376                 struct {
  377                         struct sa_mac sa;
  378                         struct sa_mac ma;
  379                 } mac;
  380         } addr;
  381 };
  382 
  383 static int ta_lookup_addr_radix(struct table_info *ti, void *key, uint32_t keylen,
  384     uint32_t *val);
  385 static int ta_init_addr_radix(struct ip_fw_chain *ch, void **ta_state,
  386     struct table_info *ti, char *data, uint8_t tflags);
  387 static int flush_radix_entry(struct radix_node *rn, void *arg);
  388 static void ta_destroy_addr_radix(void *ta_state, struct table_info *ti);
  389 static void ta_dump_addr_radix_tinfo(void *ta_state, struct table_info *ti,
  390     ipfw_ta_tinfo *tinfo);
  391 static int ta_dump_addr_radix_tentry(void *ta_state, struct table_info *ti,
  392     void *e, ipfw_obj_tentry *tent);
  393 static int ta_find_addr_radix_tentry(void *ta_state, struct table_info *ti,
  394     ipfw_obj_tentry *tent);
  395 static void ta_foreach_addr_radix(void *ta_state, struct table_info *ti,
  396     ta_foreach_f *f, void *arg);
  397 static void tei_to_sockaddr_ent_addr(struct tentry_info *tei, struct sockaddr *sa,
  398     struct sockaddr *ma, int *set_mask);
  399 static int ta_prepare_add_addr_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
  400     void *ta_buf);
  401 static int ta_add_addr_radix(void *ta_state, struct table_info *ti,
  402     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
  403 static int ta_prepare_del_addr_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
  404     void *ta_buf);
  405 static int ta_del_addr_radix(void *ta_state, struct table_info *ti,
  406     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
  407 static void ta_flush_radix_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
  408     void *ta_buf);
  409 static int ta_need_modify_radix(void *ta_state, struct table_info *ti,
  410     uint32_t count, uint64_t *pflags);
  411 
  412 static int
  413 ta_lookup_addr_radix(struct table_info *ti, void *key, uint32_t keylen,
  414     uint32_t *val)
  415 {
  416         struct radix_node_head *rnh;
  417 
  418         if (keylen == sizeof(in_addr_t)) {
  419                 struct addr_radix_entry *ent;
  420                 struct sockaddr_in sa;
  421                 KEY_LEN(sa) = KEY_LEN_INET;
  422                 sa.sin_addr.s_addr = *((in_addr_t *)key);
  423                 rnh = (struct radix_node_head *)ti->state;
  424                 ent = (struct addr_radix_entry *)(rnh->rnh_matchaddr(&sa, &rnh->rh));
  425                 if (ent != NULL) {
  426                         *val = ent->value;
  427                         return (1);
  428                 }
  429         } else if (keylen == sizeof(struct in6_addr)) {
  430                 struct addr_radix_xentry *xent;
  431                 struct sa_in6 sa6;
  432                 KEY_LEN(sa6) = KEY_LEN_INET6;
  433                 memcpy(&sa6.sin6_addr, key, sizeof(struct in6_addr));
  434                 rnh = (struct radix_node_head *)ti->xstate;
  435                 xent = (struct addr_radix_xentry *)(rnh->rnh_matchaddr(&sa6, &rnh->rh));
  436                 if (xent != NULL) {
  437                         *val = xent->value;
  438                         return (1);
  439                 }
  440         }
  441 
  442         return (0);
  443 }
  444 
  445 /*
  446  * New table
  447  */
  448 static int
  449 ta_init_addr_radix(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
  450     char *data, uint8_t tflags)
  451 {
  452         struct addr_radix_cfg *cfg;
  453 
  454         if (!rn_inithead(&ti->state, OFF_LEN_INET))
  455                 return (ENOMEM);
  456         if (!rn_inithead(&ti->xstate, OFF_LEN_INET6)) {
  457                 rn_detachhead(&ti->state);
  458                 return (ENOMEM);
  459         }
  460 
  461         cfg = malloc(sizeof(struct addr_radix_cfg), M_IPFW, M_WAITOK | M_ZERO);
  462 
  463         *ta_state = cfg;
  464         ti->lookup = ta_lookup_addr_radix;
  465 
  466         return (0);
  467 }
  468 
  469 static int
  470 flush_radix_entry(struct radix_node *rn, void *arg)
  471 {
  472         struct radix_node_head * const rnh = arg;
  473         struct addr_radix_entry *ent;
  474 
  475         ent = (struct addr_radix_entry *)
  476             rnh->rnh_deladdr(rn->rn_key, rn->rn_mask, &rnh->rh);
  477         if (ent != NULL)
  478                 free(ent, M_IPFW_TBL);
  479         return (0);
  480 }
  481 
  482 static void
  483 ta_destroy_addr_radix(void *ta_state, struct table_info *ti)
  484 {
  485         struct addr_radix_cfg *cfg;
  486         struct radix_node_head *rnh;
  487 
  488         cfg = (struct addr_radix_cfg *)ta_state;
  489 
  490         rnh = (struct radix_node_head *)(ti->state);
  491         rnh->rnh_walktree(&rnh->rh, flush_radix_entry, rnh);
  492         rn_detachhead(&ti->state);
  493 
  494         rnh = (struct radix_node_head *)(ti->xstate);
  495         rnh->rnh_walktree(&rnh->rh, flush_radix_entry, rnh);
  496         rn_detachhead(&ti->xstate);
  497 
  498         free(cfg, M_IPFW);
  499 }
  500 
  501 /*
  502  * Provide algo-specific table info
  503  */
  504 static void
  505 ta_dump_addr_radix_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
  506 {
  507         struct addr_radix_cfg *cfg;
  508 
  509         cfg = (struct addr_radix_cfg *)ta_state;
  510 
  511         tinfo->flags = IPFW_TATFLAGS_AFDATA | IPFW_TATFLAGS_AFITEM;
  512         tinfo->taclass4 = IPFW_TACLASS_RADIX;
  513         tinfo->count4 = cfg->count4;
  514         tinfo->itemsize4 = sizeof(struct addr_radix_entry);
  515         tinfo->taclass6 = IPFW_TACLASS_RADIX;
  516         tinfo->count6 = cfg->count6;
  517         tinfo->itemsize6 = sizeof(struct addr_radix_xentry);
  518 }
  519 
  520 static int
  521 ta_dump_addr_radix_tentry(void *ta_state, struct table_info *ti, void *e,
  522     ipfw_obj_tentry *tent)
  523 {
  524         struct addr_radix_entry *n;
  525 #ifdef INET6
  526         struct addr_radix_xentry *xn;
  527 #endif
  528 
  529         n = (struct addr_radix_entry *)e;
  530 
  531         /* Guess IPv4/IPv6 radix by sockaddr family */
  532         if (n->addr.sin_family == AF_INET) {
  533                 tent->k.addr.s_addr = n->addr.sin_addr.s_addr;
  534                 tent->masklen = n->masklen;
  535                 tent->subtype = AF_INET;
  536                 tent->v.kidx = n->value;
  537 #ifdef INET6
  538         } else {
  539                 xn = (struct addr_radix_xentry *)e;
  540                 memcpy(&tent->k.addr6, &xn->addr6.sin6_addr,
  541                     sizeof(struct in6_addr));
  542                 tent->masklen = xn->masklen;
  543                 tent->subtype = AF_INET6;
  544                 tent->v.kidx = xn->value;
  545 #endif
  546         }
  547 
  548         return (0);
  549 }
  550 
  551 static int
  552 ta_find_addr_radix_tentry(void *ta_state, struct table_info *ti,
  553     ipfw_obj_tentry *tent)
  554 {
  555         struct radix_node_head *rnh;
  556         void *e;
  557 
  558         e = NULL;
  559         if (tent->subtype == AF_INET) {
  560                 struct sockaddr_in sa;
  561                 KEY_LEN(sa) = KEY_LEN_INET;
  562                 sa.sin_addr.s_addr = tent->k.addr.s_addr;
  563                 rnh = (struct radix_node_head *)ti->state;
  564                 e = rnh->rnh_matchaddr(&sa, &rnh->rh);
  565         } else if (tent->subtype == AF_INET6) {
  566                 struct sa_in6 sa6;
  567                 KEY_LEN(sa6) = KEY_LEN_INET6;
  568                 memcpy(&sa6.sin6_addr, &tent->k.addr6, sizeof(struct in6_addr));
  569                 rnh = (struct radix_node_head *)ti->xstate;
  570                 e = rnh->rnh_matchaddr(&sa6, &rnh->rh);
  571         }
  572 
  573         if (e != NULL) {
  574                 ta_dump_addr_radix_tentry(ta_state, ti, e, tent);
  575                 return (0);
  576         }
  577 
  578         return (ENOENT);
  579 }
  580 
  581 static void
  582 ta_foreach_addr_radix(void *ta_state, struct table_info *ti, ta_foreach_f *f,
  583     void *arg)
  584 {
  585         struct radix_node_head *rnh;
  586 
  587         rnh = (struct radix_node_head *)(ti->state);
  588         rnh->rnh_walktree(&rnh->rh, (walktree_f_t *)f, arg);
  589 
  590         rnh = (struct radix_node_head *)(ti->xstate);
  591         rnh->rnh_walktree(&rnh->rh, (walktree_f_t *)f, arg);
  592 }
  593 
  594 #ifdef INET6
  595 static inline void ipv6_writemask(struct in6_addr *addr6, uint8_t mask);
  596 
  597 static inline void
  598 ipv6_writemask(struct in6_addr *addr6, uint8_t mask)
  599 {
  600         uint32_t *cp;
  601 
  602         for (cp = (uint32_t *)addr6; mask >= 32; mask -= 32)
  603                 *cp++ = 0xFFFFFFFF;
  604         if (mask > 0)
  605                 *cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0);
  606 }
  607 #endif
  608 
  609 static void
  610 tei_to_sockaddr_ent_addr(struct tentry_info *tei, struct sockaddr *sa,
  611     struct sockaddr *ma, int *set_mask)
  612 {
  613         int mlen;
  614 #ifdef INET
  615         struct sockaddr_in *addr, *mask;
  616 #endif
  617 #ifdef INET6
  618         struct sa_in6 *addr6, *mask6;
  619 #endif
  620         in_addr_t a4;
  621 
  622         mlen = tei->masklen;
  623 
  624         if (tei->subtype == AF_INET) {
  625 #ifdef INET
  626                 addr = (struct sockaddr_in *)sa;
  627                 mask = (struct sockaddr_in *)ma;
  628                 /* Set 'total' structure length */
  629                 KEY_LEN(*addr) = KEY_LEN_INET;
  630                 KEY_LEN(*mask) = KEY_LEN_INET;
  631                 addr->sin_family = AF_INET;
  632                 mask->sin_addr.s_addr =
  633                     htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
  634                 a4 = *((in_addr_t *)tei->paddr);
  635                 addr->sin_addr.s_addr = a4 & mask->sin_addr.s_addr;
  636                 if (mlen != 32)
  637                         *set_mask = 1;
  638                 else
  639                         *set_mask = 0;
  640 #endif
  641 #ifdef INET6
  642         } else if (tei->subtype == AF_INET6) {
  643                 /* IPv6 case */
  644                 addr6 = (struct sa_in6 *)sa;
  645                 mask6 = (struct sa_in6 *)ma;
  646                 /* Set 'total' structure length */
  647                 KEY_LEN(*addr6) = KEY_LEN_INET6;
  648                 KEY_LEN(*mask6) = KEY_LEN_INET6;
  649                 addr6->sin6_family = AF_INET6;
  650                 ipv6_writemask(&mask6->sin6_addr, mlen);
  651                 memcpy(&addr6->sin6_addr, tei->paddr, sizeof(struct in6_addr));
  652                 APPLY_MASK(&addr6->sin6_addr, &mask6->sin6_addr);
  653                 if (mlen != 128)
  654                         *set_mask = 1;
  655                 else
  656                         *set_mask = 0;
  657 #endif
  658         }
  659 }
  660 
  661 static int
  662 ta_prepare_add_addr_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
  663     void *ta_buf)
  664 {
  665         struct ta_buf_radix *tb;
  666         struct addr_radix_entry *ent;
  667 #ifdef INET6
  668         struct addr_radix_xentry *xent;
  669 #endif
  670         struct sockaddr *addr, *mask;
  671         int mlen, set_mask;
  672 
  673         tb = (struct ta_buf_radix *)ta_buf;
  674 
  675         mlen = tei->masklen;
  676         set_mask = 0;
  677 
  678         if (tei->subtype == AF_INET) {
  679 #ifdef INET
  680                 if (mlen > 32)
  681                         return (EINVAL);
  682                 ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO);
  683                 ent->masklen = mlen;
  684 
  685                 addr = (struct sockaddr *)&ent->addr;
  686                 mask = (struct sockaddr *)&tb->addr.a4.ma;
  687                 tb->ent_ptr = ent;
  688 #endif
  689 #ifdef INET6
  690         } else if (tei->subtype == AF_INET6) {
  691                 /* IPv6 case */
  692                 if (mlen > 128)
  693                         return (EINVAL);
  694                 xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
  695                 xent->masklen = mlen;
  696 
  697                 addr = (struct sockaddr *)&xent->addr6;
  698                 mask = (struct sockaddr *)&tb->addr.a6.ma;
  699                 tb->ent_ptr = xent;
  700 #endif
  701         } else {
  702                 /* Unknown CIDR type */
  703                 return (EINVAL);
  704         }
  705 
  706         tei_to_sockaddr_ent_addr(tei, addr, mask, &set_mask);
  707         /* Set pointers */
  708         tb->addr_ptr = addr;
  709         if (set_mask != 0)
  710                 tb->mask_ptr = mask;
  711 
  712         return (0);
  713 }
  714 
  715 static int
  716 ta_add_addr_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei,
  717     void *ta_buf, uint32_t *pnum)
  718 {
  719         struct addr_radix_cfg *cfg;
  720         struct radix_node_head *rnh;
  721         struct radix_node *rn;
  722         struct ta_buf_radix *tb;
  723         uint32_t *old_value, value;
  724 
  725         cfg = (struct addr_radix_cfg *)ta_state;
  726         tb = (struct ta_buf_radix *)ta_buf;
  727 
  728         /* Save current entry value from @tei */
  729         if (tei->subtype == AF_INET) {
  730                 rnh = ti->state;
  731                 ((struct addr_radix_entry *)tb->ent_ptr)->value = tei->value;
  732         } else {
  733                 rnh = ti->xstate;
  734                 ((struct addr_radix_xentry *)tb->ent_ptr)->value = tei->value;
  735         }
  736 
  737         /* Search for an entry first */
  738         rn = rnh->rnh_lookup(tb->addr_ptr, tb->mask_ptr, &rnh->rh);
  739         if (rn != NULL) {
  740                 if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
  741                         return (EEXIST);
  742                 /* Record already exists. Update value if we're asked to */
  743                 if (tei->subtype == AF_INET)
  744                         old_value = &((struct addr_radix_entry *)rn)->value;
  745                 else
  746                         old_value = &((struct addr_radix_xentry *)rn)->value;
  747 
  748                 value = *old_value;
  749                 *old_value = tei->value;
  750                 tei->value = value;
  751 
  752                 /* Indicate that update has happened instead of addition */
  753                 tei->flags |= TEI_FLAGS_UPDATED;
  754                 *pnum = 0;
  755 
  756                 return (0);
  757         }
  758 
  759         if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
  760                 return (EFBIG);
  761 
  762         rn = rnh->rnh_addaddr(tb->addr_ptr, tb->mask_ptr, &rnh->rh,tb->ent_ptr);
  763         if (rn == NULL) {
  764                 /* Unknown error */
  765                 return (EINVAL);
  766         }
  767 
  768         if (tei->subtype == AF_INET)
  769                 cfg->count4++;
  770         else
  771                 cfg->count6++;
  772         tb->ent_ptr = NULL;
  773         *pnum = 1;
  774 
  775         return (0);
  776 }
  777 
  778 static int
  779 ta_prepare_del_addr_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
  780     void *ta_buf)
  781 {
  782         struct ta_buf_radix *tb;
  783         struct sockaddr *addr, *mask;
  784         int mlen, set_mask;
  785 
  786         tb = (struct ta_buf_radix *)ta_buf;
  787 
  788         mlen = tei->masklen;
  789         set_mask = 0;
  790 
  791         if (tei->subtype == AF_INET) {
  792                 if (mlen > 32)
  793                         return (EINVAL);
  794 
  795                 addr = (struct sockaddr *)&tb->addr.a4.sa;
  796                 mask = (struct sockaddr *)&tb->addr.a4.ma;
  797 #ifdef INET6
  798         } else if (tei->subtype == AF_INET6) {
  799                 if (mlen > 128)
  800                         return (EINVAL);
  801 
  802                 addr = (struct sockaddr *)&tb->addr.a6.sa;
  803                 mask = (struct sockaddr *)&tb->addr.a6.ma;
  804 #endif
  805         } else
  806                 return (EINVAL);
  807 
  808         tei_to_sockaddr_ent_addr(tei, addr, mask, &set_mask);
  809         tb->addr_ptr = addr;
  810         if (set_mask != 0)
  811                 tb->mask_ptr = mask;
  812 
  813         return (0);
  814 }
  815 
  816 static int
  817 ta_del_addr_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei,
  818     void *ta_buf, uint32_t *pnum)
  819 {
  820         struct addr_radix_cfg *cfg;
  821         struct radix_node_head *rnh;
  822         struct radix_node *rn;
  823         struct ta_buf_radix *tb;
  824 
  825         cfg = (struct addr_radix_cfg *)ta_state;
  826         tb = (struct ta_buf_radix *)ta_buf;
  827 
  828         if (tei->subtype == AF_INET)
  829                 rnh = ti->state;
  830         else
  831                 rnh = ti->xstate;
  832 
  833         rn = rnh->rnh_deladdr(tb->addr_ptr, tb->mask_ptr, &rnh->rh);
  834 
  835         if (rn == NULL)
  836                 return (ENOENT);
  837 
  838         /* Save entry value to @tei */
  839         if (tei->subtype == AF_INET)
  840                 tei->value = ((struct addr_radix_entry *)rn)->value;
  841         else
  842                 tei->value = ((struct addr_radix_xentry *)rn)->value;
  843 
  844         tb->ent_ptr = rn;
  845 
  846         if (tei->subtype == AF_INET)
  847                 cfg->count4--;
  848         else
  849                 cfg->count6--;
  850         *pnum = 1;
  851 
  852         return (0);
  853 }
  854 
  855 static void
  856 ta_flush_radix_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
  857     void *ta_buf)
  858 {
  859         struct ta_buf_radix *tb;
  860 
  861         tb = (struct ta_buf_radix *)ta_buf;
  862 
  863         if (tb->ent_ptr != NULL)
  864                 free(tb->ent_ptr, M_IPFW_TBL);
  865 }
  866 
  867 static int
  868 ta_need_modify_radix(void *ta_state, struct table_info *ti, uint32_t count,
  869     uint64_t *pflags)
  870 {
  871 
  872         /*
  873          * radix does not require additional memory allocations
  874          * other than nodes itself. Adding new masks to the tree do
  875          * but we don't have any API to call (and we don't known which
  876          * sizes do we need).
  877          */
  878         return (0);
  879 }
  880 
  881 struct table_algo addr_radix = {
  882         .name           = "addr:radix",
  883         .type           = IPFW_TABLE_ADDR,
  884         .flags          = TA_FLAG_DEFAULT,
  885         .ta_buf_size    = sizeof(struct ta_buf_radix),
  886         .init           = ta_init_addr_radix,
  887         .destroy        = ta_destroy_addr_radix,
  888         .prepare_add    = ta_prepare_add_addr_radix,
  889         .prepare_del    = ta_prepare_del_addr_radix,
  890         .add            = ta_add_addr_radix,
  891         .del            = ta_del_addr_radix,
  892         .flush_entry    = ta_flush_radix_entry,
  893         .foreach        = ta_foreach_addr_radix,
  894         .dump_tentry    = ta_dump_addr_radix_tentry,
  895         .find_tentry    = ta_find_addr_radix_tentry,
  896         .dump_tinfo     = ta_dump_addr_radix_tinfo,
  897         .need_modify    = ta_need_modify_radix,
  898 };
  899 
  900 /*
  901  * addr:hash cmds
  902  *
  903  *
  904  * ti->data:
  905  * [inv.mask4][inv.mask6][log2hsize4][log2hsize6]
  906  * [        8][        8[          8][         8]
  907  *
  908  * inv.mask4: 32 - mask
  909  * inv.mask6:
  910  * 1) _slow lookup: mask
  911  * 2) _aligned: (128 - mask) / 8
  912  * 3) _64: 8
  913  *
  914  *
  915  * pflags:
  916  * [v4=1/v6=0][hsize]
  917  * [       32][   32]
  918  */
  919 
  920 struct chashentry;
  921 
  922 SLIST_HEAD(chashbhead, chashentry);
  923 
  924 struct chash_cfg {
  925         struct chashbhead *head4;
  926         struct chashbhead *head6;
  927         size_t  size4;
  928         size_t  size6;
  929         size_t  items4;
  930         size_t  items6;
  931         uint8_t mask4;
  932         uint8_t mask6;
  933 };
  934 
  935 struct chashentry {
  936         SLIST_ENTRY(chashentry) next;
  937         uint32_t        value;
  938         uint32_t        type;
  939         union {
  940                 uint32_t        a4;     /* Host format */
  941                 struct in6_addr a6;     /* Network format */
  942         } a;
  943 };
  944 
  945 struct ta_buf_chash
  946 {
  947         void *ent_ptr;
  948         struct chashentry ent;
  949 };
  950 
  951 #ifdef INET
  952 static __inline uint32_t hash_ip(uint32_t addr, int hsize);
  953 #endif
  954 #ifdef INET6
  955 static __inline uint32_t hash_ip6(struct in6_addr *addr6, int hsize);
  956 static __inline uint16_t hash_ip64(struct in6_addr *addr6, int hsize);
  957 static __inline uint32_t hash_ip6_slow(struct in6_addr *addr6, void *key,
  958     int mask, int hsize);
  959 static __inline uint32_t hash_ip6_al(struct in6_addr *addr6, void *key, int mask,
  960     int hsize);
  961 #endif
  962 static int ta_lookup_chash_slow(struct table_info *ti, void *key, uint32_t keylen,
  963     uint32_t *val);
  964 static int ta_lookup_chash_aligned(struct table_info *ti, void *key,
  965     uint32_t keylen, uint32_t *val);
  966 static int ta_lookup_chash_64(struct table_info *ti, void *key, uint32_t keylen,
  967     uint32_t *val);
  968 static int chash_parse_opts(struct chash_cfg *cfg, char *data);
  969 static void ta_print_chash_config(void *ta_state, struct table_info *ti,
  970     char *buf, size_t bufsize);
  971 static int ta_log2(uint32_t v);
  972 static int ta_init_chash(struct ip_fw_chain *ch, void **ta_state,
  973     struct table_info *ti, char *data, uint8_t tflags);
  974 static void ta_destroy_chash(void *ta_state, struct table_info *ti);
  975 static void ta_dump_chash_tinfo(void *ta_state, struct table_info *ti,
  976     ipfw_ta_tinfo *tinfo);
  977 static int ta_dump_chash_tentry(void *ta_state, struct table_info *ti,
  978     void *e, ipfw_obj_tentry *tent);
  979 static uint32_t hash_ent(struct chashentry *ent, int af, int mlen,
  980     uint32_t size);
  981 static int tei_to_chash_ent(struct tentry_info *tei, struct chashentry *ent);
  982 static int ta_find_chash_tentry(void *ta_state, struct table_info *ti,
  983     ipfw_obj_tentry *tent);
  984 static void ta_foreach_chash(void *ta_state, struct table_info *ti,
  985     ta_foreach_f *f, void *arg);
  986 static int ta_prepare_add_chash(struct ip_fw_chain *ch, struct tentry_info *tei,
  987     void *ta_buf);
  988 static int ta_add_chash(void *ta_state, struct table_info *ti,
  989     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
  990 static int ta_prepare_del_chash(struct ip_fw_chain *ch, struct tentry_info *tei,
  991     void *ta_buf);
  992 static int ta_del_chash(void *ta_state, struct table_info *ti,
  993     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
  994 static void ta_flush_chash_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
  995     void *ta_buf);
  996 static int ta_need_modify_chash(void *ta_state, struct table_info *ti,
  997     uint32_t count, uint64_t *pflags);
  998 static int ta_prepare_mod_chash(void *ta_buf, uint64_t *pflags);
  999 static int ta_fill_mod_chash(void *ta_state, struct table_info *ti, void *ta_buf,
 1000     uint64_t *pflags);
 1001 static void ta_modify_chash(void *ta_state, struct table_info *ti, void *ta_buf,
 1002     uint64_t pflags);
 1003 static void ta_flush_mod_chash(void *ta_buf);
 1004 
 1005 #ifdef INET
 1006 static __inline uint32_t
 1007 hash_ip(uint32_t addr, int hsize)
 1008 {
 1009 
 1010         return (addr % (hsize - 1));
 1011 }
 1012 #endif
 1013 
 1014 #ifdef INET6
 1015 static __inline uint32_t
 1016 hash_ip6(struct in6_addr *addr6, int hsize)
 1017 {
 1018         uint32_t i;
 1019 
 1020         i = addr6->s6_addr32[0] ^ addr6->s6_addr32[1] ^
 1021             addr6->s6_addr32[2] ^ addr6->s6_addr32[3];
 1022 
 1023         return (i % (hsize - 1));
 1024 }
 1025 
 1026 static __inline uint16_t
 1027 hash_ip64(struct in6_addr *addr6, int hsize)
 1028 {
 1029         uint32_t i;
 1030 
 1031         i = addr6->s6_addr32[0] ^ addr6->s6_addr32[1];
 1032 
 1033         return (i % (hsize - 1));
 1034 }
 1035 
 1036 static __inline uint32_t
 1037 hash_ip6_slow(struct in6_addr *addr6, void *key, int mask, int hsize)
 1038 {
 1039         struct in6_addr mask6;
 1040 
 1041         ipv6_writemask(&mask6, mask);
 1042         memcpy(addr6, key, sizeof(struct in6_addr));
 1043         APPLY_MASK(addr6, &mask6);
 1044         return (hash_ip6(addr6, hsize));
 1045 }
 1046 
 1047 static __inline uint32_t
 1048 hash_ip6_al(struct in6_addr *addr6, void *key, int mask, int hsize)
 1049 {
 1050         uint64_t *paddr;
 1051 
 1052         paddr = (uint64_t *)addr6;
 1053         *paddr = 0;
 1054         *(paddr + 1) = 0;
 1055         memcpy(addr6, key, mask);
 1056         return (hash_ip6(addr6, hsize));
 1057 }
 1058 #endif
 1059 
 1060 static int
 1061 ta_lookup_chash_slow(struct table_info *ti, void *key, uint32_t keylen,
 1062     uint32_t *val)
 1063 {
 1064         struct chashbhead *head;
 1065         struct chashentry *ent;
 1066         uint16_t hash, hsize;
 1067         uint8_t imask;
 1068 
 1069         if (keylen == sizeof(in_addr_t)) {
 1070 #ifdef INET
 1071                 head = (struct chashbhead *)ti->state;
 1072                 imask = ti->data >> 24;
 1073                 hsize = 1 << ((ti->data & 0xFFFF) >> 8);
 1074                 uint32_t a;
 1075                 a = ntohl(*((in_addr_t *)key));
 1076                 a = a >> imask;
 1077                 hash = hash_ip(a, hsize);
 1078                 SLIST_FOREACH(ent, &head[hash], next) {
 1079                         if (ent->a.a4 == a) {
 1080                                 *val = ent->value;
 1081                                 return (1);
 1082                         }
 1083                 }
 1084 #endif
 1085         } else {
 1086 #ifdef INET6
 1087                 /* IPv6: worst scenario: non-round mask */
 1088                 struct in6_addr addr6;
 1089                 head = (struct chashbhead *)ti->xstate;
 1090                 imask = (ti->data & 0xFF0000) >> 16;
 1091                 hsize = 1 << (ti->data & 0xFF);
 1092                 hash = hash_ip6_slow(&addr6, key, imask, hsize);
 1093                 SLIST_FOREACH(ent, &head[hash], next) {
 1094                         if (memcmp(&ent->a.a6, &addr6, 16) == 0) {
 1095                                 *val = ent->value;
 1096                                 return (1);
 1097                         }
 1098                 }
 1099 #endif
 1100         }
 1101 
 1102         return (0);
 1103 }
 1104 
 1105 static int
 1106 ta_lookup_chash_aligned(struct table_info *ti, void *key, uint32_t keylen,
 1107     uint32_t *val)
 1108 {
 1109         struct chashbhead *head;
 1110         struct chashentry *ent;
 1111         uint16_t hash, hsize;
 1112         uint8_t imask;
 1113 
 1114         if (keylen == sizeof(in_addr_t)) {
 1115 #ifdef INET
 1116                 head = (struct chashbhead *)ti->state;
 1117                 imask = ti->data >> 24;
 1118                 hsize = 1 << ((ti->data & 0xFFFF) >> 8);
 1119                 uint32_t a;
 1120                 a = ntohl(*((in_addr_t *)key));
 1121                 a = a >> imask;
 1122                 hash = hash_ip(a, hsize);
 1123                 SLIST_FOREACH(ent, &head[hash], next) {
 1124                         if (ent->a.a4 == a) {
 1125                                 *val = ent->value;
 1126                                 return (1);
 1127                         }
 1128                 }
 1129 #endif
 1130         } else {
 1131 #ifdef INET6
 1132                 /* IPv6: aligned to 8bit mask */
 1133                 struct in6_addr addr6;
 1134                 uint64_t *paddr, *ptmp;
 1135                 head = (struct chashbhead *)ti->xstate;
 1136                 imask = (ti->data & 0xFF0000) >> 16;
 1137                 hsize = 1 << (ti->data & 0xFF);
 1138 
 1139                 hash = hash_ip6_al(&addr6, key, imask, hsize);
 1140                 paddr = (uint64_t *)&addr6;
 1141                 SLIST_FOREACH(ent, &head[hash], next) {
 1142                         ptmp = (uint64_t *)&ent->a.a6;
 1143                         if (paddr[0] == ptmp[0] && paddr[1] == ptmp[1]) {
 1144                                 *val = ent->value;
 1145                                 return (1);
 1146                         }
 1147                 }
 1148 #endif
 1149         }
 1150 
 1151         return (0);
 1152 }
 1153 
 1154 static int
 1155 ta_lookup_chash_64(struct table_info *ti, void *key, uint32_t keylen,
 1156     uint32_t *val)
 1157 {
 1158         struct chashbhead *head;
 1159         struct chashentry *ent;
 1160         uint16_t hash, hsize;
 1161         uint8_t imask;
 1162 
 1163         if (keylen == sizeof(in_addr_t)) {
 1164 #ifdef INET
 1165                 head = (struct chashbhead *)ti->state;
 1166                 imask = ti->data >> 24;
 1167                 hsize = 1 << ((ti->data & 0xFFFF) >> 8);
 1168                 uint32_t a;
 1169                 a = ntohl(*((in_addr_t *)key));
 1170                 a = a >> imask;
 1171                 hash = hash_ip(a, hsize);
 1172                 SLIST_FOREACH(ent, &head[hash], next) {
 1173                         if (ent->a.a4 == a) {
 1174                                 *val = ent->value;
 1175                                 return (1);
 1176                         }
 1177                 }
 1178 #endif
 1179         } else {
 1180 #ifdef INET6
 1181                 /* IPv6: /64 */
 1182                 uint64_t a6, *paddr;
 1183                 head = (struct chashbhead *)ti->xstate;
 1184                 paddr = (uint64_t *)key;
 1185                 hsize = 1 << (ti->data & 0xFF);
 1186                 a6 = *paddr;
 1187                 hash = hash_ip64((struct in6_addr *)key, hsize);
 1188                 SLIST_FOREACH(ent, &head[hash], next) {
 1189                         paddr = (uint64_t *)&ent->a.a6;
 1190                         if (a6 == *paddr) {
 1191                                 *val = ent->value;
 1192                                 return (1);
 1193                         }
 1194                 }
 1195 #endif
 1196         }
 1197 
 1198         return (0);
 1199 }
 1200 
 1201 static int
 1202 chash_parse_opts(struct chash_cfg *cfg, char *data)
 1203 {
 1204         char *pdel, *pend, *s;
 1205         int mask4, mask6;
 1206 
 1207         mask4 = cfg->mask4;
 1208         mask6 = cfg->mask6;
 1209 
 1210         if (data == NULL)
 1211                 return (0);
 1212         if ((pdel = strchr(data, ' ')) == NULL)
 1213                 return (0);
 1214         while (*pdel == ' ')
 1215                 pdel++;
 1216         if (strncmp(pdel, "masks=", 6) != 0)
 1217                 return (EINVAL);
 1218         if ((s = strchr(pdel, ' ')) != NULL)
 1219                 *s++ = '\0';
 1220 
 1221         pdel += 6;
 1222         /* Need /XX[,/YY] */
 1223         if (*pdel++ != '/')
 1224                 return (EINVAL);
 1225         mask4 = strtol(pdel, &pend, 10);
 1226         if (*pend == ',') {
 1227                 /* ,/YY */
 1228                 pdel = pend + 1;
 1229                 if (*pdel++ != '/')
 1230                         return (EINVAL);
 1231                 mask6 = strtol(pdel, &pend, 10);
 1232                 if (*pend != '\0')
 1233                         return (EINVAL);
 1234         } else if (*pend != '\0')
 1235                 return (EINVAL);
 1236 
 1237         if (mask4 < 0 || mask4 > 32 || mask6 < 0 || mask6 > 128)
 1238                 return (EINVAL);
 1239 
 1240         cfg->mask4 = mask4;
 1241         cfg->mask6 = mask6;
 1242 
 1243         return (0);
 1244 }
 1245 
 1246 static void
 1247 ta_print_chash_config(void *ta_state, struct table_info *ti, char *buf,
 1248     size_t bufsize)
 1249 {
 1250         struct chash_cfg *cfg;
 1251 
 1252         cfg = (struct chash_cfg *)ta_state;
 1253 
 1254         if (cfg->mask4 != 32 || cfg->mask6 != 128)
 1255                 snprintf(buf, bufsize, "%s masks=/%d,/%d", "addr:hash",
 1256                     cfg->mask4, cfg->mask6);
 1257         else
 1258                 snprintf(buf, bufsize, "%s", "addr:hash");
 1259 }
 1260 
 1261 static int
 1262 ta_log2(uint32_t v)
 1263 {
 1264         uint32_t r;
 1265 
 1266         r = 0;
 1267         while (v >>= 1)
 1268                 r++;
 1269 
 1270         return (r);
 1271 }
 1272 
 1273 /*
 1274  * New table.
 1275  * We assume 'data' to be either NULL or the following format:
 1276  * 'addr:hash [masks=/32[,/128]]'
 1277  */
 1278 static int
 1279 ta_init_chash(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
 1280     char *data, uint8_t tflags)
 1281 {
 1282         int error, i;
 1283         uint32_t hsize;
 1284         struct chash_cfg *cfg;
 1285 
 1286         cfg = malloc(sizeof(struct chash_cfg), M_IPFW, M_WAITOK | M_ZERO);
 1287 
 1288         cfg->mask4 = 32;
 1289         cfg->mask6 = 128;
 1290 
 1291         if ((error = chash_parse_opts(cfg, data)) != 0) {
 1292                 free(cfg, M_IPFW);
 1293                 return (error);
 1294         }
 1295 
 1296         cfg->size4 = 128;
 1297         cfg->size6 = 128;
 1298 
 1299         cfg->head4 = malloc(sizeof(struct chashbhead) * cfg->size4, M_IPFW,
 1300             M_WAITOK | M_ZERO);
 1301         cfg->head6 = malloc(sizeof(struct chashbhead) * cfg->size6, M_IPFW,
 1302             M_WAITOK | M_ZERO);
 1303         for (i = 0; i < cfg->size4; i++)
 1304                 SLIST_INIT(&cfg->head4[i]);
 1305         for (i = 0; i < cfg->size6; i++)
 1306                 SLIST_INIT(&cfg->head6[i]);
 1307 
 1308         *ta_state = cfg;
 1309         ti->state = cfg->head4;
 1310         ti->xstate = cfg->head6;
 1311 
 1312         /* Store data depending on v6 mask length */
 1313         hsize = ta_log2(cfg->size4) << 8 | ta_log2(cfg->size6);
 1314         if (cfg->mask6 == 64) {
 1315                 ti->data = (32 - cfg->mask4) << 24 | (128 - cfg->mask6) << 16|
 1316                     hsize;
 1317                 ti->lookup = ta_lookup_chash_64;
 1318         } else if ((cfg->mask6  % 8) == 0) {
 1319                 ti->data = (32 - cfg->mask4) << 24 |
 1320                     cfg->mask6 << 13 | hsize;
 1321                 ti->lookup = ta_lookup_chash_aligned;
 1322         } else {
 1323                 /* don't do that! */
 1324                 ti->data = (32 - cfg->mask4) << 24 |
 1325                     cfg->mask6 << 16 | hsize;
 1326                 ti->lookup = ta_lookup_chash_slow;
 1327         }
 1328 
 1329         return (0);
 1330 }
 1331 
 1332 static void
 1333 ta_destroy_chash(void *ta_state, struct table_info *ti)
 1334 {
 1335         struct chash_cfg *cfg;
 1336         struct chashentry *ent, *ent_next;
 1337         int i;
 1338 
 1339         cfg = (struct chash_cfg *)ta_state;
 1340 
 1341         for (i = 0; i < cfg->size4; i++)
 1342                 SLIST_FOREACH_SAFE(ent, &cfg->head4[i], next, ent_next)
 1343                         free(ent, M_IPFW_TBL);
 1344 
 1345         for (i = 0; i < cfg->size6; i++)
 1346                 SLIST_FOREACH_SAFE(ent, &cfg->head6[i], next, ent_next)
 1347                         free(ent, M_IPFW_TBL);
 1348 
 1349         free(cfg->head4, M_IPFW);
 1350         free(cfg->head6, M_IPFW);
 1351 
 1352         free(cfg, M_IPFW);
 1353 }
 1354 
 1355 static void
 1356 ta_dump_chash_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
 1357 {
 1358         struct chash_cfg *cfg;
 1359 
 1360         cfg = (struct chash_cfg *)ta_state;
 1361 
 1362         tinfo->flags = IPFW_TATFLAGS_AFDATA | IPFW_TATFLAGS_AFITEM;
 1363         tinfo->taclass4 = IPFW_TACLASS_HASH;
 1364         tinfo->size4 = cfg->size4;
 1365         tinfo->count4 = cfg->items4;
 1366         tinfo->itemsize4 = sizeof(struct chashentry);
 1367         tinfo->taclass6 = IPFW_TACLASS_HASH;
 1368         tinfo->size6 = cfg->size6;
 1369         tinfo->count6 = cfg->items6;
 1370         tinfo->itemsize6 = sizeof(struct chashentry);
 1371 }
 1372 
 1373 static int
 1374 ta_dump_chash_tentry(void *ta_state, struct table_info *ti, void *e,
 1375     ipfw_obj_tentry *tent)
 1376 {
 1377         struct chash_cfg *cfg;
 1378         struct chashentry *ent;
 1379 
 1380         cfg = (struct chash_cfg *)ta_state;
 1381         ent = (struct chashentry *)e;
 1382 
 1383         if (ent->type == AF_INET) {
 1384                 tent->k.addr.s_addr = htonl(ent->a.a4 << (32 - cfg->mask4));
 1385                 tent->masklen = cfg->mask4;
 1386                 tent->subtype = AF_INET;
 1387                 tent->v.kidx = ent->value;
 1388 #ifdef INET6
 1389         } else {
 1390                 memcpy(&tent->k.addr6, &ent->a.a6, sizeof(struct in6_addr));
 1391                 tent->masklen = cfg->mask6;
 1392                 tent->subtype = AF_INET6;
 1393                 tent->v.kidx = ent->value;
 1394 #endif
 1395         }
 1396 
 1397         return (0);
 1398 }
 1399 
 1400 static uint32_t
 1401 hash_ent(struct chashentry *ent, int af, int mlen, uint32_t size)
 1402 {
 1403         uint32_t hash;
 1404 
 1405         hash = 0;
 1406 
 1407         if (af == AF_INET) {
 1408 #ifdef INET
 1409                 hash = hash_ip(ent->a.a4, size);
 1410 #endif
 1411         } else {
 1412 #ifdef INET6
 1413                 if (mlen == 64)
 1414                         hash = hash_ip64(&ent->a.a6, size);
 1415                 else
 1416                         hash = hash_ip6(&ent->a.a6, size);
 1417 #endif
 1418         }
 1419 
 1420         return (hash);
 1421 }
 1422 
 1423 static int
 1424 tei_to_chash_ent(struct tentry_info *tei, struct chashentry *ent)
 1425 {
 1426         int mlen;
 1427 #ifdef INET6
 1428         struct in6_addr mask6;
 1429 #endif
 1430 
 1431         mlen = tei->masklen;
 1432 
 1433         if (tei->subtype == AF_INET) {
 1434 #ifdef INET
 1435                 if (mlen > 32)
 1436                         return (EINVAL);
 1437                 ent->type = AF_INET;
 1438 
 1439                 /* Calculate masked address */
 1440                 ent->a.a4 = ntohl(*((in_addr_t *)tei->paddr)) >> (32 - mlen);
 1441 #endif
 1442 #ifdef INET6
 1443         } else if (tei->subtype == AF_INET6) {
 1444                 /* IPv6 case */
 1445                 if (mlen > 128)
 1446                         return (EINVAL);
 1447                 ent->type = AF_INET6;
 1448 
 1449                 ipv6_writemask(&mask6, mlen);
 1450                 memcpy(&ent->a.a6, tei->paddr, sizeof(struct in6_addr));
 1451                 APPLY_MASK(&ent->a.a6, &mask6);
 1452 #endif
 1453         } else {
 1454                 /* Unknown CIDR type */
 1455                 return (EINVAL);
 1456         }
 1457 
 1458         return (0);
 1459 }
 1460 
 1461 static int
 1462 ta_find_chash_tentry(void *ta_state, struct table_info *ti,
 1463     ipfw_obj_tentry *tent)
 1464 {
 1465         struct chash_cfg *cfg;
 1466         struct chashbhead *head;
 1467         struct chashentry ent, *tmp;
 1468         struct tentry_info tei;
 1469         int error;
 1470         uint32_t hash;
 1471 
 1472         cfg = (struct chash_cfg *)ta_state;
 1473 
 1474         memset(&ent, 0, sizeof(ent));
 1475         memset(&tei, 0, sizeof(tei));
 1476 
 1477         if (tent->subtype == AF_INET) {
 1478                 tei.paddr = &tent->k.addr;
 1479                 tei.masklen = cfg->mask4;
 1480                 tei.subtype = AF_INET;
 1481 
 1482                 if ((error = tei_to_chash_ent(&tei, &ent)) != 0)
 1483                         return (error);
 1484 
 1485                 head = cfg->head4;
 1486                 hash = hash_ent(&ent, AF_INET, cfg->mask4, cfg->size4);
 1487                 /* Check for existence */
 1488                 SLIST_FOREACH(tmp, &head[hash], next) {
 1489                         if (tmp->a.a4 != ent.a.a4)
 1490                                 continue;
 1491 
 1492                         ta_dump_chash_tentry(ta_state, ti, tmp, tent);
 1493                         return (0);
 1494                 }
 1495         } else {
 1496                 tei.paddr = &tent->k.addr6;
 1497                 tei.masklen = cfg->mask6;
 1498                 tei.subtype = AF_INET6;
 1499 
 1500                 if ((error = tei_to_chash_ent(&tei, &ent)) != 0)
 1501                         return (error);
 1502 
 1503                 head = cfg->head6;
 1504                 hash = hash_ent(&ent, AF_INET6, cfg->mask6, cfg->size6);
 1505                 /* Check for existence */
 1506                 SLIST_FOREACH(tmp, &head[hash], next) {
 1507                         if (memcmp(&tmp->a.a6, &ent.a.a6, 16) != 0)
 1508                                 continue;
 1509                         ta_dump_chash_tentry(ta_state, ti, tmp, tent);
 1510                         return (0);
 1511                 }
 1512         }
 1513 
 1514         return (ENOENT);
 1515 }
 1516 
 1517 static void
 1518 ta_foreach_chash(void *ta_state, struct table_info *ti, ta_foreach_f *f,
 1519     void *arg)
 1520 {
 1521         struct chash_cfg *cfg;
 1522         struct chashentry *ent, *ent_next;
 1523         int i;
 1524 
 1525         cfg = (struct chash_cfg *)ta_state;
 1526 
 1527         for (i = 0; i < cfg->size4; i++)
 1528                 SLIST_FOREACH_SAFE(ent, &cfg->head4[i], next, ent_next)
 1529                         f(ent, arg);
 1530 
 1531         for (i = 0; i < cfg->size6; i++)
 1532                 SLIST_FOREACH_SAFE(ent, &cfg->head6[i], next, ent_next)
 1533                         f(ent, arg);
 1534 }
 1535 
 1536 static int
 1537 ta_prepare_add_chash(struct ip_fw_chain *ch, struct tentry_info *tei,
 1538     void *ta_buf)
 1539 {
 1540         struct ta_buf_chash *tb;
 1541         struct chashentry *ent;
 1542         int error;
 1543 
 1544         tb = (struct ta_buf_chash *)ta_buf;
 1545 
 1546         ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO);
 1547 
 1548         error = tei_to_chash_ent(tei, ent);
 1549         if (error != 0) {
 1550                 free(ent, M_IPFW_TBL);
 1551                 return (error);
 1552         }
 1553         tb->ent_ptr = ent;
 1554 
 1555         return (0);
 1556 }
 1557 
 1558 static int
 1559 ta_add_chash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 1560     void *ta_buf, uint32_t *pnum)
 1561 {
 1562         struct chash_cfg *cfg;
 1563         struct chashbhead *head;
 1564         struct chashentry *ent, *tmp;
 1565         struct ta_buf_chash *tb;
 1566         int exists;
 1567         uint32_t hash, value;
 1568 
 1569         cfg = (struct chash_cfg *)ta_state;
 1570         tb = (struct ta_buf_chash *)ta_buf;
 1571         ent = (struct chashentry *)tb->ent_ptr;
 1572         hash = 0;
 1573         exists = 0;
 1574 
 1575         /* Read current value from @tei */
 1576         ent->value = tei->value;
 1577 
 1578         /* Read cuurrent value */
 1579         if (tei->subtype == AF_INET) {
 1580                 if (tei->masklen != cfg->mask4)
 1581                         return (EINVAL);
 1582                 head = cfg->head4;
 1583                 hash = hash_ent(ent, AF_INET, cfg->mask4, cfg->size4);
 1584 
 1585                 /* Check for existence */
 1586                 SLIST_FOREACH(tmp, &head[hash], next) {
 1587                         if (tmp->a.a4 == ent->a.a4) {
 1588                                 exists = 1;
 1589                                 break;
 1590                         }
 1591                 }
 1592         } else {
 1593                 if (tei->masklen != cfg->mask6)
 1594                         return (EINVAL);
 1595                 head = cfg->head6;
 1596                 hash = hash_ent(ent, AF_INET6, cfg->mask6, cfg->size6);
 1597                 /* Check for existence */
 1598                 SLIST_FOREACH(tmp, &head[hash], next) {
 1599                         if (memcmp(&tmp->a.a6, &ent->a.a6, 16) == 0) {
 1600                                 exists = 1;
 1601                                 break;
 1602                         }
 1603                 }
 1604         }
 1605 
 1606         if (exists == 1) {
 1607                 if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
 1608                         return (EEXIST);
 1609                 /* Record already exists. Update value if we're asked to */
 1610                 value = tmp->value;
 1611                 tmp->value = tei->value;
 1612                 tei->value = value;
 1613                 /* Indicate that update has happened instead of addition */
 1614                 tei->flags |= TEI_FLAGS_UPDATED;
 1615                 *pnum = 0;
 1616         } else {
 1617                 if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
 1618                         return (EFBIG);
 1619                 SLIST_INSERT_HEAD(&head[hash], ent, next);
 1620                 tb->ent_ptr = NULL;
 1621                 *pnum = 1;
 1622 
 1623                 /* Update counters */
 1624                 if (tei->subtype == AF_INET)
 1625                         cfg->items4++;
 1626                 else
 1627                         cfg->items6++;
 1628         }
 1629 
 1630         return (0);
 1631 }
 1632 
 1633 static int
 1634 ta_prepare_del_chash(struct ip_fw_chain *ch, struct tentry_info *tei,
 1635     void *ta_buf)
 1636 {
 1637         struct ta_buf_chash *tb;
 1638 
 1639         tb = (struct ta_buf_chash *)ta_buf;
 1640 
 1641         return (tei_to_chash_ent(tei, &tb->ent));
 1642 }
 1643 
 1644 static int
 1645 ta_del_chash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 1646     void *ta_buf, uint32_t *pnum)
 1647 {
 1648         struct chash_cfg *cfg;
 1649         struct chashbhead *head;
 1650         struct chashentry *tmp, *tmp_next, *ent;
 1651         struct ta_buf_chash *tb;
 1652         uint32_t hash;
 1653 
 1654         cfg = (struct chash_cfg *)ta_state;
 1655         tb = (struct ta_buf_chash *)ta_buf;
 1656         ent = &tb->ent;
 1657 
 1658         if (tei->subtype == AF_INET) {
 1659                 if (tei->masklen != cfg->mask4)
 1660                         return (EINVAL);
 1661                 head = cfg->head4;
 1662                 hash = hash_ent(ent, AF_INET, cfg->mask4, cfg->size4);
 1663 
 1664                 SLIST_FOREACH_SAFE(tmp, &head[hash], next, tmp_next) {
 1665                         if (tmp->a.a4 != ent->a.a4)
 1666                                 continue;
 1667 
 1668                         SLIST_REMOVE(&head[hash], tmp, chashentry, next);
 1669                         cfg->items4--;
 1670                         tb->ent_ptr = tmp;
 1671                         tei->value = tmp->value;
 1672                         *pnum = 1;
 1673                         return (0);
 1674                 }
 1675         } else {
 1676                 if (tei->masklen != cfg->mask6)
 1677                         return (EINVAL);
 1678                 head = cfg->head6;
 1679                 hash = hash_ent(ent, AF_INET6, cfg->mask6, cfg->size6);
 1680                 SLIST_FOREACH_SAFE(tmp, &head[hash], next, tmp_next) {
 1681                         if (memcmp(&tmp->a.a6, &ent->a.a6, 16) != 0)
 1682                                 continue;
 1683 
 1684                         SLIST_REMOVE(&head[hash], tmp, chashentry, next);
 1685                         cfg->items6--;
 1686                         tb->ent_ptr = tmp;
 1687                         tei->value = tmp->value;
 1688                         *pnum = 1;
 1689                         return (0);
 1690                 }
 1691         }
 1692 
 1693         return (ENOENT);
 1694 }
 1695 
 1696 static void
 1697 ta_flush_chash_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
 1698     void *ta_buf)
 1699 {
 1700         struct ta_buf_chash *tb;
 1701 
 1702         tb = (struct ta_buf_chash *)ta_buf;
 1703 
 1704         if (tb->ent_ptr != NULL)
 1705                 free(tb->ent_ptr, M_IPFW_TBL);
 1706 }
 1707 
 1708 /*
 1709  * Hash growing callbacks.
 1710  */
 1711 
 1712 static int
 1713 ta_need_modify_chash(void *ta_state, struct table_info *ti, uint32_t count,
 1714     uint64_t *pflags)
 1715 {
 1716         struct chash_cfg *cfg;
 1717         uint64_t data;
 1718 
 1719         /*
 1720          * Since we don't know exact number of IPv4/IPv6 records in @count,
 1721          * ignore non-zero @count value at all. Check current hash sizes
 1722          * and return appropriate data.
 1723          */
 1724 
 1725         cfg = (struct chash_cfg *)ta_state;
 1726 
 1727         data = 0;
 1728         if (cfg->items4 > cfg->size4 && cfg->size4 < 65536)
 1729                 data |= (cfg->size4 * 2) << 16;
 1730         if (cfg->items6 > cfg->size6 && cfg->size6 < 65536)
 1731                 data |= cfg->size6 * 2;
 1732 
 1733         if (data != 0) {
 1734                 *pflags = data;
 1735                 return (1);
 1736         }
 1737 
 1738         return (0);
 1739 }
 1740 
 1741 /*
 1742  * Allocate new, larger chash.
 1743  */
 1744 static int
 1745 ta_prepare_mod_chash(void *ta_buf, uint64_t *pflags)
 1746 {
 1747         struct mod_item *mi;
 1748         struct chashbhead *head;
 1749         int i;
 1750 
 1751         mi = (struct mod_item *)ta_buf;
 1752 
 1753         memset(mi, 0, sizeof(struct mod_item));
 1754         mi->size = (*pflags >> 16) & 0xFFFF;
 1755         mi->size6 = *pflags & 0xFFFF;
 1756         if (mi->size > 0) {
 1757                 head = malloc(sizeof(struct chashbhead) * mi->size,
 1758                     M_IPFW, M_WAITOK | M_ZERO);
 1759                 for (i = 0; i < mi->size; i++)
 1760                         SLIST_INIT(&head[i]);
 1761                 mi->main_ptr = head;
 1762         }
 1763 
 1764         if (mi->size6 > 0) {
 1765                 head = malloc(sizeof(struct chashbhead) * mi->size6,
 1766                     M_IPFW, M_WAITOK | M_ZERO);
 1767                 for (i = 0; i < mi->size6; i++)
 1768                         SLIST_INIT(&head[i]);
 1769                 mi->main_ptr6 = head;
 1770         }
 1771 
 1772         return (0);
 1773 }
 1774 
 1775 /*
 1776  * Copy data from old runtime array to new one.
 1777  */
 1778 static int
 1779 ta_fill_mod_chash(void *ta_state, struct table_info *ti, void *ta_buf,
 1780     uint64_t *pflags)
 1781 {
 1782 
 1783         /* In is not possible to do rehash if we're not holidng WLOCK. */
 1784         return (0);
 1785 }
 1786 
 1787 /*
 1788  * Switch old & new arrays.
 1789  */
 1790 static void
 1791 ta_modify_chash(void *ta_state, struct table_info *ti, void *ta_buf,
 1792     uint64_t pflags)
 1793 {
 1794         struct mod_item *mi;
 1795         struct chash_cfg *cfg;
 1796         struct chashbhead *old_head, *new_head;
 1797         struct chashentry *ent, *ent_next;
 1798         int af, i, mlen;
 1799         uint32_t nhash;
 1800         size_t old_size, new_size;
 1801 
 1802         mi = (struct mod_item *)ta_buf;
 1803         cfg = (struct chash_cfg *)ta_state;
 1804 
 1805         /* Check which hash we need to grow and do we still need that */
 1806         if (mi->size > 0 && cfg->size4 < mi->size) {
 1807                 new_head = (struct chashbhead *)mi->main_ptr;
 1808                 new_size = mi->size;
 1809                 old_size = cfg->size4;
 1810                 old_head = ti->state;
 1811                 mlen = cfg->mask4;
 1812                 af = AF_INET;
 1813 
 1814                 for (i = 0; i < old_size; i++) {
 1815                         SLIST_FOREACH_SAFE(ent, &old_head[i], next, ent_next) {
 1816                                 nhash = hash_ent(ent, af, mlen, new_size);
 1817                                 SLIST_INSERT_HEAD(&new_head[nhash], ent, next);
 1818                         }
 1819                 }
 1820 
 1821                 ti->state = new_head;
 1822                 cfg->head4 = new_head;
 1823                 cfg->size4 = mi->size;
 1824                 mi->main_ptr = old_head;
 1825         }
 1826 
 1827         if (mi->size6 > 0 && cfg->size6 < mi->size6) {
 1828                 new_head = (struct chashbhead *)mi->main_ptr6;
 1829                 new_size = mi->size6;
 1830                 old_size = cfg->size6;
 1831                 old_head = ti->xstate;
 1832                 mlen = cfg->mask6;
 1833                 af = AF_INET6;
 1834 
 1835                 for (i = 0; i < old_size; i++) {
 1836                         SLIST_FOREACH_SAFE(ent, &old_head[i], next, ent_next) {
 1837                                 nhash = hash_ent(ent, af, mlen, new_size);
 1838                                 SLIST_INSERT_HEAD(&new_head[nhash], ent, next);
 1839                         }
 1840                 }
 1841 
 1842                 ti->xstate = new_head;
 1843                 cfg->head6 = new_head;
 1844                 cfg->size6 = mi->size6;
 1845                 mi->main_ptr6 = old_head;
 1846         }
 1847 
 1848         /* Update lower 32 bits with new values */
 1849         ti->data &= 0xFFFFFFFF00000000;
 1850         ti->data |= ta_log2(cfg->size4) << 8 | ta_log2(cfg->size6);
 1851 }
 1852 
 1853 /*
 1854  * Free unneded array.
 1855  */
 1856 static void
 1857 ta_flush_mod_chash(void *ta_buf)
 1858 {
 1859         struct mod_item *mi;
 1860 
 1861         mi = (struct mod_item *)ta_buf;
 1862         if (mi->main_ptr != NULL)
 1863                 free(mi->main_ptr, M_IPFW);
 1864         if (mi->main_ptr6 != NULL)
 1865                 free(mi->main_ptr6, M_IPFW);
 1866 }
 1867 
 1868 struct table_algo addr_hash = {
 1869         .name           = "addr:hash",
 1870         .type           = IPFW_TABLE_ADDR,
 1871         .ta_buf_size    = sizeof(struct ta_buf_chash),
 1872         .init           = ta_init_chash,
 1873         .destroy        = ta_destroy_chash,
 1874         .prepare_add    = ta_prepare_add_chash,
 1875         .prepare_del    = ta_prepare_del_chash,
 1876         .add            = ta_add_chash,
 1877         .del            = ta_del_chash,
 1878         .flush_entry    = ta_flush_chash_entry,
 1879         .foreach        = ta_foreach_chash,
 1880         .dump_tentry    = ta_dump_chash_tentry,
 1881         .find_tentry    = ta_find_chash_tentry,
 1882         .print_config   = ta_print_chash_config,
 1883         .dump_tinfo     = ta_dump_chash_tinfo,
 1884         .need_modify    = ta_need_modify_chash,
 1885         .prepare_mod    = ta_prepare_mod_chash,
 1886         .fill_mod       = ta_fill_mod_chash,
 1887         .modify         = ta_modify_chash,
 1888         .flush_mod      = ta_flush_mod_chash,
 1889 };
 1890 
 1891 /*
 1892  * Iface table cmds.
 1893  *
 1894  * Implementation:
 1895  *
 1896  * Runtime part:
 1897  * - sorted array of "struct ifidx" pointed by ti->state.
 1898  *   Array is allocated with rounding up to IFIDX_CHUNK. Only existing
 1899  *   interfaces are stored in array, however its allocated size is
 1900  *   sufficient to hold all table records if needed.
 1901  * - current array size is stored in ti->data
 1902  *
 1903  * Table data:
 1904  * - "struct iftable_cfg" is allocated to store table state (ta_state).
 1905  * - All table records are stored inside namedobj instance.
 1906  *
 1907  */
 1908 
 1909 struct ifidx {
 1910         uint16_t        kidx;
 1911         uint16_t        spare;
 1912         uint32_t        value;
 1913 };
 1914 #define DEFAULT_IFIDX_SIZE      64
 1915 
 1916 struct iftable_cfg;
 1917 
 1918 struct ifentry {
 1919         struct named_object     no;
 1920         struct ipfw_ifc         ic;
 1921         struct iftable_cfg      *icfg;
 1922         uint32_t                value;
 1923         int                     linked;
 1924 };
 1925 
 1926 struct iftable_cfg {
 1927         struct namedobj_instance        *ii;
 1928         struct ip_fw_chain      *ch;
 1929         struct table_info       *ti;
 1930         void    *main_ptr;
 1931         size_t  size;   /* Number of items allocated in array */
 1932         size_t  count;  /* Number of all items */
 1933         size_t  used;   /* Number of items _active_ now */
 1934 };
 1935 
 1936 struct ta_buf_ifidx
 1937 {
 1938         struct ifentry *ife;
 1939         uint32_t value;
 1940 };
 1941 
 1942 int compare_ifidx(const void *k, const void *v);
 1943 static struct ifidx * ifidx_find(struct table_info *ti, void *key);
 1944 static int ta_lookup_ifidx(struct table_info *ti, void *key, uint32_t keylen,
 1945     uint32_t *val);
 1946 static int ta_init_ifidx(struct ip_fw_chain *ch, void **ta_state,
 1947     struct table_info *ti, char *data, uint8_t tflags);
 1948 static void ta_change_ti_ifidx(void *ta_state, struct table_info *ti);
 1949 static int destroy_ifidx_locked(struct namedobj_instance *ii,
 1950     struct named_object *no, void *arg);
 1951 static void ta_destroy_ifidx(void *ta_state, struct table_info *ti);
 1952 static void ta_dump_ifidx_tinfo(void *ta_state, struct table_info *ti,
 1953     ipfw_ta_tinfo *tinfo);
 1954 static int ta_prepare_add_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei,
 1955     void *ta_buf);
 1956 static int ta_add_ifidx(void *ta_state, struct table_info *ti,
 1957     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
 1958 static int ta_prepare_del_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei,
 1959     void *ta_buf);
 1960 static int ta_del_ifidx(void *ta_state, struct table_info *ti,
 1961     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
 1962 static void ta_flush_ifidx_entry(struct ip_fw_chain *ch,
 1963     struct tentry_info *tei, void *ta_buf);
 1964 static void if_notifier(struct ip_fw_chain *ch, void *cbdata, uint16_t ifindex);
 1965 static int ta_need_modify_ifidx(void *ta_state, struct table_info *ti,
 1966     uint32_t count, uint64_t *pflags);
 1967 static int ta_prepare_mod_ifidx(void *ta_buf, uint64_t *pflags);
 1968 static int ta_fill_mod_ifidx(void *ta_state, struct table_info *ti,
 1969     void *ta_buf, uint64_t *pflags);
 1970 static void ta_modify_ifidx(void *ta_state, struct table_info *ti, void *ta_buf,
 1971     uint64_t pflags);
 1972 static void ta_flush_mod_ifidx(void *ta_buf);
 1973 static int ta_dump_ifidx_tentry(void *ta_state, struct table_info *ti, void *e,
 1974     ipfw_obj_tentry *tent);
 1975 static int ta_find_ifidx_tentry(void *ta_state, struct table_info *ti,
 1976     ipfw_obj_tentry *tent);
 1977 static int foreach_ifidx(struct namedobj_instance *ii, struct named_object *no,
 1978     void *arg);
 1979 static void ta_foreach_ifidx(void *ta_state, struct table_info *ti,
 1980     ta_foreach_f *f, void *arg);
 1981 
 1982 int
 1983 compare_ifidx(const void *k, const void *v)
 1984 {
 1985         const struct ifidx *ifidx;
 1986         uint16_t key;
 1987 
 1988         key = *((const uint16_t *)k);
 1989         ifidx = (const struct ifidx *)v;
 1990 
 1991         if (key < ifidx->kidx)
 1992                 return (-1);
 1993         else if (key > ifidx->kidx)
 1994                 return (1);
 1995 
 1996         return (0);
 1997 }
 1998 
 1999 /*
 2000  * Adds item @item with key @key into ascending-sorted array @base.
 2001  * Assumes @base has enough additional storage.
 2002  *
 2003  * Returns 1 on success, 0 on duplicate key.
 2004  */
 2005 static int
 2006 badd(const void *key, void *item, void *base, size_t nmemb,
 2007     size_t size, int (*compar) (const void *, const void *))
 2008 {
 2009         int min, max, mid, shift, res;
 2010         caddr_t paddr;
 2011 
 2012         if (nmemb == 0) {
 2013                 memcpy(base, item, size);
 2014                 return (1);
 2015         }
 2016 
 2017         /* Binary search */
 2018         min = 0;
 2019         max = nmemb - 1;
 2020         mid = 0;
 2021         while (min <= max) {
 2022                 mid = (min + max) / 2;
 2023                 res = compar(key, (const void *)((caddr_t)base + mid * size));
 2024                 if (res == 0)
 2025                         return (0);
 2026 
 2027                 if (res > 0)
 2028                         min = mid + 1;
 2029                 else
 2030                         max = mid - 1;
 2031         }
 2032 
 2033         /* Item not found. */
 2034         res = compar(key, (const void *)((caddr_t)base + mid * size));
 2035         if (res > 0)
 2036                 shift = mid + 1;
 2037         else
 2038                 shift = mid;
 2039 
 2040         paddr = (caddr_t)base + shift * size;
 2041         if (nmemb > shift)
 2042                 memmove(paddr + size, paddr, (nmemb - shift) * size);
 2043 
 2044         memcpy(paddr, item, size);
 2045 
 2046         return (1);
 2047 }
 2048 
 2049 /*
 2050  * Deletes item with key @key from ascending-sorted array @base.
 2051  *
 2052  * Returns 1 on success, 0 for non-existent key.
 2053  */
 2054 static int
 2055 bdel(const void *key, void *base, size_t nmemb, size_t size,
 2056     int (*compar) (const void *, const void *))
 2057 {
 2058         caddr_t item;
 2059         size_t sz;
 2060 
 2061         item = (caddr_t)bsearch(key, base, nmemb, size, compar);
 2062 
 2063         if (item == NULL)
 2064                 return (0);
 2065 
 2066         sz = (caddr_t)base + nmemb * size - item;
 2067 
 2068         if (sz > 0)
 2069                 memmove(item, item + size, sz);
 2070 
 2071         return (1);
 2072 }
 2073 
 2074 static struct ifidx *
 2075 ifidx_find(struct table_info *ti, void *key)
 2076 {
 2077         struct ifidx *ifi;
 2078 
 2079         ifi = bsearch(key, ti->state, ti->data, sizeof(struct ifidx),
 2080             compare_ifidx);
 2081 
 2082         return (ifi);
 2083 }
 2084 
 2085 static int
 2086 ta_lookup_ifidx(struct table_info *ti, void *key, uint32_t keylen,
 2087     uint32_t *val)
 2088 {
 2089         struct ifidx *ifi;
 2090 
 2091         ifi = ifidx_find(ti, key);
 2092 
 2093         if (ifi != NULL) {
 2094                 *val = ifi->value;
 2095                 return (1);
 2096         }
 2097 
 2098         return (0);
 2099 }
 2100 
 2101 static int
 2102 ta_init_ifidx(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
 2103     char *data, uint8_t tflags)
 2104 {
 2105         struct iftable_cfg *icfg;
 2106 
 2107         icfg = malloc(sizeof(struct iftable_cfg), M_IPFW, M_WAITOK | M_ZERO);
 2108 
 2109         icfg->ii = ipfw_objhash_create(DEFAULT_IFIDX_SIZE);
 2110         icfg->size = DEFAULT_IFIDX_SIZE;
 2111         icfg->main_ptr = malloc(sizeof(struct ifidx) * icfg->size, M_IPFW,
 2112             M_WAITOK | M_ZERO);
 2113         icfg->ch = ch;
 2114 
 2115         *ta_state = icfg;
 2116         ti->state = icfg->main_ptr;
 2117         ti->lookup = ta_lookup_ifidx;
 2118 
 2119         return (0);
 2120 }
 2121 
 2122 /*
 2123  * Handle tableinfo @ti pointer change (on table array resize).
 2124  */
 2125 static void
 2126 ta_change_ti_ifidx(void *ta_state, struct table_info *ti)
 2127 {
 2128         struct iftable_cfg *icfg;
 2129 
 2130         icfg = (struct iftable_cfg *)ta_state;
 2131         icfg->ti = ti;
 2132 }
 2133 
 2134 static int
 2135 destroy_ifidx_locked(struct namedobj_instance *ii, struct named_object *no,
 2136     void *arg)
 2137 {
 2138         struct ifentry *ife;
 2139         struct ip_fw_chain *ch;
 2140 
 2141         ch = (struct ip_fw_chain *)arg;
 2142         ife = (struct ifentry *)no;
 2143 
 2144         ipfw_iface_del_notify(ch, &ife->ic);
 2145         ipfw_iface_unref(ch, &ife->ic);
 2146         free(ife, M_IPFW_TBL);
 2147         return (0);
 2148 }
 2149 
 2150 /*
 2151  * Destroys table @ti
 2152  */
 2153 static void
 2154 ta_destroy_ifidx(void *ta_state, struct table_info *ti)
 2155 {
 2156         struct iftable_cfg *icfg;
 2157         struct ip_fw_chain *ch;
 2158 
 2159         icfg = (struct iftable_cfg *)ta_state;
 2160         ch = icfg->ch;
 2161 
 2162         if (icfg->main_ptr != NULL)
 2163                 free(icfg->main_ptr, M_IPFW);
 2164 
 2165         IPFW_UH_WLOCK(ch);
 2166         ipfw_objhash_foreach(icfg->ii, destroy_ifidx_locked, ch);
 2167         IPFW_UH_WUNLOCK(ch);
 2168 
 2169         ipfw_objhash_destroy(icfg->ii);
 2170 
 2171         free(icfg, M_IPFW);
 2172 }
 2173 
 2174 /*
 2175  * Provide algo-specific table info
 2176  */
 2177 static void
 2178 ta_dump_ifidx_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
 2179 {
 2180         struct iftable_cfg *cfg;
 2181 
 2182         cfg = (struct iftable_cfg *)ta_state;
 2183 
 2184         tinfo->taclass4 = IPFW_TACLASS_ARRAY;
 2185         tinfo->size4 = cfg->size;
 2186         tinfo->count4 = cfg->used;
 2187         tinfo->itemsize4 = sizeof(struct ifidx);
 2188 }
 2189 
 2190 /*
 2191  * Prepare state to add to the table:
 2192  * allocate ifentry and reference needed interface.
 2193  */
 2194 static int
 2195 ta_prepare_add_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei,
 2196     void *ta_buf)
 2197 {
 2198         struct ta_buf_ifidx *tb;
 2199         char *ifname;
 2200         struct ifentry *ife;
 2201 
 2202         tb = (struct ta_buf_ifidx *)ta_buf;
 2203 
 2204         /* Check if string is terminated */
 2205         ifname = (char *)tei->paddr;
 2206         if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE)
 2207                 return (EINVAL);
 2208 
 2209         ife = malloc(sizeof(struct ifentry), M_IPFW_TBL, M_WAITOK | M_ZERO);
 2210         ife->ic.cb = if_notifier;
 2211         ife->ic.cbdata = ife;
 2212 
 2213         if (ipfw_iface_ref(ch, ifname, &ife->ic) != 0) {
 2214                 free(ife, M_IPFW_TBL);
 2215                 return (EINVAL);
 2216         }
 2217 
 2218         /* Use ipfw_iface 'ifname' field as stable storage */
 2219         ife->no.name = ife->ic.iface->ifname;
 2220 
 2221         tb->ife = ife;
 2222 
 2223         return (0);
 2224 }
 2225 
 2226 static int
 2227 ta_add_ifidx(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 2228     void *ta_buf, uint32_t *pnum)
 2229 {
 2230         struct iftable_cfg *icfg;
 2231         struct ifentry *ife, *tmp;
 2232         struct ta_buf_ifidx *tb;
 2233         struct ipfw_iface *iif;
 2234         struct ifidx *ifi;
 2235         char *ifname;
 2236         uint32_t value;
 2237 
 2238         tb = (struct ta_buf_ifidx *)ta_buf;
 2239         ifname = (char *)tei->paddr;
 2240         icfg = (struct iftable_cfg *)ta_state;
 2241         ife = tb->ife;
 2242 
 2243         ife->icfg = icfg;
 2244         ife->value = tei->value;
 2245 
 2246         tmp = (struct ifentry *)ipfw_objhash_lookup_name(icfg->ii, 0, ifname);
 2247 
 2248         if (tmp != NULL) {
 2249                 if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
 2250                         return (EEXIST);
 2251 
 2252                 /* Exchange values in @tmp and @tei */
 2253                 value = tmp->value;
 2254                 tmp->value = tei->value;
 2255                 tei->value = value;
 2256 
 2257                 iif = tmp->ic.iface;
 2258                 if (iif->resolved != 0) {
 2259                         /* We have to update runtime value, too */
 2260                         ifi = ifidx_find(ti, &iif->ifindex);
 2261                         ifi->value = ife->value;
 2262                 }
 2263 
 2264                 /* Indicate that update has happened instead of addition */
 2265                 tei->flags |= TEI_FLAGS_UPDATED;
 2266                 *pnum = 0;
 2267                 return (0);
 2268         }
 2269 
 2270         if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
 2271                 return (EFBIG);
 2272 
 2273         /* Link to internal list */
 2274         ipfw_objhash_add(icfg->ii, &ife->no);
 2275 
 2276         /* Link notifier (possible running its callback) */
 2277         ipfw_iface_add_notify(icfg->ch, &ife->ic);
 2278         icfg->count++;
 2279 
 2280         tb->ife = NULL;
 2281         *pnum = 1;
 2282 
 2283         return (0);
 2284 }
 2285 
 2286 /*
 2287  * Prepare to delete key from table.
 2288  * Do basic interface name checks.
 2289  */
 2290 static int
 2291 ta_prepare_del_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei,
 2292     void *ta_buf)
 2293 {
 2294         char *ifname;
 2295 
 2296         /* Check if string is terminated */
 2297         ifname = (char *)tei->paddr;
 2298         if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE)
 2299                 return (EINVAL);
 2300 
 2301         return (0);
 2302 }
 2303 
 2304 /*
 2305  * Remove key from both configuration list and
 2306  * runtime array. Removed interface notification.
 2307  */
 2308 static int
 2309 ta_del_ifidx(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 2310     void *ta_buf, uint32_t *pnum)
 2311 {
 2312         struct iftable_cfg *icfg;
 2313         struct ifentry *ife;
 2314         struct ta_buf_ifidx *tb;
 2315         char *ifname;
 2316         uint16_t ifindex;
 2317         int res __diagused;
 2318 
 2319         tb = (struct ta_buf_ifidx *)ta_buf;
 2320         ifname = (char *)tei->paddr;
 2321         icfg = (struct iftable_cfg *)ta_state;
 2322 
 2323         ife = (struct ifentry *)ipfw_objhash_lookup_name(icfg->ii, 0, ifname);
 2324 
 2325         if (ife == NULL)
 2326                 return (ENOENT);
 2327 
 2328         if (ife->linked != 0) {
 2329                 /* We have to remove item from runtime */
 2330                 ifindex = ife->ic.iface->ifindex;
 2331 
 2332                 res = bdel(&ifindex, icfg->main_ptr, icfg->used,
 2333                     sizeof(struct ifidx), compare_ifidx);
 2334 
 2335                 KASSERT(res == 1, ("index %d does not exist", ifindex));
 2336                 icfg->used--;
 2337                 ti->data = icfg->used;
 2338                 ife->linked = 0;
 2339         }
 2340 
 2341         /* Unlink from local list */
 2342         ipfw_objhash_del(icfg->ii, &ife->no);
 2343         /* Unlink notifier and deref */
 2344         ipfw_iface_del_notify(icfg->ch, &ife->ic);
 2345         ipfw_iface_unref(icfg->ch, &ife->ic);
 2346 
 2347         icfg->count--;
 2348         tei->value = ife->value;
 2349 
 2350         tb->ife = ife;
 2351         *pnum = 1;
 2352 
 2353         return (0);
 2354 }
 2355 
 2356 /*
 2357  * Flush deleted entry.
 2358  * Drops interface reference and frees entry.
 2359  */
 2360 static void
 2361 ta_flush_ifidx_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
 2362     void *ta_buf)
 2363 {
 2364         struct ta_buf_ifidx *tb;
 2365 
 2366         tb = (struct ta_buf_ifidx *)ta_buf;
 2367 
 2368         if (tb->ife != NULL)
 2369                 free(tb->ife, M_IPFW_TBL);
 2370 }
 2371 
 2372 /*
 2373  * Handle interface announce/withdrawal for particular table.
 2374  * Every real runtime array modification happens here.
 2375  */
 2376 static void
 2377 if_notifier(struct ip_fw_chain *ch, void *cbdata, uint16_t ifindex)
 2378 {
 2379         struct ifentry *ife;
 2380         struct ifidx ifi;
 2381         struct iftable_cfg *icfg;
 2382         struct table_info *ti;
 2383         int res __diagused;
 2384 
 2385         ife = (struct ifentry *)cbdata;
 2386         icfg = ife->icfg;
 2387         ti = icfg->ti;
 2388 
 2389         KASSERT(ti != NULL, ("ti=NULL, check change_ti handler"));
 2390 
 2391         if (ife->linked == 0 && ifindex != 0) {
 2392                 /* Interface announce */
 2393                 ifi.kidx = ifindex;
 2394                 ifi.spare = 0;
 2395                 ifi.value = ife->value;
 2396                 res = badd(&ifindex, &ifi, icfg->main_ptr, icfg->used,
 2397                     sizeof(struct ifidx), compare_ifidx);
 2398                 KASSERT(res == 1, ("index %d already exists", ifindex));
 2399                 icfg->used++;
 2400                 ti->data = icfg->used;
 2401                 ife->linked = 1;
 2402         } else if (ife->linked != 0 && ifindex == 0) {
 2403                 /* Interface withdrawal */
 2404                 ifindex = ife->ic.iface->ifindex;
 2405 
 2406                 res = bdel(&ifindex, icfg->main_ptr, icfg->used,
 2407                     sizeof(struct ifidx), compare_ifidx);
 2408 
 2409                 KASSERT(res == 1, ("index %d does not exist", ifindex));
 2410                 icfg->used--;
 2411                 ti->data = icfg->used;
 2412                 ife->linked = 0;
 2413         }
 2414 }
 2415 
 2416 /*
 2417  * Table growing callbacks.
 2418  */
 2419 
 2420 static int
 2421 ta_need_modify_ifidx(void *ta_state, struct table_info *ti, uint32_t count,
 2422     uint64_t *pflags)
 2423 {
 2424         struct iftable_cfg *cfg;
 2425         uint32_t size;
 2426 
 2427         cfg = (struct iftable_cfg *)ta_state;
 2428 
 2429         size = cfg->size;
 2430         while (size < cfg->count + count)
 2431                 size *= 2;
 2432 
 2433         if (size != cfg->size) {
 2434                 *pflags = size;
 2435                 return (1);
 2436         }
 2437 
 2438         return (0);
 2439 }
 2440 
 2441 /*
 2442  * Allocate ned, larger runtime ifidx array.
 2443  */
 2444 static int
 2445 ta_prepare_mod_ifidx(void *ta_buf, uint64_t *pflags)
 2446 {
 2447         struct mod_item *mi;
 2448 
 2449         mi = (struct mod_item *)ta_buf;
 2450 
 2451         memset(mi, 0, sizeof(struct mod_item));
 2452         mi->size = *pflags;
 2453         mi->main_ptr = malloc(sizeof(struct ifidx) * mi->size, M_IPFW,
 2454             M_WAITOK | M_ZERO);
 2455 
 2456         return (0);
 2457 }
 2458 
 2459 /*
 2460  * Copy data from old runtime array to new one.
 2461  */
 2462 static int
 2463 ta_fill_mod_ifidx(void *ta_state, struct table_info *ti, void *ta_buf,
 2464     uint64_t *pflags)
 2465 {
 2466         struct mod_item *mi;
 2467         struct iftable_cfg *icfg;
 2468 
 2469         mi = (struct mod_item *)ta_buf;
 2470         icfg = (struct iftable_cfg *)ta_state;
 2471 
 2472         /* Check if we still need to grow array */
 2473         if (icfg->size >= mi->size) {
 2474                 *pflags = 0;
 2475                 return (0);
 2476         }
 2477 
 2478         memcpy(mi->main_ptr, icfg->main_ptr, icfg->used * sizeof(struct ifidx));
 2479 
 2480         return (0);
 2481 }
 2482 
 2483 /*
 2484  * Switch old & new arrays.
 2485  */
 2486 static void
 2487 ta_modify_ifidx(void *ta_state, struct table_info *ti, void *ta_buf,
 2488     uint64_t pflags)
 2489 {
 2490         struct mod_item *mi;
 2491         struct iftable_cfg *icfg;
 2492         void *old_ptr;
 2493 
 2494         mi = (struct mod_item *)ta_buf;
 2495         icfg = (struct iftable_cfg *)ta_state;
 2496 
 2497         old_ptr = icfg->main_ptr;
 2498         icfg->main_ptr = mi->main_ptr;
 2499         icfg->size = mi->size;
 2500         ti->state = icfg->main_ptr;
 2501 
 2502         mi->main_ptr = old_ptr;
 2503 }
 2504 
 2505 /*
 2506  * Free unneded array.
 2507  */
 2508 static void
 2509 ta_flush_mod_ifidx(void *ta_buf)
 2510 {
 2511         struct mod_item *mi;
 2512 
 2513         mi = (struct mod_item *)ta_buf;
 2514         if (mi->main_ptr != NULL)
 2515                 free(mi->main_ptr, M_IPFW);
 2516 }
 2517 
 2518 static int
 2519 ta_dump_ifidx_tentry(void *ta_state, struct table_info *ti, void *e,
 2520     ipfw_obj_tentry *tent)
 2521 {
 2522         struct ifentry *ife;
 2523 
 2524         ife = (struct ifentry *)e;
 2525 
 2526         tent->masklen = 8 * IF_NAMESIZE;
 2527         memcpy(&tent->k, ife->no.name, IF_NAMESIZE);
 2528         tent->v.kidx = ife->value;
 2529 
 2530         return (0);
 2531 }
 2532 
 2533 static int
 2534 ta_find_ifidx_tentry(void *ta_state, struct table_info *ti,
 2535     ipfw_obj_tentry *tent)
 2536 {
 2537         struct iftable_cfg *icfg;
 2538         struct ifentry *ife;
 2539         char *ifname;
 2540 
 2541         icfg = (struct iftable_cfg *)ta_state;
 2542         ifname = tent->k.iface;
 2543 
 2544         if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE)
 2545                 return (EINVAL);
 2546 
 2547         ife = (struct ifentry *)ipfw_objhash_lookup_name(icfg->ii, 0, ifname);
 2548 
 2549         if (ife != NULL) {
 2550                 ta_dump_ifidx_tentry(ta_state, ti, ife, tent);
 2551                 return (0);
 2552         }
 2553 
 2554         return (ENOENT);
 2555 }
 2556 
 2557 struct wa_ifidx {
 2558         ta_foreach_f    *f;
 2559         void            *arg;
 2560 };
 2561 
 2562 static int
 2563 foreach_ifidx(struct namedobj_instance *ii, struct named_object *no,
 2564     void *arg)
 2565 {
 2566         struct ifentry *ife;
 2567         struct wa_ifidx *wa;
 2568 
 2569         ife = (struct ifentry *)no;
 2570         wa = (struct wa_ifidx *)arg;
 2571 
 2572         wa->f(ife, wa->arg);
 2573         return (0);
 2574 }
 2575 
 2576 static void
 2577 ta_foreach_ifidx(void *ta_state, struct table_info *ti, ta_foreach_f *f,
 2578     void *arg)
 2579 {
 2580         struct iftable_cfg *icfg;
 2581         struct wa_ifidx wa;
 2582 
 2583         icfg = (struct iftable_cfg *)ta_state;
 2584 
 2585         wa.f = f;
 2586         wa.arg = arg;
 2587 
 2588         ipfw_objhash_foreach(icfg->ii, foreach_ifidx, &wa);
 2589 }
 2590 
 2591 struct table_algo iface_idx = {
 2592         .name           = "iface:array",
 2593         .type           = IPFW_TABLE_INTERFACE,
 2594         .flags          = TA_FLAG_DEFAULT,
 2595         .ta_buf_size    = sizeof(struct ta_buf_ifidx),
 2596         .init           = ta_init_ifidx,
 2597         .destroy        = ta_destroy_ifidx,
 2598         .prepare_add    = ta_prepare_add_ifidx,
 2599         .prepare_del    = ta_prepare_del_ifidx,
 2600         .add            = ta_add_ifidx,
 2601         .del            = ta_del_ifidx,
 2602         .flush_entry    = ta_flush_ifidx_entry,
 2603         .foreach        = ta_foreach_ifidx,
 2604         .dump_tentry    = ta_dump_ifidx_tentry,
 2605         .find_tentry    = ta_find_ifidx_tentry,
 2606         .dump_tinfo     = ta_dump_ifidx_tinfo,
 2607         .need_modify    = ta_need_modify_ifidx,
 2608         .prepare_mod    = ta_prepare_mod_ifidx,
 2609         .fill_mod       = ta_fill_mod_ifidx,
 2610         .modify         = ta_modify_ifidx,
 2611         .flush_mod      = ta_flush_mod_ifidx,
 2612         .change_ti      = ta_change_ti_ifidx,
 2613 };
 2614 
 2615 /*
 2616  * Number array cmds.
 2617  *
 2618  * Implementation:
 2619  *
 2620  * Runtime part:
 2621  * - sorted array of "struct numarray" pointed by ti->state.
 2622  *   Array is allocated with rounding up to NUMARRAY_CHUNK.
 2623  * - current array size is stored in ti->data
 2624  *
 2625  */
 2626 
 2627 struct numarray {
 2628         uint32_t        number;
 2629         uint32_t        value;
 2630 };
 2631 
 2632 struct numarray_cfg {
 2633         void    *main_ptr;
 2634         size_t  size;   /* Number of items allocated in array */
 2635         size_t  used;   /* Number of items _active_ now */
 2636 };
 2637 
 2638 struct ta_buf_numarray
 2639 {
 2640         struct numarray na;
 2641 };
 2642 
 2643 int compare_numarray(const void *k, const void *v);
 2644 static struct numarray *numarray_find(struct table_info *ti, void *key);
 2645 static int ta_lookup_numarray(struct table_info *ti, void *key,
 2646     uint32_t keylen, uint32_t *val);
 2647 static int ta_init_numarray(struct ip_fw_chain *ch, void **ta_state,
 2648     struct table_info *ti, char *data, uint8_t tflags);
 2649 static void ta_destroy_numarray(void *ta_state, struct table_info *ti);
 2650 static void ta_dump_numarray_tinfo(void *ta_state, struct table_info *ti,
 2651     ipfw_ta_tinfo *tinfo);
 2652 static int ta_prepare_add_numarray(struct ip_fw_chain *ch,
 2653     struct tentry_info *tei, void *ta_buf);
 2654 static int ta_add_numarray(void *ta_state, struct table_info *ti,
 2655     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
 2656 static int ta_del_numarray(void *ta_state, struct table_info *ti,
 2657     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
 2658 static void ta_flush_numarray_entry(struct ip_fw_chain *ch,
 2659     struct tentry_info *tei, void *ta_buf);
 2660 static int ta_need_modify_numarray(void *ta_state, struct table_info *ti,
 2661     uint32_t count, uint64_t *pflags);
 2662 static int ta_prepare_mod_numarray(void *ta_buf, uint64_t *pflags);
 2663 static int ta_fill_mod_numarray(void *ta_state, struct table_info *ti,
 2664     void *ta_buf, uint64_t *pflags);
 2665 static void ta_modify_numarray(void *ta_state, struct table_info *ti,
 2666     void *ta_buf, uint64_t pflags);
 2667 static void ta_flush_mod_numarray(void *ta_buf);
 2668 static int ta_dump_numarray_tentry(void *ta_state, struct table_info *ti,
 2669     void *e, ipfw_obj_tentry *tent);
 2670 static int ta_find_numarray_tentry(void *ta_state, struct table_info *ti,
 2671     ipfw_obj_tentry *tent);
 2672 static void ta_foreach_numarray(void *ta_state, struct table_info *ti,
 2673     ta_foreach_f *f, void *arg);
 2674 
 2675 int
 2676 compare_numarray(const void *k, const void *v)
 2677 {
 2678         const struct numarray *na;
 2679         uint32_t key;
 2680 
 2681         key = *((const uint32_t *)k);
 2682         na = (const struct numarray *)v;
 2683 
 2684         if (key < na->number)
 2685                 return (-1);
 2686         else if (key > na->number)
 2687                 return (1);
 2688 
 2689         return (0);
 2690 }
 2691 
 2692 static struct numarray *
 2693 numarray_find(struct table_info *ti, void *key)
 2694 {
 2695         struct numarray *ri;
 2696 
 2697         ri = bsearch(key, ti->state, ti->data, sizeof(struct numarray),
 2698             compare_ifidx);
 2699 
 2700         return (ri);
 2701 }
 2702 
 2703 static int
 2704 ta_lookup_numarray(struct table_info *ti, void *key, uint32_t keylen,
 2705     uint32_t *val)
 2706 {
 2707         struct numarray *ri;
 2708 
 2709         ri = numarray_find(ti, key);
 2710 
 2711         if (ri != NULL) {
 2712                 *val = ri->value;
 2713                 return (1);
 2714         }
 2715 
 2716         return (0);
 2717 }
 2718 
 2719 static int
 2720 ta_init_numarray(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
 2721     char *data, uint8_t tflags)
 2722 {
 2723         struct numarray_cfg *cfg;
 2724 
 2725         cfg = malloc(sizeof(*cfg), M_IPFW, M_WAITOK | M_ZERO);
 2726 
 2727         cfg->size = 16;
 2728         cfg->main_ptr = malloc(sizeof(struct numarray) * cfg->size, M_IPFW,
 2729             M_WAITOK | M_ZERO);
 2730 
 2731         *ta_state = cfg;
 2732         ti->state = cfg->main_ptr;
 2733         ti->lookup = ta_lookup_numarray;
 2734 
 2735         return (0);
 2736 }
 2737 
 2738 /*
 2739  * Destroys table @ti
 2740  */
 2741 static void
 2742 ta_destroy_numarray(void *ta_state, struct table_info *ti)
 2743 {
 2744         struct numarray_cfg *cfg;
 2745 
 2746         cfg = (struct numarray_cfg *)ta_state;
 2747 
 2748         if (cfg->main_ptr != NULL)
 2749                 free(cfg->main_ptr, M_IPFW);
 2750 
 2751         free(cfg, M_IPFW);
 2752 }
 2753 
 2754 /*
 2755  * Provide algo-specific table info
 2756  */
 2757 static void
 2758 ta_dump_numarray_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
 2759 {
 2760         struct numarray_cfg *cfg;
 2761 
 2762         cfg = (struct numarray_cfg *)ta_state;
 2763 
 2764         tinfo->taclass4 = IPFW_TACLASS_ARRAY;
 2765         tinfo->size4 = cfg->size;
 2766         tinfo->count4 = cfg->used;
 2767         tinfo->itemsize4 = sizeof(struct numarray);
 2768 }
 2769 
 2770 /*
 2771  * Prepare for addition/deletion to an array.
 2772  */
 2773 static int
 2774 ta_prepare_add_numarray(struct ip_fw_chain *ch, struct tentry_info *tei,
 2775     void *ta_buf)
 2776 {
 2777         struct ta_buf_numarray *tb;
 2778 
 2779         tb = (struct ta_buf_numarray *)ta_buf;
 2780 
 2781         tb->na.number = *((uint32_t *)tei->paddr);
 2782 
 2783         return (0);
 2784 }
 2785 
 2786 static int
 2787 ta_add_numarray(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 2788     void *ta_buf, uint32_t *pnum)
 2789 {
 2790         struct numarray_cfg *cfg;
 2791         struct ta_buf_numarray *tb;
 2792         struct numarray *ri;
 2793         int res __diagused;
 2794         uint32_t value;
 2795 
 2796         tb = (struct ta_buf_numarray *)ta_buf;
 2797         cfg = (struct numarray_cfg *)ta_state;
 2798 
 2799         /* Read current value from @tei */
 2800         tb->na.value = tei->value;
 2801 
 2802         ri = numarray_find(ti, &tb->na.number);
 2803 
 2804         if (ri != NULL) {
 2805                 if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
 2806                         return (EEXIST);
 2807 
 2808                 /* Exchange values between ri and @tei */
 2809                 value = ri->value;
 2810                 ri->value = tei->value;
 2811                 tei->value = value;
 2812                 /* Indicate that update has happened instead of addition */
 2813                 tei->flags |= TEI_FLAGS_UPDATED;
 2814                 *pnum = 0;
 2815                 return (0);
 2816         }
 2817 
 2818         if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
 2819                 return (EFBIG);
 2820 
 2821         res = badd(&tb->na.number, &tb->na, cfg->main_ptr, cfg->used,
 2822             sizeof(struct numarray), compare_numarray);
 2823 
 2824         KASSERT(res == 1, ("number %d already exists", tb->na.number));
 2825         cfg->used++;
 2826         ti->data = cfg->used;
 2827         *pnum = 1;
 2828 
 2829         return (0);
 2830 }
 2831 
 2832 /*
 2833  * Remove key from both configuration list and
 2834  * runtime array. Removed interface notification.
 2835  */
 2836 static int
 2837 ta_del_numarray(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 2838     void *ta_buf, uint32_t *pnum)
 2839 {
 2840         struct numarray_cfg *cfg;
 2841         struct ta_buf_numarray *tb;
 2842         struct numarray *ri;
 2843         int res __diagused;
 2844 
 2845         tb = (struct ta_buf_numarray *)ta_buf;
 2846         cfg = (struct numarray_cfg *)ta_state;
 2847 
 2848         ri = numarray_find(ti, &tb->na.number);
 2849         if (ri == NULL)
 2850                 return (ENOENT);
 2851 
 2852         tei->value = ri->value;
 2853 
 2854         res = bdel(&tb->na.number, cfg->main_ptr, cfg->used,
 2855             sizeof(struct numarray), compare_numarray);
 2856 
 2857         KASSERT(res == 1, ("number %u does not exist", tb->na.number));
 2858         cfg->used--;
 2859         ti->data = cfg->used;
 2860         *pnum = 1;
 2861 
 2862         return (0);
 2863 }
 2864 
 2865 static void
 2866 ta_flush_numarray_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
 2867     void *ta_buf)
 2868 {
 2869 
 2870         /* We don't have any state, do nothing */
 2871 }
 2872 
 2873 /*
 2874  * Table growing callbacks.
 2875  */
 2876 
 2877 static int
 2878 ta_need_modify_numarray(void *ta_state, struct table_info *ti, uint32_t count,
 2879     uint64_t *pflags)
 2880 {
 2881         struct numarray_cfg *cfg;
 2882         size_t size;
 2883 
 2884         cfg = (struct numarray_cfg *)ta_state;
 2885 
 2886         size = cfg->size;
 2887         while (size < cfg->used + count)
 2888                 size *= 2;
 2889 
 2890         if (size != cfg->size) {
 2891                 *pflags = size;
 2892                 return (1);
 2893         }
 2894 
 2895         return (0);
 2896 }
 2897 
 2898 /*
 2899  * Allocate new, larger runtime array.
 2900  */
 2901 static int
 2902 ta_prepare_mod_numarray(void *ta_buf, uint64_t *pflags)
 2903 {
 2904         struct mod_item *mi;
 2905 
 2906         mi = (struct mod_item *)ta_buf;
 2907 
 2908         memset(mi, 0, sizeof(struct mod_item));
 2909         mi->size = *pflags;
 2910         mi->main_ptr = malloc(sizeof(struct numarray) * mi->size, M_IPFW,
 2911             M_WAITOK | M_ZERO);
 2912 
 2913         return (0);
 2914 }
 2915 
 2916 /*
 2917  * Copy data from old runtime array to new one.
 2918  */
 2919 static int
 2920 ta_fill_mod_numarray(void *ta_state, struct table_info *ti, void *ta_buf,
 2921     uint64_t *pflags)
 2922 {
 2923         struct mod_item *mi;
 2924         struct numarray_cfg *cfg;
 2925 
 2926         mi = (struct mod_item *)ta_buf;
 2927         cfg = (struct numarray_cfg *)ta_state;
 2928 
 2929         /* Check if we still need to grow array */
 2930         if (cfg->size >= mi->size) {
 2931                 *pflags = 0;
 2932                 return (0);
 2933         }
 2934 
 2935         memcpy(mi->main_ptr, cfg->main_ptr, cfg->used * sizeof(struct numarray));
 2936 
 2937         return (0);
 2938 }
 2939 
 2940 /*
 2941  * Switch old & new arrays.
 2942  */
 2943 static void
 2944 ta_modify_numarray(void *ta_state, struct table_info *ti, void *ta_buf,
 2945     uint64_t pflags)
 2946 {
 2947         struct mod_item *mi;
 2948         struct numarray_cfg *cfg;
 2949         void *old_ptr;
 2950 
 2951         mi = (struct mod_item *)ta_buf;
 2952         cfg = (struct numarray_cfg *)ta_state;
 2953 
 2954         old_ptr = cfg->main_ptr;
 2955         cfg->main_ptr = mi->main_ptr;
 2956         cfg->size = mi->size;
 2957         ti->state = cfg->main_ptr;
 2958 
 2959         mi->main_ptr = old_ptr;
 2960 }
 2961 
 2962 /*
 2963  * Free unneded array.
 2964  */
 2965 static void
 2966 ta_flush_mod_numarray(void *ta_buf)
 2967 {
 2968         struct mod_item *mi;
 2969 
 2970         mi = (struct mod_item *)ta_buf;
 2971         if (mi->main_ptr != NULL)
 2972                 free(mi->main_ptr, M_IPFW);
 2973 }
 2974 
 2975 static int
 2976 ta_dump_numarray_tentry(void *ta_state, struct table_info *ti, void *e,
 2977     ipfw_obj_tentry *tent)
 2978 {
 2979         struct numarray *na;
 2980 
 2981         na = (struct numarray *)e;
 2982 
 2983         tent->k.key = na->number;
 2984         tent->v.kidx = na->value;
 2985 
 2986         return (0);
 2987 }
 2988 
 2989 static int
 2990 ta_find_numarray_tentry(void *ta_state, struct table_info *ti,
 2991     ipfw_obj_tentry *tent)
 2992 {
 2993         struct numarray *ri;
 2994 
 2995         ri = numarray_find(ti, &tent->k.key);
 2996 
 2997         if (ri != NULL) {
 2998                 ta_dump_numarray_tentry(ta_state, ti, ri, tent);
 2999                 return (0);
 3000         }
 3001 
 3002         return (ENOENT);
 3003 }
 3004 
 3005 static void
 3006 ta_foreach_numarray(void *ta_state, struct table_info *ti, ta_foreach_f *f,
 3007     void *arg)
 3008 {
 3009         struct numarray_cfg *cfg;
 3010         struct numarray *array;
 3011         int i;
 3012 
 3013         cfg = (struct numarray_cfg *)ta_state;
 3014         array = cfg->main_ptr;
 3015 
 3016         for (i = 0; i < cfg->used; i++)
 3017                 f(&array[i], arg);
 3018 }
 3019 
 3020 struct table_algo number_array = {
 3021         .name           = "number:array",
 3022         .type           = IPFW_TABLE_NUMBER,
 3023         .ta_buf_size    = sizeof(struct ta_buf_numarray),
 3024         .init           = ta_init_numarray,
 3025         .destroy        = ta_destroy_numarray,
 3026         .prepare_add    = ta_prepare_add_numarray,
 3027         .prepare_del    = ta_prepare_add_numarray,
 3028         .add            = ta_add_numarray,
 3029         .del            = ta_del_numarray,
 3030         .flush_entry    = ta_flush_numarray_entry,
 3031         .foreach        = ta_foreach_numarray,
 3032         .dump_tentry    = ta_dump_numarray_tentry,
 3033         .find_tentry    = ta_find_numarray_tentry,
 3034         .dump_tinfo     = ta_dump_numarray_tinfo,
 3035         .need_modify    = ta_need_modify_numarray,
 3036         .prepare_mod    = ta_prepare_mod_numarray,
 3037         .fill_mod       = ta_fill_mod_numarray,
 3038         .modify         = ta_modify_numarray,
 3039         .flush_mod      = ta_flush_mod_numarray,
 3040 };
 3041 
 3042 /*
 3043  * flow:hash cmds
 3044  *
 3045  *
 3046  * ti->data:
 3047  * [inv.mask4][inv.mask6][log2hsize4][log2hsize6]
 3048  * [        8][        8[          8][         8]
 3049  *
 3050  * inv.mask4: 32 - mask
 3051  * inv.mask6:
 3052  * 1) _slow lookup: mask
 3053  * 2) _aligned: (128 - mask) / 8
 3054  * 3) _64: 8
 3055  *
 3056  *
 3057  * pflags:
 3058  * [hsize4][hsize6]
 3059  * [    16][    16]
 3060  */
 3061 
 3062 struct fhashentry;
 3063 
 3064 SLIST_HEAD(fhashbhead, fhashentry);
 3065 
 3066 struct fhashentry {
 3067         SLIST_ENTRY(fhashentry) next;
 3068         uint8_t         af;
 3069         uint8_t         proto;
 3070         uint16_t        spare0;
 3071         uint16_t        dport;
 3072         uint16_t        sport;
 3073         uint32_t        value;
 3074         uint32_t        spare1;
 3075 };
 3076 
 3077 struct fhashentry4 {
 3078         struct fhashentry       e;
 3079         struct in_addr          dip;
 3080         struct in_addr          sip;
 3081 };
 3082 
 3083 struct fhashentry6 {
 3084         struct fhashentry       e;
 3085         struct in6_addr         dip6;
 3086         struct in6_addr         sip6;
 3087 };
 3088 
 3089 struct fhash_cfg {
 3090         struct fhashbhead       *head;
 3091         size_t                  size;
 3092         size_t                  items;
 3093         struct fhashentry4      fe4;
 3094         struct fhashentry6      fe6;
 3095 };
 3096 
 3097 struct ta_buf_fhash {
 3098         void    *ent_ptr;
 3099         struct fhashentry6 fe6;
 3100 };
 3101 
 3102 static __inline int cmp_flow_ent(struct fhashentry *a,
 3103     struct fhashentry *b, size_t sz);
 3104 static __inline uint32_t hash_flow4(struct fhashentry4 *f, int hsize);
 3105 static __inline uint32_t hash_flow6(struct fhashentry6 *f, int hsize);
 3106 static uint32_t hash_flow_ent(struct fhashentry *ent, uint32_t size);
 3107 static int ta_lookup_fhash(struct table_info *ti, void *key, uint32_t keylen,
 3108     uint32_t *val);
 3109 static int ta_init_fhash(struct ip_fw_chain *ch, void **ta_state,
 3110 struct table_info *ti, char *data, uint8_t tflags);
 3111 static void ta_destroy_fhash(void *ta_state, struct table_info *ti);
 3112 static void ta_dump_fhash_tinfo(void *ta_state, struct table_info *ti,
 3113     ipfw_ta_tinfo *tinfo);
 3114 static int ta_dump_fhash_tentry(void *ta_state, struct table_info *ti,
 3115     void *e, ipfw_obj_tentry *tent);
 3116 static int tei_to_fhash_ent(struct tentry_info *tei, struct fhashentry *ent);
 3117 static int ta_find_fhash_tentry(void *ta_state, struct table_info *ti,
 3118     ipfw_obj_tentry *tent);
 3119 static void ta_foreach_fhash(void *ta_state, struct table_info *ti,
 3120     ta_foreach_f *f, void *arg);
 3121 static int ta_prepare_add_fhash(struct ip_fw_chain *ch,
 3122     struct tentry_info *tei, void *ta_buf);
 3123 static int ta_add_fhash(void *ta_state, struct table_info *ti,
 3124     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
 3125 static int ta_prepare_del_fhash(struct ip_fw_chain *ch, struct tentry_info *tei,
 3126     void *ta_buf);
 3127 static int ta_del_fhash(void *ta_state, struct table_info *ti,
 3128     struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
 3129 static void ta_flush_fhash_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
 3130     void *ta_buf);
 3131 static int ta_need_modify_fhash(void *ta_state, struct table_info *ti,
 3132     uint32_t count, uint64_t *pflags);
 3133 static int ta_prepare_mod_fhash(void *ta_buf, uint64_t *pflags);
 3134 static int ta_fill_mod_fhash(void *ta_state, struct table_info *ti,
 3135     void *ta_buf, uint64_t *pflags);
 3136 static void ta_modify_fhash(void *ta_state, struct table_info *ti, void *ta_buf,
 3137     uint64_t pflags);
 3138 static void ta_flush_mod_fhash(void *ta_buf);
 3139 
 3140 static __inline int
 3141 cmp_flow_ent(struct fhashentry *a, struct fhashentry *b, size_t sz)
 3142 {
 3143         uint64_t *ka, *kb;
 3144 
 3145         ka = (uint64_t *)(&a->next + 1);
 3146         kb = (uint64_t *)(&b->next + 1);
 3147 
 3148         if (*ka == *kb && (memcmp(a + 1, b + 1, sz) == 0))
 3149                 return (1);
 3150 
 3151         return (0);
 3152 }
 3153 
 3154 static __inline uint32_t
 3155 hash_flow4(struct fhashentry4 *f, int hsize)
 3156 {
 3157         uint32_t i;
 3158 
 3159         i = (f->dip.s_addr) ^ (f->sip.s_addr) ^ (f->e.dport) ^ (f->e.sport);
 3160 
 3161         return (i % (hsize - 1));
 3162 }
 3163 
 3164 static __inline uint32_t
 3165 hash_flow6(struct fhashentry6 *f, int hsize)
 3166 {
 3167         uint32_t i;
 3168 
 3169         i = (f->dip6.__u6_addr.__u6_addr32[2]) ^
 3170             (f->dip6.__u6_addr.__u6_addr32[3]) ^
 3171             (f->sip6.__u6_addr.__u6_addr32[2]) ^
 3172             (f->sip6.__u6_addr.__u6_addr32[3]) ^
 3173             (f->e.dport) ^ (f->e.sport);
 3174 
 3175         return (i % (hsize - 1));
 3176 }
 3177 
 3178 static uint32_t
 3179 hash_flow_ent(struct fhashentry *ent, uint32_t size)
 3180 {
 3181         uint32_t hash;
 3182 
 3183         if (ent->af == AF_INET) {
 3184                 hash = hash_flow4((struct fhashentry4 *)ent, size);
 3185         } else {
 3186                 hash = hash_flow6((struct fhashentry6 *)ent, size);
 3187         }
 3188 
 3189         return (hash);
 3190 }
 3191 
 3192 static int
 3193 ta_lookup_fhash(struct table_info *ti, void *key, uint32_t keylen,
 3194     uint32_t *val)
 3195 {
 3196         struct fhashbhead *head;
 3197         struct fhashentry *ent;
 3198         struct fhashentry4 *m4;
 3199         struct ipfw_flow_id *id;
 3200         uint32_t hsize;
 3201         uint16_t hash;
 3202 
 3203         id = (struct ipfw_flow_id *)key;
 3204         head = (struct fhashbhead *)ti->state;
 3205         hsize = ti->data;
 3206         m4 = (struct fhashentry4 *)ti->xstate;
 3207 
 3208         if (id->addr_type == 4) {
 3209                 struct fhashentry4 f;
 3210 
 3211                 /* Copy hash mask */
 3212                 f = *m4;
 3213 
 3214                 f.dip.s_addr &= id->dst_ip;
 3215                 f.sip.s_addr &= id->src_ip;
 3216                 f.e.dport &= id->dst_port;
 3217                 f.e.sport &= id->src_port;
 3218                 f.e.proto &= id->proto;
 3219                 hash = hash_flow4(&f, hsize);
 3220                 SLIST_FOREACH(ent, &head[hash], next) {
 3221                         if (cmp_flow_ent(ent, &f.e, 2 * 4) != 0) {
 3222                                 *val = ent->value;
 3223                                 return (1);
 3224                         }
 3225                 }
 3226         } else if (id->addr_type == 6) {
 3227                 struct fhashentry6 f;
 3228                 uint64_t *fp, *idp;
 3229 
 3230                 /* Copy hash mask */
 3231                 f = *((struct fhashentry6 *)(m4 + 1));
 3232 
 3233                 /* Handle lack of __u6_addr.__u6_addr64 */
 3234                 fp = (uint64_t *)&f.dip6;
 3235                 idp = (uint64_t *)&id->dst_ip6;
 3236                 /* src IPv6 is stored after dst IPv6 */
 3237                 *fp++ &= *idp++;
 3238                 *fp++ &= *idp++;
 3239                 *fp++ &= *idp++;
 3240                 *fp &= *idp;
 3241                 f.e.dport &= id->dst_port;
 3242                 f.e.sport &= id->src_port;
 3243                 f.e.proto &= id->proto;
 3244                 hash = hash_flow6(&f, hsize);
 3245                 SLIST_FOREACH(ent, &head[hash], next) {
 3246                         if (cmp_flow_ent(ent, &f.e, 2 * 16) != 0) {
 3247                                 *val = ent->value;
 3248                                 return (1);
 3249                         }
 3250                 }
 3251         }
 3252 
 3253         return (0);
 3254 }
 3255 
 3256 /*
 3257  * New table.
 3258  */
 3259 static int
 3260 ta_init_fhash(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
 3261     char *data, uint8_t tflags)
 3262 {
 3263         struct fhash_cfg *cfg;
 3264         struct fhashentry4 *fe4;
 3265         struct fhashentry6 *fe6;
 3266         u_int i;
 3267 
 3268         cfg = malloc(sizeof(struct fhash_cfg), M_IPFW, M_WAITOK | M_ZERO);
 3269 
 3270         cfg->size = 512;
 3271 
 3272         cfg->head = malloc(sizeof(struct fhashbhead) * cfg->size, M_IPFW,
 3273             M_WAITOK | M_ZERO);
 3274         for (i = 0; i < cfg->size; i++)
 3275                 SLIST_INIT(&cfg->head[i]);
 3276 
 3277         /* Fill in fe masks based on @tflags */
 3278         fe4 = &cfg->fe4;
 3279         fe6 = &cfg->fe6;
 3280         if (tflags & IPFW_TFFLAG_SRCIP) {
 3281                 memset(&fe4->sip, 0xFF, sizeof(fe4->sip));
 3282                 memset(&fe6->sip6, 0xFF, sizeof(fe6->sip6));
 3283         }
 3284         if (tflags & IPFW_TFFLAG_DSTIP) {
 3285                 memset(&fe4->dip, 0xFF, sizeof(fe4->dip));
 3286                 memset(&fe6->dip6, 0xFF, sizeof(fe6->dip6));
 3287         }
 3288         if (tflags & IPFW_TFFLAG_SRCPORT) {
 3289                 memset(&fe4->e.sport, 0xFF, sizeof(fe4->e.sport));
 3290                 memset(&fe6->e.sport, 0xFF, sizeof(fe6->e.sport));
 3291         }
 3292         if (tflags & IPFW_TFFLAG_DSTPORT) {
 3293                 memset(&fe4->e.dport, 0xFF, sizeof(fe4->e.dport));
 3294                 memset(&fe6->e.dport, 0xFF, sizeof(fe6->e.dport));
 3295         }
 3296         if (tflags & IPFW_TFFLAG_PROTO) {
 3297                 memset(&fe4->e.proto, 0xFF, sizeof(fe4->e.proto));
 3298                 memset(&fe6->e.proto, 0xFF, sizeof(fe6->e.proto));
 3299         }
 3300 
 3301         fe4->e.af = AF_INET;
 3302         fe6->e.af = AF_INET6;
 3303 
 3304         *ta_state = cfg;
 3305         ti->state = cfg->head;
 3306         ti->xstate = &cfg->fe4;
 3307         ti->data = cfg->size;
 3308         ti->lookup = ta_lookup_fhash;
 3309 
 3310         return (0);
 3311 }
 3312 
 3313 static void
 3314 ta_destroy_fhash(void *ta_state, struct table_info *ti)
 3315 {
 3316         struct fhash_cfg *cfg;
 3317         struct fhashentry *ent, *ent_next;
 3318         int i;
 3319 
 3320         cfg = (struct fhash_cfg *)ta_state;
 3321 
 3322         for (i = 0; i < cfg->size; i++)
 3323                 SLIST_FOREACH_SAFE(ent, &cfg->head[i], next, ent_next)
 3324                         free(ent, M_IPFW_TBL);
 3325 
 3326         free(cfg->head, M_IPFW);
 3327         free(cfg, M_IPFW);
 3328 }
 3329 
 3330 /*
 3331  * Provide algo-specific table info
 3332  */
 3333 static void
 3334 ta_dump_fhash_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
 3335 {
 3336         struct fhash_cfg *cfg;
 3337 
 3338         cfg = (struct fhash_cfg *)ta_state;
 3339 
 3340         tinfo->flags = IPFW_TATFLAGS_AFITEM;
 3341         tinfo->taclass4 = IPFW_TACLASS_HASH;
 3342         tinfo->size4 = cfg->size;
 3343         tinfo->count4 = cfg->items;
 3344         tinfo->itemsize4 = sizeof(struct fhashentry4);
 3345         tinfo->itemsize6 = sizeof(struct fhashentry6);
 3346 }
 3347 
 3348 static int
 3349 ta_dump_fhash_tentry(void *ta_state, struct table_info *ti, void *e,
 3350     ipfw_obj_tentry *tent)
 3351 {
 3352         struct fhashentry *ent;
 3353         struct fhashentry4 *fe4;
 3354 #ifdef INET6
 3355         struct fhashentry6 *fe6;
 3356 #endif
 3357         struct tflow_entry *tfe;
 3358 
 3359         ent = (struct fhashentry *)e;
 3360         tfe = &tent->k.flow;
 3361 
 3362         tfe->af = ent->af;
 3363         tfe->proto = ent->proto;
 3364         tfe->dport = htons(ent->dport);
 3365         tfe->sport = htons(ent->sport);
 3366         tent->v.kidx = ent->value;
 3367         tent->subtype = ent->af;
 3368 
 3369         if (ent->af == AF_INET) {
 3370                 fe4 = (struct fhashentry4 *)ent;
 3371                 tfe->a.a4.sip.s_addr = htonl(fe4->sip.s_addr);
 3372                 tfe->a.a4.dip.s_addr = htonl(fe4->dip.s_addr);
 3373                 tent->masklen = 32;
 3374 #ifdef INET6
 3375         } else {
 3376                 fe6 = (struct fhashentry6 *)ent;
 3377                 tfe->a.a6.sip6 = fe6->sip6;
 3378                 tfe->a.a6.dip6 = fe6->dip6;
 3379                 tent->masklen = 128;
 3380 #endif
 3381         }
 3382 
 3383         return (0);
 3384 }
 3385 
 3386 static int
 3387 tei_to_fhash_ent(struct tentry_info *tei, struct fhashentry *ent)
 3388 {
 3389 #ifdef INET
 3390         struct fhashentry4 *fe4;
 3391 #endif
 3392 #ifdef INET6
 3393         struct fhashentry6 *fe6;
 3394 #endif
 3395         struct tflow_entry *tfe;
 3396 
 3397         tfe = (struct tflow_entry *)tei->paddr;
 3398 
 3399         ent->af = tei->subtype;
 3400         ent->proto = tfe->proto;
 3401         ent->dport = ntohs(tfe->dport);
 3402         ent->sport = ntohs(tfe->sport);
 3403 
 3404         if (tei->subtype == AF_INET) {
 3405 #ifdef INET
 3406                 fe4 = (struct fhashentry4 *)ent;
 3407                 fe4->sip.s_addr = ntohl(tfe->a.a4.sip.s_addr);
 3408                 fe4->dip.s_addr = ntohl(tfe->a.a4.dip.s_addr);
 3409 #endif
 3410 #ifdef INET6
 3411         } else if (tei->subtype == AF_INET6) {
 3412                 fe6 = (struct fhashentry6 *)ent;
 3413                 fe6->sip6 = tfe->a.a6.sip6;
 3414                 fe6->dip6 = tfe->a.a6.dip6;
 3415 #endif
 3416         } else {
 3417                 /* Unknown CIDR type */
 3418                 return (EINVAL);
 3419         }
 3420 
 3421         return (0);
 3422 }
 3423 
 3424 static int
 3425 ta_find_fhash_tentry(void *ta_state, struct table_info *ti,
 3426     ipfw_obj_tentry *tent)
 3427 {
 3428         struct fhash_cfg *cfg;
 3429         struct fhashbhead *head;
 3430         struct fhashentry *ent, *tmp;
 3431         struct fhashentry6 fe6;
 3432         struct tentry_info tei;
 3433         int error;
 3434         uint32_t hash;
 3435         size_t sz;
 3436 
 3437         cfg = (struct fhash_cfg *)ta_state;
 3438 
 3439         ent = &fe6.e;
 3440 
 3441         memset(&fe6, 0, sizeof(fe6));
 3442         memset(&tei, 0, sizeof(tei));
 3443 
 3444         tei.paddr = &tent->k.flow;
 3445         tei.subtype = tent->subtype;
 3446 
 3447         if ((error = tei_to_fhash_ent(&tei, ent)) != 0)
 3448                 return (error);
 3449 
 3450         head = cfg->head;
 3451         hash = hash_flow_ent(ent, cfg->size);
 3452 
 3453         if (tei.subtype == AF_INET)
 3454                 sz = 2 * sizeof(struct in_addr);
 3455         else
 3456                 sz = 2 * sizeof(struct in6_addr);
 3457 
 3458         /* Check for existence */
 3459         SLIST_FOREACH(tmp, &head[hash], next) {
 3460                 if (cmp_flow_ent(tmp, ent, sz) != 0) {
 3461                         ta_dump_fhash_tentry(ta_state, ti, tmp, tent);
 3462                         return (0);
 3463                 }
 3464         }
 3465 
 3466         return (ENOENT);
 3467 }
 3468 
 3469 static void
 3470 ta_foreach_fhash(void *ta_state, struct table_info *ti, ta_foreach_f *f,
 3471     void *arg)
 3472 {
 3473         struct fhash_cfg *cfg;
 3474         struct fhashentry *ent, *ent_next;
 3475         int i;
 3476 
 3477         cfg = (struct fhash_cfg *)ta_state;
 3478 
 3479         for (i = 0; i < cfg->size; i++)
 3480                 SLIST_FOREACH_SAFE(ent, &cfg->head[i], next, ent_next)
 3481                         f(ent, arg);
 3482 }
 3483 
 3484 static int
 3485 ta_prepare_add_fhash(struct ip_fw_chain *ch, struct tentry_info *tei,
 3486     void *ta_buf)
 3487 {
 3488         struct ta_buf_fhash *tb;
 3489         struct fhashentry *ent;
 3490         size_t sz;
 3491         int error;
 3492 
 3493         tb = (struct ta_buf_fhash *)ta_buf;
 3494 
 3495         if (tei->subtype == AF_INET)
 3496                 sz = sizeof(struct fhashentry4);
 3497         else if (tei->subtype == AF_INET6)
 3498                 sz = sizeof(struct fhashentry6);
 3499         else
 3500                 return (EINVAL);
 3501 
 3502         ent = malloc(sz, M_IPFW_TBL, M_WAITOK | M_ZERO);
 3503 
 3504         error = tei_to_fhash_ent(tei, ent);
 3505         if (error != 0) {
 3506                 free(ent, M_IPFW_TBL);
 3507                 return (error);
 3508         }
 3509         tb->ent_ptr = ent;
 3510 
 3511         return (0);
 3512 }
 3513 
 3514 static int
 3515 ta_add_fhash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 3516     void *ta_buf, uint32_t *pnum)
 3517 {
 3518         struct fhash_cfg *cfg;
 3519         struct fhashbhead *head;
 3520         struct fhashentry *ent, *tmp;
 3521         struct ta_buf_fhash *tb;
 3522         int exists;
 3523         uint32_t hash, value;
 3524         size_t sz;
 3525 
 3526         cfg = (struct fhash_cfg *)ta_state;
 3527         tb = (struct ta_buf_fhash *)ta_buf;
 3528         ent = (struct fhashentry *)tb->ent_ptr;
 3529         exists = 0;
 3530 
 3531         /* Read current value from @tei */
 3532         ent->value = tei->value;
 3533 
 3534         head = cfg->head;
 3535         hash = hash_flow_ent(ent, cfg->size);
 3536 
 3537         if (tei->subtype == AF_INET)
 3538                 sz = 2 * sizeof(struct in_addr);
 3539         else
 3540                 sz = 2 * sizeof(struct in6_addr);
 3541 
 3542         /* Check for existence */
 3543         SLIST_FOREACH(tmp, &head[hash], next) {
 3544                 if (cmp_flow_ent(tmp, ent, sz) != 0) {
 3545                         exists = 1;
 3546                         break;
 3547                 }
 3548         }
 3549 
 3550         if (exists == 1) {
 3551                 if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
 3552                         return (EEXIST);
 3553                 /* Record already exists. Update value if we're asked to */
 3554                 /* Exchange values between tmp and @tei */
 3555                 value = tmp->value;
 3556                 tmp->value = tei->value;
 3557                 tei->value = value;
 3558                 /* Indicate that update has happened instead of addition */
 3559                 tei->flags |= TEI_FLAGS_UPDATED;
 3560                 *pnum = 0;
 3561         } else {
 3562                 if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
 3563                         return (EFBIG);
 3564 
 3565                 SLIST_INSERT_HEAD(&head[hash], ent, next);
 3566                 tb->ent_ptr = NULL;
 3567                 *pnum = 1;
 3568 
 3569                 /* Update counters and check if we need to grow hash */
 3570                 cfg->items++;
 3571         }
 3572 
 3573         return (0);
 3574 }
 3575 
 3576 static int
 3577 ta_prepare_del_fhash(struct ip_fw_chain *ch, struct tentry_info *tei,
 3578     void *ta_buf)
 3579 {
 3580         struct ta_buf_fhash *tb;
 3581 
 3582         tb = (struct ta_buf_fhash *)ta_buf;
 3583 
 3584         return (tei_to_fhash_ent(tei, &tb->fe6.e));
 3585 }
 3586 
 3587 static int
 3588 ta_del_fhash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 3589     void *ta_buf, uint32_t *pnum)
 3590 {
 3591         struct fhash_cfg *cfg;
 3592         struct fhashbhead *head;
 3593         struct fhashentry *ent, *tmp;
 3594         struct ta_buf_fhash *tb;
 3595         uint32_t hash;
 3596         size_t sz;
 3597 
 3598         cfg = (struct fhash_cfg *)ta_state;
 3599         tb = (struct ta_buf_fhash *)ta_buf;
 3600         ent = &tb->fe6.e;
 3601 
 3602         head = cfg->head;
 3603         hash = hash_flow_ent(ent, cfg->size);
 3604 
 3605         if (tei->subtype == AF_INET)
 3606                 sz = 2 * sizeof(struct in_addr);
 3607         else
 3608                 sz = 2 * sizeof(struct in6_addr);
 3609 
 3610         /* Check for existence */
 3611         SLIST_FOREACH(tmp, &head[hash], next) {
 3612                 if (cmp_flow_ent(tmp, ent, sz) == 0)
 3613                         continue;
 3614 
 3615                 SLIST_REMOVE(&head[hash], tmp, fhashentry, next);
 3616                 tei->value = tmp->value;
 3617                 *pnum = 1;
 3618                 cfg->items--;
 3619                 tb->ent_ptr = tmp;
 3620                 return (0);
 3621         }
 3622 
 3623         return (ENOENT);
 3624 }
 3625 
 3626 static void
 3627 ta_flush_fhash_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
 3628     void *ta_buf)
 3629 {
 3630         struct ta_buf_fhash *tb;
 3631 
 3632         tb = (struct ta_buf_fhash *)ta_buf;
 3633 
 3634         if (tb->ent_ptr != NULL)
 3635                 free(tb->ent_ptr, M_IPFW_TBL);
 3636 }
 3637 
 3638 /*
 3639  * Hash growing callbacks.
 3640  */
 3641 
 3642 static int
 3643 ta_need_modify_fhash(void *ta_state, struct table_info *ti, uint32_t count,
 3644     uint64_t *pflags)
 3645 {
 3646         struct fhash_cfg *cfg;
 3647 
 3648         cfg = (struct fhash_cfg *)ta_state;
 3649 
 3650         if (cfg->items > cfg->size && cfg->size < 65536) {
 3651                 *pflags = cfg->size * 2;
 3652                 return (1);
 3653         }
 3654 
 3655         return (0);
 3656 }
 3657 
 3658 /*
 3659  * Allocate new, larger fhash.
 3660  */
 3661 static int
 3662 ta_prepare_mod_fhash(void *ta_buf, uint64_t *pflags)
 3663 {
 3664         struct mod_item *mi;
 3665         struct fhashbhead *head;
 3666         u_int i;
 3667 
 3668         mi = (struct mod_item *)ta_buf;
 3669 
 3670         memset(mi, 0, sizeof(struct mod_item));
 3671         mi->size = *pflags;
 3672         head = malloc(sizeof(struct fhashbhead) * mi->size, M_IPFW,
 3673             M_WAITOK | M_ZERO);
 3674         for (i = 0; i < mi->size; i++)
 3675                 SLIST_INIT(&head[i]);
 3676 
 3677         mi->main_ptr = head;
 3678 
 3679         return (0);
 3680 }
 3681 
 3682 /*
 3683  * Copy data from old runtime array to new one.
 3684  */
 3685 static int
 3686 ta_fill_mod_fhash(void *ta_state, struct table_info *ti, void *ta_buf,
 3687     uint64_t *pflags)
 3688 {
 3689 
 3690         /* In is not possible to do rehash if we're not holidng WLOCK. */
 3691         return (0);
 3692 }
 3693 
 3694 /*
 3695  * Switch old & new arrays.
 3696  */
 3697 static void
 3698 ta_modify_fhash(void *ta_state, struct table_info *ti, void *ta_buf,
 3699     uint64_t pflags)
 3700 {
 3701         struct mod_item *mi;
 3702         struct fhash_cfg *cfg;
 3703         struct fhashbhead *old_head, *new_head;
 3704         struct fhashentry *ent, *ent_next;
 3705         int i;
 3706         uint32_t nhash;
 3707         size_t old_size;
 3708 
 3709         mi = (struct mod_item *)ta_buf;
 3710         cfg = (struct fhash_cfg *)ta_state;
 3711 
 3712         old_size = cfg->size;
 3713         old_head = ti->state;
 3714 
 3715         new_head = (struct fhashbhead *)mi->main_ptr;
 3716         for (i = 0; i < old_size; i++) {
 3717                 SLIST_FOREACH_SAFE(ent, &old_head[i], next, ent_next) {
 3718                         nhash = hash_flow_ent(ent, mi->size);
 3719                         SLIST_INSERT_HEAD(&new_head[nhash], ent, next);
 3720                 }
 3721         }
 3722 
 3723         ti->state = new_head;
 3724         ti->data = mi->size;
 3725         cfg->head = new_head;
 3726         cfg->size = mi->size;
 3727 
 3728         mi->main_ptr = old_head;
 3729 }
 3730 
 3731 /*
 3732  * Free unneded array.
 3733  */
 3734 static void
 3735 ta_flush_mod_fhash(void *ta_buf)
 3736 {
 3737         struct mod_item *mi;
 3738 
 3739         mi = (struct mod_item *)ta_buf;
 3740         if (mi->main_ptr != NULL)
 3741                 free(mi->main_ptr, M_IPFW);
 3742 }
 3743 
 3744 struct table_algo flow_hash = {
 3745         .name           = "flow:hash",
 3746         .type           = IPFW_TABLE_FLOW,
 3747         .flags          = TA_FLAG_DEFAULT,
 3748         .ta_buf_size    = sizeof(struct ta_buf_fhash),
 3749         .init           = ta_init_fhash,
 3750         .destroy        = ta_destroy_fhash,
 3751         .prepare_add    = ta_prepare_add_fhash,
 3752         .prepare_del    = ta_prepare_del_fhash,
 3753         .add            = ta_add_fhash,
 3754         .del            = ta_del_fhash,
 3755         .flush_entry    = ta_flush_fhash_entry,
 3756         .foreach        = ta_foreach_fhash,
 3757         .dump_tentry    = ta_dump_fhash_tentry,
 3758         .find_tentry    = ta_find_fhash_tentry,
 3759         .dump_tinfo     = ta_dump_fhash_tinfo,
 3760         .need_modify    = ta_need_modify_fhash,
 3761         .prepare_mod    = ta_prepare_mod_fhash,
 3762         .fill_mod       = ta_fill_mod_fhash,
 3763         .modify         = ta_modify_fhash,
 3764         .flush_mod      = ta_flush_mod_fhash,
 3765 };
 3766 
 3767 /*
 3768  * Kernel fibs bindings.
 3769  *
 3770  * Implementation:
 3771  *
 3772  * Runtime part:
 3773  * - fully relies on route API
 3774  * - fib number is stored in ti->data
 3775  *
 3776  */
 3777 
 3778 static int ta_lookup_kfib(struct table_info *ti, void *key, uint32_t keylen,
 3779     uint32_t *val);
 3780 static int kfib_parse_opts(int *pfib, char *data);
 3781 static void ta_print_kfib_config(void *ta_state, struct table_info *ti,
 3782     char *buf, size_t bufsize);
 3783 static int ta_init_kfib(struct ip_fw_chain *ch, void **ta_state,
 3784     struct table_info *ti, char *data, uint8_t tflags);
 3785 static void ta_destroy_kfib(void *ta_state, struct table_info *ti);
 3786 static void ta_dump_kfib_tinfo(void *ta_state, struct table_info *ti,
 3787     ipfw_ta_tinfo *tinfo);
 3788 static int ta_dump_kfib_tentry(void *ta_state, struct table_info *ti, void *e,
 3789     ipfw_obj_tentry *tent);
 3790 static int ta_dump_kfib_tentry_int(int familt, const struct rtentry *rt,
 3791     ipfw_obj_tentry *tent);
 3792 static int ta_find_kfib_tentry(void *ta_state, struct table_info *ti,
 3793     ipfw_obj_tentry *tent);
 3794 static void ta_foreach_kfib(void *ta_state, struct table_info *ti,
 3795     ta_foreach_f *f, void *arg);
 3796 
 3797 static int
 3798 ta_lookup_kfib(struct table_info *ti, void *key, uint32_t keylen,
 3799     uint32_t *val)
 3800 {
 3801 #ifdef INET
 3802         struct in_addr in;
 3803 #endif
 3804         int error;
 3805 
 3806         error = ENOENT;
 3807 #ifdef INET
 3808         if (keylen == 4) {
 3809                 in.s_addr = *(in_addr_t *)key;
 3810                 NET_EPOCH_ASSERT();
 3811                 error = fib4_lookup(ti->data, in, 0, NHR_NONE, 0) != NULL;
 3812         }
 3813 #endif
 3814 #ifdef INET6
 3815         if (keylen == 6)
 3816                 error = fib6_lookup(ti->data, (struct in6_addr *)key,
 3817                     0, NHR_NONE, 0) != NULL;
 3818 #endif
 3819 
 3820         if (error != 0)
 3821                 return (0);
 3822 
 3823         *val = 0;
 3824 
 3825         return (1);
 3826 }
 3827 
 3828 /* Parse 'fib=%d' */
 3829 static int
 3830 kfib_parse_opts(int *pfib, char *data)
 3831 {
 3832         char *pdel, *pend, *s;
 3833         int fibnum;
 3834 
 3835         if (data == NULL)
 3836                 return (0);
 3837         if ((pdel = strchr(data, ' ')) == NULL)
 3838                 return (0);
 3839         while (*pdel == ' ')
 3840                 pdel++;
 3841         if (strncmp(pdel, "fib=", 4) != 0)
 3842                 return (EINVAL);
 3843         if ((s = strchr(pdel, ' ')) != NULL)
 3844                 *s++ = '\0';
 3845 
 3846         pdel += 4;
 3847         /* Need \d+ */
 3848         fibnum = strtol(pdel, &pend, 10);
 3849         if (*pend != '\0')
 3850                 return (EINVAL);
 3851 
 3852         *pfib = fibnum;
 3853 
 3854         return (0);
 3855 }
 3856 
 3857 static void
 3858 ta_print_kfib_config(void *ta_state, struct table_info *ti, char *buf,
 3859     size_t bufsize)
 3860 {
 3861 
 3862         if (ti->data != 0)
 3863                 snprintf(buf, bufsize, "%s fib=%lu", "addr:kfib", ti->data);
 3864         else
 3865                 snprintf(buf, bufsize, "%s", "addr:kfib");
 3866 }
 3867 
 3868 static int
 3869 ta_init_kfib(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
 3870     char *data, uint8_t tflags)
 3871 {
 3872         int error, fibnum;
 3873 
 3874         fibnum = 0;
 3875         if ((error = kfib_parse_opts(&fibnum, data)) != 0)
 3876                 return (error);
 3877 
 3878         if (fibnum >= rt_numfibs)
 3879                 return (E2BIG);
 3880 
 3881         ti->data = fibnum;
 3882         ti->lookup = ta_lookup_kfib;
 3883 
 3884         return (0);
 3885 }
 3886 
 3887 /*
 3888  * Destroys table @ti
 3889  */
 3890 static void
 3891 ta_destroy_kfib(void *ta_state, struct table_info *ti)
 3892 {
 3893 
 3894 }
 3895 
 3896 /*
 3897  * Provide algo-specific table info
 3898  */
 3899 static void
 3900 ta_dump_kfib_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
 3901 {
 3902 
 3903         tinfo->flags = IPFW_TATFLAGS_AFDATA;
 3904         tinfo->taclass4 = IPFW_TACLASS_RADIX;
 3905         tinfo->count4 = 0;
 3906         tinfo->itemsize4 = 128; /* table is readonly, value does not matter */
 3907         tinfo->taclass6 = IPFW_TACLASS_RADIX;
 3908         tinfo->count6 = 0;
 3909         tinfo->itemsize6 = 128;
 3910 }
 3911 
 3912 static int
 3913 ta_dump_kfib_tentry_int(int family, const struct rtentry *rt,
 3914     ipfw_obj_tentry *tent)
 3915 {
 3916         uint32_t scopeid;
 3917         int plen;
 3918 
 3919 #ifdef INET
 3920         if (family == AF_INET) {
 3921                 rt_get_inet_prefix_plen(rt, &tent->k.addr, &plen, &scopeid);
 3922                 tent->masklen = plen;
 3923                 tent->subtype = AF_INET;
 3924                 tent->v.kidx = 0;
 3925         }
 3926 #endif
 3927 #ifdef INET6
 3928         if (family == AF_INET6) {
 3929                 rt_get_inet6_prefix_plen(rt, &tent->k.addr6, &plen, &scopeid);
 3930                 tent->masklen = plen;
 3931                 tent->subtype = AF_INET6;
 3932                 tent->v.kidx = 0;
 3933         }
 3934 #endif
 3935         return (0);
 3936 }
 3937 
 3938 static int
 3939 ta_find_kfib_tentry(void *ta_state, struct table_info *ti,
 3940     ipfw_obj_tentry *tent)
 3941 {
 3942         struct rtentry *rt = NULL;
 3943         struct route_nhop_data rnd;
 3944         struct epoch_tracker et;
 3945         int error;
 3946 
 3947         NET_EPOCH_ENTER(et);
 3948 
 3949         switch (tent->subtype) {
 3950 #ifdef INET
 3951         case AF_INET:
 3952                 rt = fib4_lookup_rt(ti->data, tent->k.addr, 0, 0, &rnd);
 3953                 break;
 3954 #endif
 3955 #ifdef INET6
 3956         case AF_INET6:
 3957                 rt = fib6_lookup_rt(ti->data, &tent->k.addr6, 0, 0, &rnd);
 3958                 break;
 3959 #endif
 3960         }
 3961         if (rt != NULL)
 3962                 error = ta_dump_kfib_tentry_int(tent->subtype, rt, tent);
 3963         else
 3964                 error = ENOENT;
 3965         NET_EPOCH_EXIT(et);
 3966 
 3967         return (error);
 3968 }
 3969 
 3970 struct kfib_dump_arg {
 3971         struct rtentry *rt;
 3972         int             family;
 3973         ta_foreach_f    *f;
 3974         void            *arg;
 3975 };
 3976 
 3977 static int
 3978 ta_dump_kfib_tentry(void *ta_state, struct table_info *ti, void *e,
 3979     ipfw_obj_tentry *tent)
 3980 {
 3981         struct kfib_dump_arg *karg = (struct kfib_dump_arg *)e;
 3982 
 3983         return (ta_dump_kfib_tentry_int(karg->family, karg->rt, tent));
 3984 }
 3985 
 3986 static int
 3987 walk_wrapper_f(struct rtentry *rt, void *arg)
 3988 {
 3989         struct kfib_dump_arg *karg = (struct kfib_dump_arg *)arg;
 3990 
 3991         karg->rt = rt;
 3992         return (karg->f(karg, karg->arg));
 3993 }
 3994 
 3995 static void
 3996 ta_foreach_kfib(void *ta_state, struct table_info *ti, ta_foreach_f *f,
 3997     void *arg)
 3998 {
 3999         struct kfib_dump_arg karg = { .f = f, .arg = arg };
 4000 
 4001         karg.family = AF_INET;
 4002         rib_walk(ti->data, AF_INET, false, walk_wrapper_f, &karg);
 4003         karg.family = AF_INET6;
 4004         rib_walk(ti->data, AF_INET6, false, walk_wrapper_f, &karg);
 4005 }
 4006 
 4007 struct table_algo addr_kfib = {
 4008         .name           = "addr:kfib",
 4009         .type           = IPFW_TABLE_ADDR,
 4010         .flags          = TA_FLAG_READONLY,
 4011         .ta_buf_size    = 0,
 4012         .init           = ta_init_kfib,
 4013         .destroy        = ta_destroy_kfib,
 4014         .foreach        = ta_foreach_kfib,
 4015         .dump_tentry    = ta_dump_kfib_tentry,
 4016         .find_tentry    = ta_find_kfib_tentry,
 4017         .dump_tinfo     = ta_dump_kfib_tinfo,
 4018         .print_config   = ta_print_kfib_config,
 4019 };
 4020 
 4021 struct mac_radix_entry {
 4022         struct radix_node       rn[2];
 4023         uint32_t                value;
 4024         uint8_t                 masklen;
 4025         struct sa_mac           sa;
 4026 };
 4027 
 4028 struct mac_radix_cfg {
 4029         struct radix_node_head  *head;
 4030         size_t                  count;
 4031 };
 4032 
 4033 static int
 4034 ta_lookup_mac_radix(struct table_info *ti, void *key, uint32_t keylen,
 4035     uint32_t *val)
 4036 {
 4037         struct radix_node_head *rnh;
 4038 
 4039         if (keylen == ETHER_ADDR_LEN) {
 4040                 struct mac_radix_entry *ent;
 4041                 struct sa_mac sa;
 4042                 KEY_LEN(sa) = KEY_LEN_MAC;
 4043                 memcpy(sa.mac_addr.octet, key, ETHER_ADDR_LEN);
 4044                 rnh = (struct radix_node_head *)ti->state;
 4045                 ent = (struct mac_radix_entry *)(rnh->rnh_matchaddr(&sa, &rnh->rh));
 4046                 if (ent != NULL) {
 4047                         *val = ent->value;
 4048                         return (1);
 4049                 }
 4050         }
 4051         return (0);
 4052 }
 4053 
 4054 static int
 4055 ta_init_mac_radix(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
 4056     char *data, uint8_t tflags)
 4057 {
 4058         struct mac_radix_cfg *cfg;
 4059 
 4060         if (!rn_inithead(&ti->state, OFF_LEN_MAC))
 4061                 return (ENOMEM);
 4062 
 4063         cfg = malloc(sizeof(struct mac_radix_cfg), M_IPFW, M_WAITOK | M_ZERO);
 4064 
 4065         *ta_state = cfg;
 4066         ti->lookup = ta_lookup_mac_radix;
 4067 
 4068         return (0);
 4069 }
 4070 
 4071 static void
 4072 ta_destroy_mac_radix(void *ta_state, struct table_info *ti)
 4073 {
 4074         struct mac_radix_cfg *cfg;
 4075         struct radix_node_head *rnh;
 4076 
 4077         cfg = (struct mac_radix_cfg *)ta_state;
 4078 
 4079         rnh = (struct radix_node_head *)(ti->state);
 4080         rnh->rnh_walktree(&rnh->rh, flush_radix_entry, rnh);
 4081         rn_detachhead(&ti->state);
 4082 
 4083         free(cfg, M_IPFW);
 4084 }
 4085 
 4086 static void
 4087 tei_to_sockaddr_ent_mac(struct tentry_info *tei, struct sockaddr *sa,
 4088     struct sockaddr *ma, int *set_mask)
 4089 {
 4090         int mlen, i;
 4091         struct sa_mac *addr, *mask;
 4092         u_char *cp;
 4093 
 4094         mlen = tei->masklen;
 4095         addr = (struct sa_mac *)sa;
 4096         mask = (struct sa_mac *)ma;
 4097         /* Set 'total' structure length */
 4098         KEY_LEN(*addr) = KEY_LEN_MAC;
 4099         KEY_LEN(*mask) = KEY_LEN_MAC;
 4100 
 4101         for (i = mlen, cp = mask->mac_addr.octet; i >= 8; i -= 8)
 4102                 *cp++ = 0xFF;
 4103         if (i > 0)
 4104                 *cp = ~((1 << (8 - i)) - 1);
 4105 
 4106         addr->mac_addr = *((struct ether_addr *)tei->paddr);
 4107         for (i = 0; i < ETHER_ADDR_LEN; ++i)
 4108                 addr->mac_addr.octet[i] &= mask->mac_addr.octet[i];
 4109 
 4110         if (mlen != 8 * ETHER_ADDR_LEN)
 4111                 *set_mask = 1;
 4112         else
 4113                 *set_mask = 0;
 4114 }
 4115 
 4116 static int
 4117 ta_prepare_add_mac_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
 4118     void *ta_buf)
 4119 {
 4120         struct ta_buf_radix *tb;
 4121         struct mac_radix_entry *ent;
 4122         struct sockaddr *addr, *mask;
 4123         int mlen, set_mask;
 4124 
 4125         tb = (struct ta_buf_radix *)ta_buf;
 4126 
 4127         mlen = tei->masklen;
 4128         set_mask = 0;
 4129 
 4130         if (tei->subtype == AF_LINK) {
 4131                 if (mlen > 8 * ETHER_ADDR_LEN)
 4132                         return (EINVAL);
 4133                 ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO);
 4134                 ent->masklen = mlen;
 4135 
 4136                 addr = (struct sockaddr *)&ent->sa;
 4137                 mask = (struct sockaddr *)&tb->addr.mac.ma;
 4138                 tb->ent_ptr = ent;
 4139         } else {
 4140                 /* Unknown CIDR type */
 4141                 return (EINVAL);
 4142         }
 4143 
 4144         tei_to_sockaddr_ent_mac(tei, addr, mask, &set_mask);
 4145         /* Set pointers */
 4146         tb->addr_ptr = addr;
 4147         if (set_mask != 0)
 4148                 tb->mask_ptr = mask;
 4149 
 4150         return (0);
 4151 }
 4152 
 4153 static int
 4154 ta_add_mac_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 4155     void *ta_buf, uint32_t *pnum)
 4156 {
 4157         struct mac_radix_cfg *cfg;
 4158         struct radix_node_head *rnh;
 4159         struct radix_node *rn;
 4160         struct ta_buf_radix *tb;
 4161         uint32_t *old_value, value;
 4162 
 4163         cfg = (struct mac_radix_cfg *)ta_state;
 4164         tb = (struct ta_buf_radix *)ta_buf;
 4165 
 4166         /* Save current entry value from @tei */
 4167         rnh = ti->state;
 4168         ((struct mac_radix_entry *)tb->ent_ptr)->value = tei->value;
 4169 
 4170         /* Search for an entry first */
 4171         rn = rnh->rnh_lookup(tb->addr_ptr, tb->mask_ptr, &rnh->rh);
 4172         if (rn != NULL) {
 4173                 if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
 4174                         return (EEXIST);
 4175                 /* Record already exists. Update value if we're asked to */
 4176                 old_value = &((struct mac_radix_entry *)rn)->value;
 4177 
 4178                 value = *old_value;
 4179                 *old_value = tei->value;
 4180                 tei->value = value;
 4181 
 4182                 /* Indicate that update has happened instead of addition */
 4183                 tei->flags |= TEI_FLAGS_UPDATED;
 4184                 *pnum = 0;
 4185 
 4186                 return (0);
 4187         }
 4188 
 4189         if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
 4190                 return (EFBIG);
 4191 
 4192         rn = rnh->rnh_addaddr(tb->addr_ptr, tb->mask_ptr, &rnh->rh, tb->ent_ptr);
 4193         if (rn == NULL) {
 4194                 /* Unknown error */
 4195                 return (EINVAL);
 4196         }
 4197 
 4198         cfg->count++;
 4199         tb->ent_ptr = NULL;
 4200         *pnum = 1;
 4201 
 4202         return (0);
 4203 }
 4204 
 4205 static int
 4206 ta_prepare_del_mac_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
 4207     void *ta_buf)
 4208 {
 4209         struct ta_buf_radix *tb;
 4210         struct sockaddr *addr, *mask;
 4211         int mlen, set_mask;
 4212 
 4213         tb = (struct ta_buf_radix *)ta_buf;
 4214 
 4215         mlen = tei->masklen;
 4216         set_mask = 0;
 4217 
 4218         if (tei->subtype == AF_LINK) {
 4219                 if (mlen > 8 * ETHER_ADDR_LEN)
 4220                         return (EINVAL);
 4221 
 4222                 addr = (struct sockaddr *)&tb->addr.mac.sa;
 4223                 mask = (struct sockaddr *)&tb->addr.mac.ma;
 4224         } else
 4225                 return (EINVAL);
 4226 
 4227         tei_to_sockaddr_ent_mac(tei, addr, mask, &set_mask);
 4228         tb->addr_ptr = addr;
 4229         if (set_mask != 0)
 4230                 tb->mask_ptr = mask;
 4231 
 4232         return (0);
 4233 }
 4234 
 4235 static int
 4236 ta_del_mac_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei,
 4237     void *ta_buf, uint32_t *pnum)
 4238 {
 4239         struct mac_radix_cfg *cfg;
 4240         struct radix_node_head *rnh;
 4241         struct radix_node *rn;
 4242         struct ta_buf_radix *tb;
 4243 
 4244         cfg = (struct mac_radix_cfg *)ta_state;
 4245         tb = (struct ta_buf_radix *)ta_buf;
 4246         rnh = ti->state;
 4247 
 4248         rn = rnh->rnh_deladdr(tb->addr_ptr, tb->mask_ptr, &rnh->rh);
 4249 
 4250         if (rn == NULL)
 4251                 return (ENOENT);
 4252 
 4253         /* Save entry value to @tei */
 4254         tei->value = ((struct mac_radix_entry *)rn)->value;
 4255 
 4256         tb->ent_ptr = rn;
 4257         cfg->count--;
 4258         *pnum = 1;
 4259 
 4260         return (0);
 4261 }
 4262 
 4263 static void
 4264 ta_foreach_mac_radix(void *ta_state, struct table_info *ti, ta_foreach_f *f,
 4265     void *arg)
 4266 {
 4267         struct radix_node_head *rnh;
 4268 
 4269         rnh = (struct radix_node_head *)(ti->state);
 4270         rnh->rnh_walktree(&rnh->rh, (walktree_f_t *)f, arg);
 4271 }
 4272 
 4273 static void
 4274 ta_dump_mac_radix_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
 4275 {
 4276         struct mac_radix_cfg *cfg;
 4277 
 4278         cfg = (struct mac_radix_cfg *)ta_state;
 4279 
 4280         tinfo->flags = IPFW_TATFLAGS_AFDATA | IPFW_TATFLAGS_AFITEM;
 4281         tinfo->taclass4 = IPFW_TACLASS_RADIX;
 4282         tinfo->count4 = cfg->count;
 4283         tinfo->itemsize4 = sizeof(struct mac_radix_entry);
 4284 }
 4285 
 4286 static int
 4287 ta_dump_mac_radix_tentry(void *ta_state, struct table_info *ti, void *e,
 4288     ipfw_obj_tentry *tent)
 4289 {
 4290         struct mac_radix_entry *n = (struct mac_radix_entry *)e;
 4291 
 4292         memcpy(tent->k.mac, n->sa.mac_addr.octet, ETHER_ADDR_LEN);
 4293         tent->masklen = n->masklen;
 4294         tent->subtype = AF_LINK;
 4295         tent->v.kidx = n->value;
 4296 
 4297         return (0);
 4298 }
 4299 
 4300 static int
 4301 ta_find_mac_radix_tentry(void *ta_state, struct table_info *ti,
 4302     ipfw_obj_tentry *tent)
 4303 {
 4304         struct radix_node_head *rnh;
 4305         void *e;
 4306 
 4307         e = NULL;
 4308         if (tent->subtype == AF_LINK) {
 4309                 struct sa_mac sa;
 4310                 KEY_LEN(sa) = KEY_LEN_MAC;
 4311                 memcpy(tent->k.mac, sa.mac_addr.octet, ETHER_ADDR_LEN);
 4312                 rnh = (struct radix_node_head *)ti->state;
 4313                 e = rnh->rnh_matchaddr(&sa, &rnh->rh);
 4314         }
 4315 
 4316         if (e != NULL) {
 4317                 ta_dump_mac_radix_tentry(ta_state, ti, e, tent);
 4318                 return (0);
 4319         }
 4320 
 4321         return (ENOENT);
 4322 }
 4323 
 4324 struct table_algo mac_radix = {
 4325         .name           = "mac:radix",
 4326         .type           = IPFW_TABLE_MAC,
 4327         .flags          = TA_FLAG_DEFAULT,
 4328         .ta_buf_size    = sizeof(struct ta_buf_radix),
 4329         .init           = ta_init_mac_radix,
 4330         .destroy        = ta_destroy_mac_radix,
 4331         .prepare_add    = ta_prepare_add_mac_radix,
 4332         .prepare_del    = ta_prepare_del_mac_radix,
 4333         .add            = ta_add_mac_radix,
 4334         .del            = ta_del_mac_radix,
 4335         .flush_entry    = ta_flush_radix_entry,
 4336         .foreach        = ta_foreach_mac_radix,
 4337         .dump_tentry    = ta_dump_mac_radix_tentry,
 4338         .find_tentry    = ta_find_mac_radix_tentry,
 4339         .dump_tinfo     = ta_dump_mac_radix_tinfo,
 4340         .need_modify    = ta_need_modify_radix,
 4341 };
 4342 
 4343 void
 4344 ipfw_table_algo_init(struct ip_fw_chain *ch)
 4345 {
 4346         size_t sz;
 4347 
 4348         /*
 4349          * Register all algorithms presented here.
 4350          */
 4351         sz = sizeof(struct table_algo);
 4352         ipfw_add_table_algo(ch, &addr_radix, sz, &addr_radix.idx);
 4353         ipfw_add_table_algo(ch, &addr_hash, sz, &addr_hash.idx);
 4354         ipfw_add_table_algo(ch, &iface_idx, sz, &iface_idx.idx);
 4355         ipfw_add_table_algo(ch, &number_array, sz, &number_array.idx);
 4356         ipfw_add_table_algo(ch, &flow_hash, sz, &flow_hash.idx);
 4357         ipfw_add_table_algo(ch, &addr_kfib, sz, &addr_kfib.idx);
 4358         ipfw_add_table_algo(ch, &mac_radix, sz, &mac_radix.idx);
 4359 }
 4360 
 4361 void
 4362 ipfw_table_algo_destroy(struct ip_fw_chain *ch)
 4363 {
 4364 
 4365         ipfw_del_table_algo(ch, addr_radix.idx);
 4366         ipfw_del_table_algo(ch, addr_hash.idx);
 4367         ipfw_del_table_algo(ch, iface_idx.idx);
 4368         ipfw_del_table_algo(ch, number_array.idx);
 4369         ipfw_del_table_algo(ch, flow_hash.idx);
 4370         ipfw_del_table_algo(ch, addr_kfib.idx);
 4371         ipfw_del_table_algo(ch, mac_radix.idx);
 4372 }

Cache object: d11c5a76955fa20ed877441974bce3e3


[ 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.