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