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