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