2 * Copyright (c) 2004 Ruslan Ermilov and Vsevolod Lobko.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
30 * Lookup table support for ipfw.
32 * This file contains handlers for all generic tables' operations:
33 * add/del/flush entries, list/dump tables etc..
35 * Table data modification is protected by both UH and runtimg lock
36 * while reading configuration/data is protected by UH lock.
38 * Lookup algorithms for all table types are located in ip_fw_table_algo.c
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/malloc.h>
46 #include <sys/kernel.h>
48 #include <sys/rwlock.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/queue.h>
52 #include <net/if.h> /* ip_fw.h requires IFNAMSIZ */
54 #include <netinet/in.h>
55 #include <netinet/ip_var.h> /* struct ipfw_rule_ref */
56 #include <netinet/ip_fw.h>
58 #include <netpfil/ipfw/ip_fw_private.h>
59 #include <netpfil/ipfw/ip_fw_table.h>
63 * Table has the following `type` concepts:
65 * `no.type` represents lookup key type (cidr, ifp, uid, etc..)
66 * `ta->atype` represents exact lookup algorithm.
67 * For example, we can use more efficient search schemes if we plan
68 * to use some specific table for storing host-routes only.
69 * `ftype` (at the moment )is pure userland field helping to properly
70 * format value data e.g. "value is IPv4 nexthop" or "value is DSCP"
75 struct named_object no;
76 uint8_t vtype; /* format table type */
77 uint8_t linked; /* 1 if already linked */
78 uint8_t tflags; /* type flags */
80 uint32_t count; /* Number of records */
81 uint32_t limit; /* Max number of records */
82 char tablename[64]; /* table name */
83 struct table_algo *ta; /* Callbacks for given algo */
84 void *astate; /* algorithm state */
85 struct table_info ti; /* data to put to table_info */
88 struct tables_config {
89 struct namedobj_instance *namehash;
91 struct table_algo *algo[256];
92 struct table_algo *def_algo[IPFW_TABLE_MAXTYPE + 1];
95 static struct table_config *find_table(struct namedobj_instance *ni,
97 static struct table_config *alloc_table_config(struct ip_fw_chain *ch,
98 struct tid_info *ti, struct table_algo *ta, char *adata, uint8_t tflags,
100 static void free_table_config(struct namedobj_instance *ni,
101 struct table_config *tc);
102 static int create_table_internal(struct ip_fw_chain *ch, struct tid_info *ti,
103 char *aname, ipfw_xtable_info *i);
104 static void link_table(struct ip_fw_chain *chain, struct table_config *tc);
105 static void unlink_table(struct ip_fw_chain *chain, struct table_config *tc);
106 static void free_table_state(void **state, void **xstate, uint8_t type);
107 static int export_tables(struct ip_fw_chain *ch, ipfw_obj_lheader *olh,
108 struct sockopt_data *sd);
109 static void export_table_info(struct ip_fw_chain *ch, struct table_config *tc,
110 ipfw_xtable_info *i);
111 static int dump_table_tentry(void *e, void *arg);
112 static int dump_table_xentry(void *e, void *arg);
114 static int ipfw_dump_table_v0(struct ip_fw_chain *ch, struct sockopt_data *sd);
115 static int ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt_data *sd);
116 static int ipfw_manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
117 struct sockopt_data *sd);
118 static int ipfw_manage_table_ent_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
119 struct sockopt_data *sd);
121 static int check_table_space(struct ip_fw_chain *ch, struct table_config *tc,
122 struct table_info *ti, uint32_t count);
123 static int destroy_table(struct ip_fw_chain *ch, struct tid_info *ti);
125 static struct table_algo *find_table_algo(struct tables_config *tableconf,
126 struct tid_info *ti, char *name);
128 #define CHAIN_TO_TCFG(chain) ((struct tables_config *)(chain)->tblcfg)
129 #define CHAIN_TO_NI(chain) (CHAIN_TO_TCFG(chain)->namehash)
130 #define KIDX_TO_TI(ch, k) (&(((struct table_info *)(ch)->tablestate)[k]))
132 #define TA_BUF_SZ 128 /* On-stack buffer for add/delete state */
136 add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
137 struct tentry_info *tei, uint32_t count)
139 struct table_config *tc;
140 struct table_algo *ta;
141 struct namedobj_instance *ni;
145 ipfw_xtable_info *xi;
146 char ta_buf[TA_BUF_SZ];
149 ni = CHAIN_TO_NI(ch);
152 * Find and reference existing table.
155 if ((tc = find_table(ni, ti)) != NULL) {
156 /* check table type */
157 if (tc->no.type != ti->type) {
162 /* Try to exit early on limit hit */
163 if (tc->limit != 0 && tc->count == tc->limit &&
164 (tei->flags & TEI_FLAGS_UPDATE) == 0) {
169 /* Reference and unlock */
176 /* Compability mode: create new table for old clients */
177 if ((tei->flags & TEI_FLAGS_COMPAT) == 0)
180 xi = malloc(sizeof(ipfw_xtable_info), M_TEMP, M_WAITOK|M_ZERO);
181 xi->vtype = IPFW_VTYPE_U32;
183 error = create_table_internal(ch, ti, NULL, xi);
189 /* Let's try to find & reference another time */
191 if ((tc = find_table(ni, ti)) == NULL) {
196 if (tc->no.type != ti->type) {
201 /* Reference and unlock */
208 /* Prepare record (allocate memory) */
209 memset(&ta_buf, 0, sizeof(ta_buf));
210 error = ta->prepare_add(ch, tei, &ta_buf);
217 * Ensure we are able to add all entries without additional
218 * memory allocations. May release/reacquire UH_WLOCK.
221 error = check_table_space(ch, tc, KIDX_TO_TI(ch, kidx), count);
224 ta->flush_entry(ch, tei, &ta_buf);
228 ni = CHAIN_TO_NI(ch);
230 /* Drop reference we've used in first search */
233 /* Check limit before adding */
234 if (tc->limit != 0 && tc->count == tc->limit) {
235 if ((tei->flags & TEI_FLAGS_UPDATE) == 0) {
237 ta->flush_entry(ch, tei, &ta_buf);
242 * We have UPDATE flag set.
243 * Permit updating record (if found),
244 * but restrict adding new one since we've
245 * already hit the limit.
247 tei->flags |= TEI_FLAGS_DONTADD;
250 /* We've got valid table in @tc. Let's add data */
256 error = ta->add(tc->astate, KIDX_TO_TI(ch, kidx), tei, &ta_buf, &num);
259 /* Update number of records. */
262 /* Permit post-add algorithm grow/rehash. */
263 error = check_table_space(ch, tc, KIDX_TO_TI(ch, kidx), 0);
268 /* Run cleaning callback anyway */
269 ta->flush_entry(ch, tei, &ta_buf);
275 del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
276 struct tentry_info *tei, uint32_t count)
278 struct table_config *tc;
279 struct table_algo *ta;
280 struct namedobj_instance *ni;
284 char ta_buf[TA_BUF_SZ];
287 ni = CHAIN_TO_NI(ch);
288 if ((tc = find_table(ni, ti)) == NULL) {
293 if (tc->no.type != ti->type) {
301 * Give a chance for algorithm to shrink.
302 * May release/reacquire UH_WLOCK.
305 error = check_table_space(ch, tc, KIDX_TO_TI(ch, kidx), 0);
308 ta->flush_entry(ch, tei, &ta_buf);
313 * We assume ta_buf size is enough for storing
314 * prepare_del() key, so we're running under UH_WLOCK here.
316 memset(&ta_buf, 0, sizeof(ta_buf));
317 if ((error = ta->prepare_del(ch, tei, &ta_buf)) != 0) {
326 error = ta->del(tc->astate, KIDX_TO_TI(ch, kidx), tei, &ta_buf, &num);
331 /* Run post-del hook to permit shrinking */
332 error = check_table_space(ch, tc, KIDX_TO_TI(ch, kidx), 0);
337 ta->flush_entry(ch, tei, &ta_buf);
343 * Ensure that table @tc has enough space to add @count entries without
344 * need for reallocation.
347 * 0) has_space() (UH_WLOCK) - checks if @count items can be added w/o resize.
349 * 1) alloc_modify (no locks, M_WAITOK) - alloc new state based on @pflags.
350 * 2) prepare_modifyt (UH_WLOCK) - copy old data into new storage
351 * 3) modify (UH_WLOCK + WLOCK) - switch pointers
352 * 4) flush_modify (UH_WLOCK) - free state, if needed
354 * Returns 0 on success.
357 check_table_space(struct ip_fw_chain *ch, struct table_config *tc,
358 struct table_info *ti, uint32_t count)
360 struct table_algo *ta;
362 char ta_buf[TA_BUF_SZ];
365 IPFW_UH_WLOCK_ASSERT(ch);
369 /* Acquire reference not to loose @tc between locks/unlocks */
373 * TODO: think about avoiding race between large add/large delete
374 * operation on algorithm which implements shrinking along with
379 if (ta->has_space(tc->astate, ti, count, &pflags) != 0) {
384 /* We have to shrink/grow table */
386 memset(&ta_buf, 0, sizeof(ta_buf));
388 if ((error = ta->prepare_mod(ta_buf, &pflags)) != 0) {
395 /* Check if we still need to alter table */
396 ti = KIDX_TO_TI(ch, tc->no.kidx);
397 if (ta->has_space(tc->astate, ti, count, &pflags) != 0) {
400 * Other threads has already performed resize.
401 * Flush our state and return/
403 ta->flush_mod(ta_buf);
407 error = ta->fill_mod(tc->astate, ti, ta_buf, &pflags);
409 /* Do actual modification */
411 ta->modify(tc->astate, ti, ta_buf, pflags);
415 /* Anyway, flush data and retry */
416 ta->flush_mod(ta_buf);
426 ipfw_manage_table_ent(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
427 struct sockopt_data *sd)
431 switch (op3->version) {
433 error = ipfw_manage_table_ent_v0(ch, op3, sd);
436 error = ipfw_manage_table_ent_v1(ch, op3, sd);
446 * Adds or deletes record in table.
448 * Request: [ ip_fw3_opheader ipfw_table_xentry ]
450 * Returns 0 on success
453 ipfw_manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
454 struct sockopt_data *sd)
456 ipfw_table_xentry *xent;
457 struct tentry_info tei;
459 int error, hdrlen, read;
461 hdrlen = offsetof(ipfw_table_xentry, k);
463 /* Check minimum header size */
464 if (sd->valsize < (sizeof(*op3) + hdrlen))
467 read = sizeof(ip_fw3_opheader);
469 /* Check if xentry len field is valid */
470 xent = (ipfw_table_xentry *)(op3 + 1);
471 if (xent->len < hdrlen || xent->len + read > sd->valsize)
474 memset(&tei, 0, sizeof(tei));
475 tei.paddr = &xent->k;
476 tei.masklen = xent->masklen;
477 tei.value = xent->value;
478 /* Old requests compability */
479 tei.flags = TEI_FLAGS_COMPAT;
480 if (xent->type == IPFW_TABLE_CIDR) {
481 if (xent->len - hdrlen == sizeof(in_addr_t))
482 tei.subtype = AF_INET;
484 tei.subtype = AF_INET6;
487 memset(&ti, 0, sizeof(ti));
489 ti.type = xent->type;
491 error = (op3->opcode == IP_FW_TABLE_XADD) ?
492 add_table_entry(ch, &ti, &tei, 1) :
493 del_table_entry(ch, &ti, &tei, 1);
499 * Adds or deletes record in table.
500 * Data layout (v1)(current):
501 * Request: [ ipfw_obj_header
502 * ipfw_obj_ctlv(IPFW_TLV_TBLENT_LIST) [ ipfw_obj_tentry x N ]
505 * Returns 0 on success
508 ipfw_manage_table_ent_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
509 struct sockopt_data *sd)
511 ipfw_obj_tentry *tent;
514 struct tentry_info tei;
518 /* Check minimum header size */
519 if (sd->valsize < (sizeof(*oh) + sizeof(*ctlv)))
522 /* Check if passed data is too long */
523 if (sd->valsize != sd->kavail)
526 oh = (ipfw_obj_header *)sd->kbuf;
528 /* Basic length checks for TLVs */
529 if (oh->ntlv.head.length != sizeof(oh->ntlv))
534 ctlv = (ipfw_obj_ctlv *)(oh + 1);
535 if (ctlv->head.length + read != sd->valsize)
539 * TODO: permit adding multiple entries for given table
542 if (ctlv->count != 1)
545 read += sizeof(*ctlv);
547 /* Assume tentry may grow to support larger keys */
548 tent = (ipfw_obj_tentry *)(ctlv + 1);
549 if (tent->head.length < sizeof(*tent) ||
550 tent->head.length + read > sd->valsize)
553 /* Convert data into kernel request objects */
554 memset(&tei, 0, sizeof(tei));
555 tei.paddr = &tent->k;
556 tei.subtype = tent->subtype;
557 tei.masklen = tent->masklen;
558 if (tent->head.flags & IPFW_TF_UPDATE)
559 tei.flags |= TEI_FLAGS_UPDATE;
560 tei.value = tent->value;
562 objheader_to_ti(oh, &ti);
563 ti.type = oh->ntlv.type;
566 error = (oh->opheader.opcode == IP_FW_TABLE_XADD) ?
567 add_table_entry(ch, &ti, &tei, 1) :
568 del_table_entry(ch, &ti, &tei, 1);
574 * Looks up an entry in given table.
575 * Data layout (v0)(current):
576 * Request: [ ipfw_obj_header ipfw_obj_tentry ]
577 * Reply: [ ipfw_obj_header ipfw_obj_tentry ]
579 * Returns 0 on success
582 ipfw_find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
583 struct sockopt_data *sd)
585 ipfw_obj_tentry *tent;
588 struct table_config *tc;
589 struct table_algo *ta;
590 struct table_info *kti;
591 struct namedobj_instance *ni;
595 /* Check minimum header size */
596 sz = sizeof(*oh) + sizeof(*tent);
597 if (sd->valsize != sz)
600 oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
601 tent = (ipfw_obj_tentry *)(oh + 1);
603 /* Basic length checks for TLVs */
604 if (oh->ntlv.head.length != sizeof(oh->ntlv))
607 objheader_to_ti(oh, &ti);
608 ti.type = oh->ntlv.type;
612 ni = CHAIN_TO_NI(ch);
615 * Find existing table and check its type .
618 if ((tc = find_table(ni, &ti)) == NULL) {
623 /* check table type */
624 if (tc->no.type != ti.type) {
629 kti = KIDX_TO_TI(ch, tc->no.kidx);
632 if (ta->find_tentry == NULL)
635 error = ta->find_tentry(tc->astate, kti, tent);
643 ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
644 struct sockopt_data *sd)
647 struct _ipfw_obj_header *oh;
650 if (sd->valsize != sizeof(*oh))
653 oh = (struct _ipfw_obj_header *)op3;
654 objheader_to_ti(oh, &ti);
656 if (op3->opcode == IP_FW_TABLE_XDESTROY)
657 error = destroy_table(ch, &ti);
658 else if (op3->opcode == IP_FW_TABLE_XFLUSH)
659 error = flush_table(ch, &ti);
667 * Flushes all entries in given table.
668 * Data layout (v0)(current):
669 * Request: [ ip_fw3_opheader ]
671 * Returns 0 on success
674 flush_table(struct ip_fw_chain *ch, struct tid_info *ti)
676 struct namedobj_instance *ni;
677 struct table_config *tc;
678 struct table_algo *ta;
679 struct table_info ti_old, ti_new, *tablestate;
680 void *astate_old, *astate_new;
681 char algostate[64], *pstate;
687 * Stage 1: save table algoritm.
688 * Reference found table to ensure it won't disappear.
691 ni = CHAIN_TO_NI(ch);
692 if ((tc = find_table(ni, ti)) == NULL) {
698 /* Save statup algo parameters */
699 if (ta->print_config != NULL) {
700 ta->print_config(tc->astate, KIDX_TO_TI(ch, tc->no.kidx),
701 algostate, sizeof(algostate));
709 * Stage 2: allocate new table instance using same algo.
711 memset(&ti_new, 0, sizeof(struct table_info));
712 if ((error = ta->init(ch, &astate_new, &ti_new, pstate, tflags)) != 0) {
720 * Stage 3: swap old state pointers with newly-allocated ones.
725 ni = CHAIN_TO_NI(ch);
727 tablestate = (struct table_info *)ch->tablestate;
730 ti_old = tablestate[kidx];
731 tablestate[kidx] = ti_new;
734 astate_old = tc->astate;
735 tc->astate = astate_new;
743 * Stage 4: perform real flush.
745 ta->destroy(astate_old, &ti_old);
751 * Destroys table specified by @ti.
752 * Data layout (v0)(current):
753 * Request: [ ip_fw3_opheader ]
755 * Returns 0 on success
758 destroy_table(struct ip_fw_chain *ch, struct tid_info *ti)
760 struct namedobj_instance *ni;
761 struct table_config *tc;
765 ni = CHAIN_TO_NI(ch);
766 if ((tc = find_table(ni, ti)) == NULL) {
771 /* Do not permit destroying referenced tables */
772 if (tc->no.refcnt > 0) {
778 unlink_table(ch, tc);
782 if (ipfw_objhash_free_idx(ni, tc->no.kidx) != 0)
783 printf("Error unlinking kidx %d from table %s\n",
784 tc->no.kidx, tc->tablename);
788 free_table_config(ni, tc);
794 destroy_table_locked(struct namedobj_instance *ni, struct named_object *no,
798 unlink_table((struct ip_fw_chain *)arg, (struct table_config *)no);
799 if (ipfw_objhash_free_idx(ni, no->kidx) != 0)
800 printf("Error unlinking kidx %d from table %s\n",
802 free_table_config(ni, (struct table_config *)no);
806 ipfw_destroy_tables(struct ip_fw_chain *ch)
809 /* Remove all tables from working set */
812 ipfw_objhash_foreach(CHAIN_TO_NI(ch), destroy_table_locked, ch);
816 /* Free pointers itself */
817 free(ch->tablestate, M_IPFW);
819 ipfw_table_algo_destroy(ch);
821 ipfw_objhash_destroy(CHAIN_TO_NI(ch));
822 free(CHAIN_TO_TCFG(ch), M_IPFW);
826 ipfw_init_tables(struct ip_fw_chain *ch)
828 struct tables_config *tcfg;
830 /* Allocate pointers */
831 ch->tablestate = malloc(V_fw_tables_max * sizeof(struct table_info),
832 M_IPFW, M_WAITOK | M_ZERO);
834 tcfg = malloc(sizeof(struct tables_config), M_IPFW, M_WAITOK | M_ZERO);
835 tcfg->namehash = ipfw_objhash_create(V_fw_tables_max);
838 ipfw_table_algo_init(ch);
844 ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables)
846 unsigned int ntables_old, tbl;
847 struct namedobj_instance *ni;
848 void *new_idx, *old_tablestate, *tablestate;
849 struct table_info *ti;
850 struct table_config *tc;
853 /* Check new value for validity */
854 if (ntables > IPFW_TABLES_MAX)
855 ntables = IPFW_TABLES_MAX;
857 /* Allocate new pointers */
858 tablestate = malloc(ntables * sizeof(struct table_info),
859 M_IPFW, M_WAITOK | M_ZERO);
861 ipfw_objhash_bitmap_alloc(ntables, (void *)&new_idx, &new_blocks);
865 tbl = (ntables >= V_fw_tables_max) ? V_fw_tables_max : ntables;
866 ni = CHAIN_TO_NI(ch);
868 /* Temporary restrict decreasing max_tables */
869 if (ntables < V_fw_tables_max) {
872 * FIXME: Check if we really can shrink
878 /* Copy table info/indices */
879 memcpy(tablestate, ch->tablestate, sizeof(struct table_info) * tbl);
880 ipfw_objhash_bitmap_merge(ni, &new_idx, &new_blocks);
884 /* Change pointers */
885 old_tablestate = ch->tablestate;
886 ch->tablestate = tablestate;
887 ipfw_objhash_bitmap_swap(ni, &new_idx, &new_blocks);
889 ntables_old = V_fw_tables_max;
890 V_fw_tables_max = ntables;
894 /* Notify all consumers that their @ti pointer has changed */
895 ti = (struct table_info *)ch->tablestate;
896 for (i = 0; i < tbl; i++, ti++) {
897 if (ti->lookup == NULL)
899 tc = (struct table_config *)ipfw_objhash_lookup_kidx(ni, i);
900 if (tc == NULL || tc->ta->change_ti == NULL)
903 tc->ta->change_ti(tc->astate, ti);
908 /* Free old pointers */
909 free(old_tablestate, M_IPFW);
910 ipfw_objhash_bitmap_free(new_idx, new_blocks);
916 ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
919 struct table_info *ti;
921 ti = &(((struct table_info *)ch->tablestate)[tbl]);
923 return (ti->lookup(ti, &addr, sizeof(in_addr_t), val));
927 ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen,
928 void *paddr, uint32_t *val)
930 struct table_info *ti;
932 ti = &(((struct table_info *)ch->tablestate)[tbl]);
934 return (ti->lookup(ti, paddr, plen, val));
938 * Info/List/dump support for tables.
943 * High-level 'get' cmds sysctl handlers
947 * Get buffer size needed to list info for all tables.
948 * Data layout (v0)(current):
949 * Request: [ empty ], size = sizeof(ipfw_obj_lheader)
950 * Reply: [ ipfw_obj_lheader ]
952 * Returns 0 on success
955 ipfw_listsize_tables(struct ip_fw_chain *ch, struct sockopt_data *sd)
957 struct _ipfw_obj_lheader *olh;
959 olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
963 olh->size = sizeof(*olh); /* Make export_table store needed size */
966 export_tables(ch, olh, sd);
973 * Lists all tables currently available in kernel.
974 * Data layout (v0)(current):
975 * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
976 * Reply: [ ipfw_obj_lheader ipfw_xtable_info x N ]
978 * Returns 0 on success
981 ipfw_list_tables(struct ip_fw_chain *ch, struct sockopt_data *sd)
983 struct _ipfw_obj_lheader *olh;
986 olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
989 if (sd->valsize < olh->size)
993 error = export_tables(ch, olh, sd);
1000 * Store table info to buffer provided by @sd.
1001 * Data layout (v0)(current):
1002 * Request: [ ipfw_obj_header ipfw_xtable_info(empty)]
1003 * Reply: [ ipfw_obj_header ipfw_xtable_info ]
1005 * Returns 0 on success.
1008 ipfw_describe_table(struct ip_fw_chain *ch, struct sockopt_data *sd)
1010 struct _ipfw_obj_header *oh;
1011 struct table_config *tc;
1015 sz = sizeof(*oh) + sizeof(ipfw_xtable_info);
1016 oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
1020 objheader_to_ti(oh, &ti);
1023 if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
1024 IPFW_UH_RUNLOCK(ch);
1028 export_table_info(ch, tc, (ipfw_xtable_info *)(oh + 1));
1029 IPFW_UH_RUNLOCK(ch);
1035 struct table_info *ti;
1036 struct table_config *tc;
1037 struct sockopt_data *sd;
1041 ipfw_table_entry *ent;
1043 ipfw_obj_tentry tent;
1047 ipfw_dump_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
1048 struct sockopt_data *sd)
1052 switch (op3->version) {
1054 error = ipfw_dump_table_v0(ch, sd);
1057 error = ipfw_dump_table_v1(ch, sd);
1067 * Dumps all table data
1068 * Data layout (v1)(current):
1069 * Request: [ ipfw_obj_header ], size = ipfw_xtable_info.size
1070 * Reply: [ ipfw_obj_header ipfw_xtable_info ipfw_obj_tentry x N ]
1072 * Returns 0 on success
1075 ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt_data *sd)
1077 struct _ipfw_obj_header *oh;
1078 ipfw_xtable_info *i;
1080 struct table_config *tc;
1081 struct table_algo *ta;
1082 struct dump_args da;
1085 sz = sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
1086 oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
1090 i = (ipfw_xtable_info *)(oh + 1);
1091 objheader_to_ti(oh, &ti);
1094 if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
1095 IPFW_UH_RUNLOCK(ch);
1098 export_table_info(ch, tc, i);
1101 if (sd->valsize < sz + tc->count * sizeof(ipfw_obj_tentry)) {
1104 * Submitted buffer size is not enough.
1105 * WE've already filled in @i structure with
1106 * relevant table info including size, so we
1107 * can return. Buffer will be flushed automatically.
1109 IPFW_UH_RUNLOCK(ch);
1114 * Do the actual dump in eXtended format
1116 memset(&da, 0, sizeof(da));
1117 da.ti = KIDX_TO_TI(ch, tc->no.kidx);
1123 ta->foreach(tc->astate, da.ti, dump_table_tentry, &da);
1124 IPFW_UH_RUNLOCK(ch);
1130 * Dumps all table data
1131 * Data layout (version 0)(legacy):
1132 * Request: [ ipfw_xtable ], size = IP_FW_TABLE_XGETSIZE()
1133 * Reply: [ ipfw_xtable ipfw_table_xentry x N ]
1135 * Returns 0 on success
1138 ipfw_dump_table_v0(struct ip_fw_chain *ch, struct sockopt_data *sd)
1142 struct table_config *tc;
1143 struct table_algo *ta;
1144 struct dump_args da;
1147 xtbl = (ipfw_xtable *)ipfw_get_sopt_header(sd, sizeof(ipfw_xtable));
1151 memset(&ti, 0, sizeof(ti));
1152 ti.uidx = xtbl->tbl;
1155 if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
1156 IPFW_UH_RUNLOCK(ch);
1159 sz = tc->count * sizeof(ipfw_table_xentry) + sizeof(ipfw_xtable);
1161 xtbl->cnt = tc->count;
1163 xtbl->type = tc->no.type;
1164 xtbl->tbl = ti.uidx;
1166 if (sd->valsize < sz) {
1169 * Submitted buffer size is not enough.
1170 * WE've already filled in @i structure with
1171 * relevant table info including size, so we
1172 * can return. Buffer will be flushed automatically.
1174 IPFW_UH_RUNLOCK(ch);
1178 /* Do the actual dump in eXtended format */
1179 memset(&da, 0, sizeof(da));
1180 da.ti = KIDX_TO_TI(ch, tc->no.kidx);
1186 ta->foreach(tc->astate, da.ti, dump_table_xentry, &da);
1187 IPFW_UH_RUNLOCK(ch);
1193 * Creates new table.
1194 * Data layout (v0)(current):
1195 * Request: [ ipfw_obj_header ipfw_xtable_info ]
1197 * Returns 0 on success
1200 ipfw_create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
1201 struct sockopt_data *sd)
1203 struct _ipfw_obj_header *oh;
1204 ipfw_xtable_info *i;
1205 char *tname, *aname;
1207 struct namedobj_instance *ni;
1208 struct table_config *tc;
1210 if (sd->valsize != sizeof(*oh) + sizeof(ipfw_xtable_info))
1213 oh = (struct _ipfw_obj_header *)sd->kbuf;
1214 i = (ipfw_xtable_info *)(oh + 1);
1217 * Verify user-supplied strings.
1218 * Check for null-terminated/zero-length strings/
1220 tname = oh->ntlv.name;
1221 aname = i->algoname;
1222 if (ipfw_check_table_name(tname) != 0 ||
1223 strnlen(aname, sizeof(i->algoname)) == sizeof(i->algoname))
1226 if (aname[0] == '\0') {
1227 /* Use default algorithm */
1231 objheader_to_ti(oh, &ti);
1234 ni = CHAIN_TO_NI(ch);
1237 if ((tc = find_table(ni, &ti)) != NULL) {
1238 IPFW_UH_RUNLOCK(ch);
1241 IPFW_UH_RUNLOCK(ch);
1243 return (create_table_internal(ch, &ti, aname, i));
1247 * Creates new table based on @ti and @aname.
1249 * Relies on table name checking inside find_name_tlv()
1250 * Assume @aname to be checked and valid.
1252 * Returns 0 on success.
1255 create_table_internal(struct ip_fw_chain *ch, struct tid_info *ti,
1256 char *aname, ipfw_xtable_info *i)
1258 struct namedobj_instance *ni;
1259 struct table_config *tc;
1260 struct table_algo *ta;
1263 ni = CHAIN_TO_NI(ch);
1265 ta = find_table_algo(CHAIN_TO_TCFG(ch), ti, aname);
1269 tc = alloc_table_config(ch, ti, ta, aname, i->tflags, i->vtype);
1273 tc->limit = i->limit;
1277 /* Check if table has been already created */
1278 if (find_table(ni, ti) != NULL) {
1279 IPFW_UH_WUNLOCK(ch);
1280 free_table_config(ni, tc);
1284 if (ipfw_objhash_alloc_idx(ni, &kidx) != 0) {
1285 IPFW_UH_WUNLOCK(ch);
1286 printf("Unable to allocate table index."
1287 " Consider increasing net.inet.ip.fw.tables_max");
1288 free_table_config(ni, tc);
1298 IPFW_UH_WUNLOCK(ch);
1304 objheader_to_ti(struct _ipfw_obj_header *oh, struct tid_info *ti)
1307 memset(ti, 0, sizeof(struct tid_info));
1308 ti->set = oh->ntlv.set;
1310 ti->tlvs = &oh->ntlv;
1311 ti->tlen = oh->ntlv.head.length;
1315 ipfw_export_table_ntlv(struct ip_fw_chain *ch, uint16_t kidx,
1316 struct sockopt_data *sd)
1318 struct namedobj_instance *ni;
1319 struct named_object *no;
1320 ipfw_obj_ntlv *ntlv;
1322 ni = CHAIN_TO_NI(ch);
1324 no = ipfw_objhash_lookup_kidx(ni, kidx);
1325 KASSERT(no != NULL, ("invalid table kidx passed"));
1327 ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv));
1331 ntlv->head.type = IPFW_TLV_TBL_NAME;
1332 ntlv->head.length = sizeof(*ntlv);
1333 ntlv->idx = no->kidx;
1334 strlcpy(ntlv->name, no->name, sizeof(ntlv->name));
1340 export_table_info(struct ip_fw_chain *ch, struct table_config *tc,
1341 ipfw_xtable_info *i)
1343 struct table_info *ti;
1344 struct table_algo *ta;
1346 i->type = tc->no.type;
1347 i->tflags = tc->tflags;
1348 i->vtype = tc->vtype;
1349 i->set = tc->no.set;
1350 i->kidx = tc->no.kidx;
1351 i->refcnt = tc->no.refcnt;
1352 i->count = tc->count;
1353 i->limit = tc->limit;
1354 i->size = tc->count * sizeof(ipfw_obj_tentry);
1355 i->size += sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
1356 strlcpy(i->tablename, tc->tablename, sizeof(i->tablename));
1357 ti = KIDX_TO_TI(ch, tc->no.kidx);
1359 if (ta->print_config != NULL) {
1360 /* Use algo function to print table config to string */
1361 ta->print_config(tc->astate, ti, i->algoname,
1362 sizeof(i->algoname));
1364 strlcpy(i->algoname, ta->name, sizeof(i->algoname));
1365 /* Dump algo-specific data, if possible */
1366 if (ta->dump_tinfo != NULL) {
1367 ta->dump_tinfo(tc->astate, ti, &i->ta_info);
1368 i->ta_info.flags |= IPFW_TATFLAGS_DATA;
1372 struct dump_table_args {
1373 struct ip_fw_chain *ch;
1374 struct sockopt_data *sd;
1378 export_table_internal(struct namedobj_instance *ni, struct named_object *no,
1381 ipfw_xtable_info *i;
1382 struct dump_table_args *dta;
1384 dta = (struct dump_table_args *)arg;
1386 i = (ipfw_xtable_info *)ipfw_get_sopt_space(dta->sd, sizeof(*i));
1387 KASSERT(i != 0, ("previously checked buffer is not enough"));
1389 export_table_info(dta->ch, (struct table_config *)no, i);
1393 * Export all tables as ipfw_xtable_info structures to
1394 * storage provided by @sd.
1395 * Returns 0 on success.
1398 export_tables(struct ip_fw_chain *ch, ipfw_obj_lheader *olh,
1399 struct sockopt_data *sd)
1403 struct dump_table_args dta;
1405 count = ipfw_objhash_count(CHAIN_TO_NI(ch));
1406 size = count * sizeof(ipfw_xtable_info) + sizeof(ipfw_obj_lheader);
1408 /* Fill in header regadless of buffer size */
1410 olh->objsize = sizeof(ipfw_xtable_info);
1412 if (size > olh->size) {
1422 ipfw_objhash_foreach(CHAIN_TO_NI(ch), export_table_internal, &dta);
1428 * Legacy IP_FW_TABLE_GETSIZE handler
1431 ipfw_count_table(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t *cnt)
1433 struct table_config *tc;
1435 if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL)
1443 * Legacy IP_FW_TABLE_XGETSIZE handler
1446 ipfw_count_xtable(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t *cnt)
1448 struct table_config *tc;
1450 if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL) {
1452 return (0); /* 'table all list' requires success */
1454 *cnt = tc->count * sizeof(ipfw_table_xentry);
1456 *cnt += sizeof(ipfw_xtable);
1461 dump_table_entry(void *e, void *arg)
1463 struct dump_args *da;
1464 struct table_config *tc;
1465 struct table_algo *ta;
1466 ipfw_table_entry *ent;
1469 da = (struct dump_args *)arg;
1474 /* Out of memory, returning */
1475 if (da->cnt == da->size)
1478 ent->tbl = da->uidx;
1481 error = ta->dump_tentry(tc->astate, da->ti, e, &da->tent);
1485 ent->addr = da->tent.k.addr.s_addr;
1486 ent->masklen = da->tent.masklen;
1487 ent->value = da->tent.value;
1493 * Dumps table in pre-8.1 legacy format.
1496 ipfw_dump_table_legacy(struct ip_fw_chain *ch, struct tid_info *ti,
1499 struct table_config *tc;
1500 struct table_algo *ta;
1501 struct dump_args da;
1505 if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL)
1506 return (0); /* XXX: We should return ESRCH */
1510 /* This dump format supports IPv4 only */
1511 if (tc->no.type != IPFW_TABLE_CIDR)
1514 memset(&da, 0, sizeof(da));
1515 da.ti = KIDX_TO_TI(ch, tc->no.kidx);
1517 da.ent = &tbl->ent[0];
1518 da.size = tbl->size;
1521 ta->foreach(tc->astate, da.ti, dump_table_entry, &da);
1528 * Dumps table entry in eXtended format (v1)(current).
1531 dump_table_tentry(void *e, void *arg)
1533 struct dump_args *da;
1534 struct table_config *tc;
1535 struct table_algo *ta;
1536 ipfw_obj_tentry *tent;
1538 da = (struct dump_args *)arg;
1543 tent = (ipfw_obj_tentry *)ipfw_get_sopt_space(da->sd, sizeof(*tent));
1544 /* Out of memory, returning */
1549 tent->head.length = sizeof(ipfw_obj_tentry);
1550 tent->idx = da->uidx;
1552 return (ta->dump_tentry(tc->astate, da->ti, e, tent));
1556 * Dumps table entry in eXtended format (v0).
1559 dump_table_xentry(void *e, void *arg)
1561 struct dump_args *da;
1562 struct table_config *tc;
1563 struct table_algo *ta;
1564 ipfw_table_xentry *xent;
1565 ipfw_obj_tentry *tent;
1568 da = (struct dump_args *)arg;
1573 xent = (ipfw_table_xentry *)ipfw_get_sopt_space(da->sd, sizeof(*xent));
1574 /* Out of memory, returning */
1577 xent->len = sizeof(ipfw_table_xentry);
1578 xent->tbl = da->uidx;
1580 memset(&da->tent, 0, sizeof(da->tent));
1582 error = ta->dump_tentry(tc->astate, da->ti, e, tent);
1586 /* Convert current format to previous one */
1587 xent->masklen = tent->masklen;
1588 xent->value = tent->value;
1589 /* Apply some hacks */
1590 if (tc->no.type == IPFW_TABLE_CIDR && tent->subtype == AF_INET) {
1591 xent->k.addr6.s6_addr32[3] = tent->k.addr.s_addr;
1592 xent->flags = IPFW_TCF_INET;
1594 memcpy(&xent->k, &tent->k, sizeof(xent->k));
1604 * Finds algoritm by index, table type or supplied name
1606 static struct table_algo *
1607 find_table_algo(struct tables_config *tcfg, struct tid_info *ti, char *name)
1610 struct table_algo *ta;
1612 if (ti->type > IPFW_TABLE_MAXTYPE)
1615 /* Search by index */
1616 if (ti->atype != 0) {
1617 if (ti->atype > tcfg->algo_count)
1619 return (tcfg->algo[ti->atype]);
1622 /* Search by name if supplied */
1624 /* TODO: better search */
1625 for (i = 1; i <= tcfg->algo_count; i++) {
1629 * One can supply additional algorithm
1630 * parameters so we compare only the first word
1632 * 'hash_cidr hsize=32'
1636 l = strlen(ta->name);
1637 if (strncmp(name, ta->name, l) == 0) {
1638 if (name[l] == '\0' || name[l] == ' ')
1646 /* Return default algorithm for given type if set */
1647 return (tcfg->def_algo[ti->type]);
1651 * Register new table algo @ta.
1652 * Stores algo id iside @idx.<F2>
1654 * Returns 0 on success.
1657 ipfw_add_table_algo(struct ip_fw_chain *ch, struct table_algo *ta, size_t size,
1660 struct tables_config *tcfg;
1661 struct table_algo *ta_new;
1664 if (size > sizeof(struct table_algo))
1667 /* Check for the required on-stack size for add/del */
1668 sz = roundup2(ta->ta_buf_size, sizeof(void *));
1672 KASSERT(ta->type >= IPFW_TABLE_MAXTYPE,("Increase IPFW_TABLE_MAXTYPE"));
1674 ta_new = malloc(sizeof(struct table_algo), M_IPFW, M_WAITOK | M_ZERO);
1675 memcpy(ta_new, ta, size);
1677 tcfg = CHAIN_TO_TCFG(ch);
1679 KASSERT(tcfg->algo_count < 255, ("Increase algo array size"));
1681 tcfg->algo[++tcfg->algo_count] = ta_new;
1682 ta_new->idx = tcfg->algo_count;
1684 /* Set algorithm as default one for given type */
1685 if ((ta_new->flags & TA_FLAG_DEFAULT) != 0 &&
1686 tcfg->def_algo[ta_new->type] == NULL)
1687 tcfg->def_algo[ta_new->type] = ta_new;
1695 * Unregisters table algo using @idx as id.
1698 ipfw_del_table_algo(struct ip_fw_chain *ch, int idx)
1700 struct tables_config *tcfg;
1701 struct table_algo *ta;
1703 tcfg = CHAIN_TO_TCFG(ch);
1705 KASSERT(idx <= tcfg->algo_count, ("algo idx %d out of range 1..%d",
1706 idx, tcfg->algo_count));
1708 ta = tcfg->algo[idx];
1709 KASSERT(ta != NULL, ("algo idx %d is NULL", idx));
1711 if (tcfg->def_algo[ta->type] == ta)
1712 tcfg->def_algo[ta->type] = NULL;
1718 * Lists all table algorithms currently available.
1719 * Data layout (v0)(current):
1720 * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
1721 * Reply: [ ipfw_obj_lheader ipfw_ta_info x N ]
1723 * Returns 0 on success
1726 ipfw_list_table_algo(struct ip_fw_chain *ch, struct sockopt_data *sd)
1728 struct _ipfw_obj_lheader *olh;
1729 struct tables_config *tcfg;
1731 struct table_algo *ta;
1732 uint32_t count, n, size;
1734 olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
1737 if (sd->valsize < olh->size)
1741 tcfg = CHAIN_TO_TCFG(ch);
1742 count = tcfg->algo_count;
1743 size = count * sizeof(ipfw_ta_info) + sizeof(ipfw_obj_lheader);
1745 /* Fill in header regadless of buffer size */
1747 olh->objsize = sizeof(ipfw_ta_info);
1749 if (size > olh->size) {
1751 IPFW_UH_RUNLOCK(ch);
1756 for (n = 1; n <= count; n++) {
1757 i = (ipfw_ta_info *)ipfw_get_sopt_space(sd, sizeof(*i));
1758 KASSERT(i != 0, ("previously checked buffer is not enough"));
1760 strlcpy(i->algoname, ta->name, sizeof(i->algoname));
1762 i->refcnt = ta->refcnt;
1765 IPFW_UH_RUNLOCK(ch);
1772 * Tables rewriting code
1777 * Determine table number and lookup type for @cmd.
1778 * Fill @tbl and @type with appropriate values.
1779 * Returns 0 for relevant opcodes, 1 otherwise.
1782 classify_table_opcode(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype)
1784 ipfw_insn_if *cmdif;
1790 switch (cmd->opcode) {
1791 case O_IP_SRC_LOOKUP:
1792 case O_IP_DST_LOOKUP:
1793 /* Basic IPv4/IPv6 or u32 lookups */
1795 /* Assume CIDR by default */
1796 *ptype = IPFW_TABLE_CIDR;
1799 if (F_LEN(cmd) > F_INSN_SIZE(ipfw_insn_u32)) {
1801 * generic lookup. The key must be
1802 * in 32bit big-endian format.
1804 v = ((ipfw_insn_u32 *)cmd)->d[1];
1813 *ptype = IPFW_TABLE_NUMBER;
1817 *ptype = IPFW_TABLE_NUMBER;
1821 *ptype = IPFW_TABLE_NUMBER;
1825 *ptype = IPFW_TABLE_NUMBER;
1833 /* Interface table, possibly */
1834 cmdif = (ipfw_insn_if *)cmd;
1835 if (cmdif->name[0] != '\1')
1838 *ptype = IPFW_TABLE_INTERFACE;
1839 *puidx = cmdif->p.glob;
1842 case O_IP_FLOW_LOOKUP:
1844 *ptype = IPFW_TABLE_FLOW;
1853 * Sets new table value for given opcode.
1854 * Assume the same opcodes as classify_table_opcode()
1857 update_table_opcode(ipfw_insn *cmd, uint16_t idx)
1859 ipfw_insn_if *cmdif;
1861 switch (cmd->opcode) {
1862 case O_IP_SRC_LOOKUP:
1863 case O_IP_DST_LOOKUP:
1864 /* Basic IPv4/IPv6 or u32 lookups */
1870 /* Interface table, possibly */
1871 cmdif = (ipfw_insn_if *)cmd;
1872 cmdif->p.glob = idx;
1874 case O_IP_FLOW_LOOKUP:
1881 * Checks table name for validity.
1882 * Enforce basic length checks, the rest
1883 * should be done in userland.
1885 * Returns 0 if name is considered valid.
1888 ipfw_check_table_name(char *name)
1891 ipfw_obj_ntlv *ntlv = NULL;
1893 nsize = sizeof(ntlv->name);
1895 if (strnlen(name, nsize) == nsize)
1898 if (name[0] == '\0')
1902 * TODO: do some more complicated checks
1909 * Find tablename TLV by @uid.
1910 * Check @tlvs for valid data inside.
1912 * Returns pointer to found TLV or NULL.
1914 static ipfw_obj_ntlv *
1915 find_name_tlv(void *tlvs, int len, uint16_t uidx)
1917 ipfw_obj_ntlv *ntlv;
1921 pa = (uintptr_t)tlvs;
1924 for (; pa < pe; pa += l) {
1925 ntlv = (ipfw_obj_ntlv *)pa;
1926 l = ntlv->head.length;
1928 if (l != sizeof(*ntlv))
1931 if (ntlv->head.type != IPFW_TLV_TBL_NAME)
1934 if (ntlv->idx != uidx)
1937 if (ipfw_check_table_name(ntlv->name) != 0)
1947 * Finds table config based on either legacy index
1949 * Note @ti structure contains unchecked data from userland.
1951 * Returns pointer to table_config or NULL.
1953 static struct table_config *
1954 find_table(struct namedobj_instance *ni, struct tid_info *ti)
1956 char *name, bname[16];
1957 struct named_object *no;
1958 ipfw_obj_ntlv *ntlv;
1961 if (ti->tlvs != NULL) {
1962 ntlv = find_name_tlv(ti->tlvs, ti->tlen, ti->uidx);
1968 snprintf(bname, sizeof(bname), "%d", ti->uidx);
1973 no = ipfw_objhash_lookup_name(ni, set, name);
1975 return ((struct table_config *)no);
1978 static struct table_config *
1979 alloc_table_config(struct ip_fw_chain *ch, struct tid_info *ti,
1980 struct table_algo *ta, char *aname, uint8_t tflags, uint8_t vtype)
1982 char *name, bname[16];
1983 struct table_config *tc;
1985 ipfw_obj_ntlv *ntlv;
1988 if (ti->tlvs != NULL) {
1989 ntlv = find_name_tlv(ti->tlvs, ti->tlen, ti->uidx);
1995 snprintf(bname, sizeof(bname), "%d", ti->uidx);
2000 tc = malloc(sizeof(struct table_config), M_IPFW, M_WAITOK | M_ZERO);
2001 tc->no.name = tc->tablename;
2002 tc->no.type = ti->type;
2004 tc->tflags = tflags;
2006 strlcpy(tc->tablename, name, sizeof(tc->tablename));
2007 /* Set default value type to u32 for compability reasons */
2009 tc->vtype = IPFW_VTYPE_U32;
2013 if (ti->tlvs == NULL) {
2015 tc->no.uidx = ti->uidx;
2018 /* Preallocate data structures for new tables */
2019 error = ta->init(ch, &tc->astate, &tc->ti, aname, tflags);
2029 free_table_config(struct namedobj_instance *ni, struct table_config *tc)
2032 if (tc->linked == 0)
2033 tc->ta->destroy(tc->astate, &tc->ti);
2039 * Links @tc to @chain table named instance.
2040 * Sets appropriate type/states in @chain table info.
2043 link_table(struct ip_fw_chain *ch, struct table_config *tc)
2045 struct namedobj_instance *ni;
2046 struct table_info *ti;
2049 IPFW_UH_WLOCK_ASSERT(ch);
2050 IPFW_WLOCK_ASSERT(ch);
2052 ni = CHAIN_TO_NI(ch);
2055 ipfw_objhash_add(ni, &tc->no);
2057 ti = KIDX_TO_TI(ch, kidx);
2060 /* Notify algo on real @ti address */
2061 if (tc->ta->change_ti != NULL)
2062 tc->ta->change_ti(tc->astate, ti);
2069 * Unlinks @tc from @chain table named instance.
2070 * Zeroes states in @chain and stores them in @tc.
2073 unlink_table(struct ip_fw_chain *ch, struct table_config *tc)
2075 struct namedobj_instance *ni;
2076 struct table_info *ti;
2079 IPFW_UH_WLOCK_ASSERT(ch);
2080 IPFW_WLOCK_ASSERT(ch);
2082 ni = CHAIN_TO_NI(ch);
2085 /* Clear state. @ti copy is already saved inside @tc */
2086 ipfw_objhash_del(ni, &tc->no);
2087 ti = KIDX_TO_TI(ch, kidx);
2088 memset(ti, 0, sizeof(struct table_info));
2092 /* Notify algo on real @ti address */
2093 if (tc->ta->change_ti != NULL)
2094 tc->ta->change_ti(tc->astate, NULL);
2098 * Finds named object by @uidx number.
2099 * Refs found object, allocate new index for non-existing object.
2100 * Fills in @oib with userland/kernel indexes.
2101 * First free oidx pointer is saved back in @oib.
2103 * Returns 0 on success.
2106 bind_table_rule(struct ip_fw_chain *ch, struct ip_fw *rule,
2107 struct rule_check_info *ci, struct obj_idx **oib, struct tid_info *ti)
2109 struct table_config *tc;
2110 struct namedobj_instance *ni;
2111 struct named_object *no;
2112 int error, l, cmdlen;
2114 struct obj_idx *pidx, *p;
2123 ni = CHAIN_TO_NI(ch);
2125 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
2126 cmdlen = F_LEN(cmd);
2128 if (classify_table_opcode(cmd, &ti->uidx, &ti->type) != 0)
2131 pidx->uidx = ti->uidx;
2132 pidx->type = ti->type;
2134 if ((tc = find_table(ni, ti)) != NULL) {
2135 if (tc->no.type != ti->type) {
2136 /* Incompatible types */
2141 /* Reference found table and save kidx */
2143 pidx->kidx = tc->no.kidx;
2148 /* Table not found. Allocate new index and save for later */
2149 if (ipfw_objhash_alloc_idx(ni, &pidx->kidx) != 0) {
2150 printf("Unable to allocate table %s index in set %u."
2151 " Consider increasing net.inet.ip.fw.tables_max",
2163 /* Unref everything we have already done */
2164 for (p = *oib; p < pidx; p++) {
2166 ipfw_objhash_free_idx(ni, p->kidx);
2170 /* Find & unref by existing idx */
2171 no = ipfw_objhash_lookup_kidx(ni, p->kidx);
2172 KASSERT(no != NULL, ("Ref'd table %d disappeared",
2178 IPFW_UH_WUNLOCK(ch);
2186 * Compatibility function for old ipfw(8) binaries.
2187 * Rewrites table kernel indices with userland ones.
2188 * Works for \d+ talbes only (e.g. for tables, converted
2189 * from old numbered system calls).
2191 * Returns 0 on success.
2192 * Raises error on any other tables.
2195 ipfw_rewrite_table_kidx(struct ip_fw_chain *chain, struct ip_fw_rule0 *rule)
2197 int cmdlen, error, l;
2199 uint16_t kidx, uidx;
2201 struct named_object *no;
2202 struct namedobj_instance *ni;
2204 ni = CHAIN_TO_NI(chain);
2210 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
2211 cmdlen = F_LEN(cmd);
2213 if (classify_table_opcode(cmd, &kidx, &type) != 0)
2216 if ((no = ipfw_objhash_lookup_kidx(ni, kidx)) == NULL)
2220 if (no->compat == 0) {
2223 * We are called via legacy opcode.
2224 * Save error and show table as fake number
2225 * not to make ipfw(8) hang.
2231 update_table_opcode(cmd, uidx);
2238 * Sets every table kidx in @bmask which is used in rule @rule.
2240 * Returns number of newly-referenced tables.
2243 ipfw_mark_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule,
2246 int cmdlen, l, count;
2255 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
2256 cmdlen = F_LEN(cmd);
2258 if (classify_table_opcode(cmd, &kidx, &type) != 0)
2261 if ((bmask[kidx / 32] & (1 << (kidx % 32))) == 0)
2264 bmask[kidx / 32] |= 1 << (kidx % 32);
2273 * Checks is opcode is referencing table of appropriate type.
2274 * Adds reference count for found table if true.
2275 * Rewrites user-supplied opcode values with kernel ones.
2277 * Returns 0 on success and appropriate error code otherwise.
2280 ipfw_rewrite_table_uidx(struct ip_fw_chain *chain,
2281 struct rule_check_info *ci)
2283 int cmdlen, error, ftype, l;
2287 struct table_config *tc;
2288 struct table_algo *ta;
2289 struct namedobj_instance *ni;
2290 struct named_object *no, *no_n, *no_tmp;
2291 struct obj_idx *p, *pidx_first, *pidx_last;
2292 struct namedobjects_head nh;
2295 ni = CHAIN_TO_NI(chain);
2297 /* Prepare queue to store configs */
2301 * Prepare an array for storing opcode indices.
2302 * Use stack allocation by default.
2304 if (ci->table_opcodes <= (sizeof(ci->obuf)/sizeof(ci->obuf[0]))) {
2306 pidx_first = ci->obuf;
2308 pidx_first = malloc(ci->table_opcodes * sizeof(struct obj_idx),
2309 M_IPFW, M_WAITOK | M_ZERO);
2311 pidx_last = pidx_first;
2317 memset(&ti, 0, sizeof(ti));
2320 * Use default set for looking up tables (old way) or
2321 * use set rule is assigned to (new way).
2323 ti.set = (V_fw_tables_sets != 0) ? ci->krule->set : 0;
2324 if (ci->ctlv != NULL) {
2325 ti.tlvs = (void *)(ci->ctlv + 1);
2326 ti.tlen = ci->ctlv->head.length - sizeof(ipfw_obj_ctlv);
2330 * Stage 1: reference existing tables, determine number
2331 * of tables we need to allocate and allocate indexes for each.
2333 error = bind_table_rule(chain, ci->krule, ci, &pidx_last, &ti);
2336 if (pidx_first != ci->obuf)
2337 free(pidx_first, M_IPFW);
2343 * Stage 2: allocate table configs for every non-existent table
2346 if (ci->new_tables > 0) {
2347 for (p = pidx_first; p < pidx_last; p++) {
2355 ta = find_table_algo(CHAIN_TO_TCFG(chain), &ti, NULL);
2360 tc = alloc_table_config(chain, &ti, ta, NULL, 0,
2368 tc->no.kidx = p->kidx;
2372 TAILQ_INSERT_TAIL(&nh, &tc->no, nn_next);
2376 * Stage 2.1: Check if we're going to create 2 tables
2377 * with the same name, but different table types.
2379 TAILQ_FOREACH(no, &nh, nn_next) {
2380 TAILQ_FOREACH(no_tmp, &nh, nn_next) {
2381 if (ipfw_objhash_same_name(ni, no, no_tmp) == 0)
2383 if (no->type != no_tmp->type) {
2391 IPFW_UH_WLOCK(chain);
2393 if (ci->new_tables > 0) {
2395 * Stage 3: link & reference new table configs
2400 * Step 3.1: Check if some tables we need to create have been
2401 * already created with different table type.
2405 TAILQ_FOREACH_SAFE(no, &nh, nn_next, no_tmp) {
2406 no_n = ipfw_objhash_lookup_name(ni, no->set, no->name);
2410 if (no_n->type != no->type) {
2419 * Someone has allocated table with different table type.
2420 * We have to rollback everything.
2422 IPFW_UH_WUNLOCK(chain);
2427 * Attach new tables.
2428 * We need to set table pointers for each new table,
2429 * so we have to acquire main WLOCK.
2432 TAILQ_FOREACH_SAFE(no, &nh, nn_next, no_tmp) {
2433 no_n = ipfw_objhash_lookup_name(ni, no->set, no->name);
2436 /* New table. Attach to runtime hash */
2437 TAILQ_REMOVE(&nh, no, nn_next);
2438 link_table(chain, (struct table_config *)no);
2443 * Newly-allocated table with the same type.
2444 * Reference it and update out @pidx array
2448 /* Keep oib array in sync: update kidx */
2449 for (p = pidx_first; p < pidx_last; p++) {
2450 if (p->kidx != no->kidx)
2453 p->kidx = no_n->kidx;
2457 IPFW_WUNLOCK(chain);
2460 /* Perform rule rewrite */
2461 l = ci->krule->cmd_len;
2462 cmd = ci->krule->cmd;
2465 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
2466 cmdlen = F_LEN(cmd);
2468 if (classify_table_opcode(cmd, &uidx, &type) != 0)
2470 update_table_opcode(cmd, p->kidx);
2474 IPFW_UH_WUNLOCK(chain);
2479 * Stage 4: free resources
2482 if (!TAILQ_EMPTY(&nh)) {
2483 /* Free indexes first */
2484 IPFW_UH_WLOCK(chain);
2485 TAILQ_FOREACH_SAFE(no, &nh, nn_next, no_tmp) {
2486 ipfw_objhash_free_idx(ni, no->kidx);
2488 IPFW_UH_WUNLOCK(chain);
2490 TAILQ_FOREACH_SAFE(no, &nh, nn_next, no_tmp)
2491 free_table_config(ni, tc);
2494 if (pidx_first != ci->obuf)
2495 free(pidx_first, M_IPFW);
2501 * Remove references from every table used in @rule.
2504 ipfw_unbind_table_rule(struct ip_fw_chain *chain, struct ip_fw *rule)
2508 struct namedobj_instance *ni;
2509 struct named_object *no;
2513 ni = CHAIN_TO_NI(chain);
2518 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
2519 cmdlen = F_LEN(cmd);
2521 if (classify_table_opcode(cmd, &kidx, &type) != 0)
2524 no = ipfw_objhash_lookup_kidx(ni, kidx);
2526 KASSERT(no != NULL, ("table id %d not found", kidx));
2527 KASSERT(no->type == type, ("wrong type %d (%d) for table id %d",
2528 no->type, type, kidx));
2529 KASSERT(no->refcnt > 0, ("refcount for table %d is %d",
2538 * Removes table bindings for every rule in rule chain @head.
2541 ipfw_unbind_table_list(struct ip_fw_chain *chain, struct ip_fw *head)
2545 while ((rule = head) != NULL) {
2546 head = head->x_next;
2547 ipfw_unbind_table_rule(chain, rule);