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