From fd0869d54785422f077f7daa9c3e1838b215343f Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Thu, 14 Aug 2014 17:31:04 +0000 Subject: [PATCH] * Document internal commands. * Do not require/set default table type if algo name is specified. * Add TA_FLAG_READONLY option for algorithms. --- sbin/ipfw/ipfw.8 | 21 ++++++++ sbin/ipfw/tables.c | 10 ++-- sys/netpfil/ipfw/ip_fw_table.c | 80 +++++++++++++++++++---------- sys/netpfil/ipfw/ip_fw_table.h | 3 +- sys/netpfil/ipfw/ip_fw_table_algo.c | 10 ++-- 5 files changed, 88 insertions(+), 36 deletions(-) diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index 96476971d816..6584bdb37bea 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -113,6 +113,11 @@ in-kernel NAT. .Oc .Oc .Ar pathname +.Ss INTERNAL DIAGNOSTICS +.Nm +.Cm internal iflist +.Nm +.Cm internal talist .Sh DESCRIPTION The .Nm @@ -3181,6 +3186,22 @@ Controls whether bridged packets are passed to .Nm . Default is no. .El +.Sh INTERNAL DIAGNOSTICS +There are some commands that may be useful to understand current state +of certain subsystems inside kernel module. +These commands provide debugging output which may change without notice. +.Pp +Currently the following commands are available as +.Cm internal +sub-options: +.Bl -tag -width indent +.It Cm iflist +Lists all interface which are currently tracked by +.Nm +with their in-kernel status. +.It Cm talist +List all table lookup algorithms currently available. +.El .Sh EXAMPLES There are far too many possible uses of .Nm diff --git a/sbin/ipfw/tables.c b/sbin/ipfw/tables.c index b90b46f47680..db88f304c867 100644 --- a/sbin/ipfw/tables.c +++ b/sbin/ipfw/tables.c @@ -391,10 +391,6 @@ table_create(ipfw_obj_header *oh, int ac, char *av[]) sz = sizeof(tbuf); memset(&xi, 0, sizeof(xi)); - /* Set some defaults to preserve compability */ - xi.type = IPFW_TABLE_CIDR; - xi.vtype = IPFW_VTYPE_U32; - while (ac > 0) { tcmd = get_token(tablenewcmds, *av, "option"); ac--; av++; @@ -464,6 +460,12 @@ table_create(ipfw_obj_header *oh, int ac, char *av[]) } } + /* Set some defaults to preserve compability */ + if (xi.algoname[0] == '\0' && xi.type == 0) + xi.type = IPFW_TABLE_CIDR; + if (xi.vtype == 0) + xi.vtype = IPFW_VTYPE_U32; + if ((error = table_do_create(oh, &xi)) != 0) err(EX_OSERR, "Table creation failed"); } diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index 64250e672fe3..228e2b7d0d36 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -667,6 +667,9 @@ check_table_space(struct ip_fw_chain *ch, struct table_config *tc, error = 0; ta = tc->ta; + if (ta->need_modify == NULL) + return (0); + /* Acquire reference not to loose @tc between locks/unlocks */ tc->no.refcnt++; @@ -1051,6 +1054,11 @@ flush_table(struct ip_fw_chain *ch, struct tid_info *ti) return (ESRCH); } ta = tc->ta; + /* Do not flush readonly tables */ + if ((ta->flags & TA_FLAG_READONLY) != 0) { + IPFW_UH_WUNLOCK(ch); + return (EACCES); + } tc->no.refcnt++; /* Save startup algo parameters */ if (ta->print_config != NULL) { @@ -1206,6 +1214,12 @@ swap_tables(struct ip_fw_chain *ch, struct tid_info *a, return (EFBIG); } + /* Check if one of the tables is readonly */ + if (((tc_a->ta->flags | tc_b->ta->flags) & TA_FLAG_READONLY) != 0) { + IPFW_UH_WUNLOCK(ch); + return (EACCES); + } + /* Everything is fine, prepare to swap */ tablestate = (struct table_info *)ch->tablestate; ti = tablestate[tc_a->no.kidx]; @@ -1622,6 +1636,13 @@ ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3, IPFW_UH_WUNLOCK(ch); return (ESRCH); } + + /* Do not support any modifications for readonly tables */ + if ((tc->ta->flags & TA_FLAG_READONLY) != 0) { + IPFW_UH_WUNLOCK(ch); + return (EACCES); + } + if ((i->mflags & IPFW_TMFLAGS_FTYPE) != 0) tc->vftype = i->vftype; if ((i->mflags & IPFW_TMFLAGS_LIMIT) != 0) @@ -1720,7 +1741,10 @@ create_table_internal(struct ip_fw_chain *ch, struct tid_info *ti, tc->vftype = i->vftype; tc->limit = i->limit; - tc->locked = (i->flags & IPFW_TGFLAGS_LOCKED) != 0; + if (ta->flags & TA_FLAG_READONLY) + tc->locked = 1; + else + tc->locked = (i->flags & IPFW_TGFLAGS_LOCKED) != 0; IPFW_UH_WLOCK(ch); @@ -2311,32 +2335,36 @@ find_table_algo(struct tables_config *tcfg, struct tid_info *ti, char *name) return (tcfg->algo[ti->atype]); } - /* Search by name if supplied */ - if (name != NULL) { - /* TODO: better search */ - for (i = 1; i <= tcfg->algo_count; i++) { - ta = tcfg->algo[i]; - - /* - * One can supply additional algorithm - * parameters so we compare only the first word - * of supplied name: - * 'hash_cidr hsize=32' - * '^^^^^^^^^' - * - */ - l = strlen(ta->name); - if (strncmp(name, ta->name, l) == 0) { - if (name[l] == '\0' || name[l] == ' ') - return (ta); - } - } - - return (NULL); + if (name == NULL) { + /* Return default algorithm for given type if set */ + return (tcfg->def_algo[ti->type]); } - /* Return default algorithm for given type if set */ - return (tcfg->def_algo[ti->type]); + /* Search by name */ + /* TODO: better search */ + for (i = 1; i <= tcfg->algo_count; i++) { + ta = tcfg->algo[i]; + + /* + * One can supply additional algorithm + * parameters so we compare only the first word + * of supplied name: + * 'hash_cidr hsize=32' + * '^^^^^^^^^' + * + */ + l = strlen(ta->name); + if (strncmp(name, ta->name, l) != 0) + continue; + if (name[l] != '\0' && name[l] != ' ') + continue; + /* Check if we're requesting proper table type */ + if (ti->type != 0 && ti->type != ta->type) + return (NULL); + return (ta); + } + + return (NULL); } /* @@ -2704,7 +2732,7 @@ alloc_table_config(struct ip_fw_chain *ch, struct tid_info *ti, tc = malloc(sizeof(struct table_config), M_IPFW, M_WAITOK | M_ZERO); tc->no.name = tc->tablename; - tc->no.type = ti->type; + tc->no.type = ta->type; tc->no.set = set; tc->tflags = tflags; tc->ta = ta; diff --git a/sys/netpfil/ipfw/ip_fw_table.h b/sys/netpfil/ipfw/ip_fw_table.h index bcbffa838d85..eba54890fb53 100644 --- a/sys/netpfil/ipfw/ip_fw_table.h +++ b/sys/netpfil/ipfw/ip_fw_table.h @@ -132,7 +132,8 @@ struct table_algo { ta_print_config *print_config; ta_dump_tinfo *dump_tinfo; }; -#define TA_FLAG_DEFAULT 0x01 /* Algorithm is default for given type */ +#define TA_FLAG_DEFAULT 0x01 /* Algo is default for given type */ +#define TA_FLAG_READONLY 0x02 /* Algo does not support modifications*/ int ipfw_add_table_algo(struct ip_fw_chain *ch, struct table_algo *ta, size_t size, int *idx); diff --git a/sys/netpfil/ipfw/ip_fw_table_algo.c b/sys/netpfil/ipfw/ip_fw_table_algo.c index a2a5be7ebd0e..30b0343cff06 100644 --- a/sys/netpfil/ipfw/ip_fw_table_algo.c +++ b/sys/netpfil/ipfw/ip_fw_table_algo.c @@ -179,7 +179,7 @@ __FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 267384 2014-06- * -need_modify: checks if @ti has enough space to hold another @count items. * typedef int (ta_need_modify)(void *ta_state, struct table_info *ti, * uint32_t count, uint64_t *pflags); - * MANDATORY, locked (UH). (M_NOWAIT). Returns 0 if has. + * OPTIONAL, locked (UH). (M_NOWAIT). Returns 0 if has. * * Checks if given table has enough space to add @count items without * resize. Caller may use @pflags to store desired modification data. @@ -188,7 +188,7 @@ __FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 267384 2014-06- * * -prepare_mod: allocate structures for table modification. * typedef int (ta_prepare_mod)(void *ta_buf, uint64_t *pflags); - * MANDATORY, unlocked. (M_WAITOK). Returns 0 on success. + * OPTIONAL(need_modify), unlocked. (M_WAITOK). Returns 0 on success. * * Allocate all needed state for table modification. Caller * should use `struct mod_item` to store new state in @ta_buf. @@ -199,7 +199,7 @@ __FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 267384 2014-06- * -fill_mod: copy some data to new state/ * typedef int (ta_fill_mod)(void *ta_state, struct table_info *ti, * void *ta_buf, uint64_t *pflags); - * MANDATORY, locked (UH). (M_NOWAIT). Returns 0 on success. + * OPTIONAL(need_modify), locked (UH). (M_NOWAIT). Returns 0 on success. * * Copy as much data as we can to minimize changes under WLOCK. * For example, array can be merged inside this callback. @@ -209,7 +209,7 @@ __FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 267384 2014-06- * -modify: perform final modification. * typedef void (ta_modify)(void *ta_state, struct table_info *ti, * void *ta_buf, uint64_t pflags); - * MANDATORY, locked (UH+WLOCK). (M_NOWAIT). + * OPTIONAL(need_modify), locked (UH+WLOCK). (M_NOWAIT). * * Performs all changes necessary to switch to new structures. * * Caller should save old pointers to @ta_buf storage. @@ -218,7 +218,7 @@ __FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 267384 2014-06- * * -flush_mod: flush table modification state. * typedef void (ta_flush_mod)(void *ta_buf); - * MANDATORY, unlocked. (M_WAITOK). + * OPTIONAL(need_modify), unlocked. (M_WAITOK). * * Performs flush for the following: * - prepare_mod (modification was not necessary)