svn commit: r269276 - in projects/ipfw: sbin/ipfw sys/netinet sys/netpfil/ipfw

Alexander V. Chernikov melifaro at FreeBSD.org
Tue Jul 29 22:44:28 UTC 2014


Author: melifaro
Date: Tue Jul 29 22:44:26 2014
New Revision: 269276
URL: http://svnweb.freebsd.org/changeset/base/269276

Log:
  * Dump available table algorithms via "ipfw talist" cmd.
  
  Kernel changes:
  * Add type/refcount fields to table algo instances.
  * Add IP_FW_TABLES_ALIST opcode to export available algorihms to userland.
  
  Userland changes:
  * Fix cores on empty input inside "ipfw table" handler.
  * Add "ipfw talist" cmd to print availabled kernel algorithms.
  * Change "table info" output to reflect long algorithm config lines.

Modified:
  projects/ipfw/sbin/ipfw/ipfw2.h
  projects/ipfw/sbin/ipfw/main.c
  projects/ipfw/sbin/ipfw/tables.c
  projects/ipfw/sys/netinet/ip_fw.h
  projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
  projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
  projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h
  projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c

Modified: projects/ipfw/sbin/ipfw/ipfw2.h
==============================================================================
--- projects/ipfw/sbin/ipfw/ipfw2.h	Tue Jul 29 22:29:32 2014	(r269275)
+++ projects/ipfw/sbin/ipfw/ipfw2.h	Tue Jul 29 22:44:26 2014	(r269276)
@@ -297,6 +297,7 @@ void ipfw_flush(int force);
 void ipfw_zero(int ac, char *av[], int optname);
 void ipfw_list(int ac, char *av[], int show_counters);
 void ipfw_list_tifaces(void);
+void ipfw_list_ta(int ac, char *av[]);
 
 #ifdef PF
 /* altq.c */

Modified: projects/ipfw/sbin/ipfw/main.c
==============================================================================
--- projects/ipfw/sbin/ipfw/main.c	Tue Jul 29 22:29:32 2014	(r269275)
+++ projects/ipfw/sbin/ipfw/main.c	Tue Jul 29 22:44:26 2014	(r269276)
@@ -440,6 +440,8 @@ ipfw_main(int oldac, char **oldav)
 			ipfw_table_handler(ac, av);
 		else if (_substrcmp(*av, "iflist") == 0)
 			ipfw_list_tifaces();
+		else if (_substrcmp(*av, "talist") == 0)
+			ipfw_list_ta(ac, av);
 		else
 			errx(EX_USAGE, "bad command `%s'", *av);
 	}

Modified: projects/ipfw/sbin/ipfw/tables.c
==============================================================================
--- projects/ipfw/sbin/ipfw/tables.c	Tue Jul 29 22:29:32 2014	(r269275)
+++ projects/ipfw/sbin/ipfw/tables.c	Tue Jul 29 22:44:26 2014	(r269276)
@@ -146,6 +146,7 @@ ipfw_table_handler(int ac, char *av[])
 		set = 0;
 
 	ac--; av++;
+	NEED1("table needs name");
 	tablename = *av;
 
 	if (table_check_name(tablename) == 0) {
@@ -158,11 +159,11 @@ ipfw_table_handler(int ac, char *av[])
 			errx(EX_USAGE, "table name %s is invalid", tablename);
 	}
 	ac--; av++;
+	NEED1("table needs command");
 
 	if ((tcmd = match_token(tablecmds, *av)) == -1)
 		errx(EX_USAGE, "invalid table command %s", *av);
 
-	NEED1("table needs command");
 	switch (tcmd) {
 	case TOK_LIST:
 	case TOK_INFO:
@@ -416,8 +417,8 @@ table_show_info(ipfw_xtable_info *i, voi
 		vtype = "unknown";
 
 	printf(" type: %s, kindex: %d\n", ttype, i->kidx);
-	printf(" valtype: %s, algorithm: %s\n", vtype, i->algoname);
-	printf(" references: %u\n", i->refcnt);
+	printf(" valtype: %s, references: %u\n", vtype, i->refcnt);
+	printf(" algorithm: %s\n", i->algoname);
 	printf(" items: %u, size: %u\n", i->count, i->size);
 
 	return (0);
@@ -901,6 +902,59 @@ table_show_entry(ipfw_xtable_info *i, ip
 	}
 }
 
+static int
+table_do_get_algolist(ipfw_obj_lheader **polh)
+{
+	ipfw_obj_lheader req, *olh;
+	size_t sz;
+	int error;
+
+	memset(&req, 0, sizeof(req));
+	sz = sizeof(req);
+
+	error = do_get3(IP_FW_TABLES_ALIST, &req.opheader, &sz);
+	if (error != 0 && error != ENOMEM)
+		return (error);
+
+	sz = req.size;
+	if ((olh = calloc(1, sz)) == NULL)
+		return (ENOMEM);
+
+	olh->size = sz;
+	if ((error = do_get3(IP_FW_TABLES_ALIST, &olh->opheader, &sz)) != 0) {
+		free(olh);
+		return (error);
+	}
+
+	*polh = olh;
+	return (0);
+}
+
+void
+ipfw_list_ta(int ac, char *av[])
+{
+	ipfw_obj_lheader *olh;
+	ipfw_ta_info *info;
+	int error, i;
+	const char *atype;
+
+	error = table_do_get_algolist(&olh);
+	if (error != 0)
+		err(EX_OSERR, "Unable to request algorithm list");
+
+	info = (ipfw_ta_info *)(olh + 1);
+	for (i = 0; i < olh->count; i++) {
+		if ((atype = match_value(tabletypes, info->type)) == NULL)
+			atype = "unknown";
+
+		printf("%s type: %s references: %u\n", info->algoname,
+		    atype, info->refcnt);
+		info = (ipfw_ta_info *)((caddr_t)info + olh->objsize);
+	}
+
+	free(olh);
+}
+
 int
 compare_ntlv(const void *_a, const void *_b)
 {

Modified: projects/ipfw/sys/netinet/ip_fw.h
==============================================================================
--- projects/ipfw/sys/netinet/ip_fw.h	Tue Jul 29 22:29:32 2014	(r269275)
+++ projects/ipfw/sys/netinet/ip_fw.h	Tue Jul 29 22:44:26 2014	(r269276)
@@ -89,6 +89,7 @@ typedef struct _ip_fw3_opheader {
 #define	IP_FW_XADD		98	/* add entry */
 #define	IP_FW_TABLE_XFIND	99	/* finds an entry */
 #define	IP_FW_XIFLIST		100	/* list tracked interfaces */
+#define	IP_FW_TABLES_ALIST	101	/* list table algorithms */
 
 /*
  * Usage guidelines:
@@ -799,6 +800,15 @@ typedef struct _ipfw_iface_info {
 } ipfw_iface_info;
 #define	IPFW_IFFLAG_RESOLVED	0x01	/* Interface exists		*/
 
+typedef struct _ipfw_ta_info {
+	char		algoname[32];	/* algorithm name		*/
+	uint32_t	type;		/* lookup type			*/
+	uint32_t	flags;
+	uint32_t	refcnt;
+	uint32_t	spare0;
+	uint64_t	spare1;
+} ipfw_ta_info;
+
 #define	IPFW_OBJTYPE_TABLE	1
 typedef struct _ipfw_obj_header {
 	ip_fw3_opheader	opheader;	/* IP_FW3 opcode		*/

Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c	Tue Jul 29 22:29:32 2014	(r269275)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c	Tue Jul 29 22:44:26 2014	(r269276)
@@ -2001,6 +2001,9 @@ ipfw_ctl(struct sockopt *sopt)
 	case IP_FW_TABLE_XFIND: /* IP_FW3 */
 		error = ipfw_find_table_entry(chain, op3, &sdata);
 		break;
+	case IP_FW_TABLES_ALIST: /* IP_FW3 */
+		error = ipfw_list_table_algo(chain, &sdata);
+		break;
 
 	/*--- LEGACY API ---*/
 	case IP_FW_TABLE_ADD:

Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c	Tue Jul 29 22:29:32 2014	(r269275)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c	Tue Jul 29 22:44:26 2014	(r269276)
@@ -1641,6 +1641,59 @@ ipfw_del_table_algo(struct ip_fw_chain *
 	free(ta, M_IPFW);
 }
 
+/*
+ * Lists all table algorithms currently available.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
+ * Reply: [ ipfw_obj_lheader ipfw_ta_info x N ]
+ *
+ * Returns 0 on success
+ */
+int
+ipfw_list_table_algo(struct ip_fw_chain *ch, struct sockopt_data *sd)
+{
+	struct _ipfw_obj_lheader *olh;
+	struct tables_config *tcfg;
+	ipfw_ta_info *i;
+	struct table_algo *ta;
+	uint32_t count, n, size;
+
+	olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
+	if (olh == NULL)
+		return (EINVAL);
+	if (sd->valsize < olh->size)
+		return (EINVAL);
+
+	IPFW_UH_RLOCK(ch);
+	tcfg = CHAIN_TO_TCFG(ch);
+	count = tcfg->algo_count;
+	size = count * sizeof(ipfw_ta_info) + sizeof(ipfw_obj_lheader);
+
+	/* Fill in header regadless of buffer size */
+	olh->count = count;
+	olh->objsize = sizeof(ipfw_ta_info);
+
+	if (size > olh->size) {
+		olh->size = size;
+		IPFW_UH_RUNLOCK(ch);
+		return (ENOMEM);
+	}
+	olh->size = size;
+
+	for (n = 1; n <= count; n++) {
+		i = (ipfw_ta_info *)ipfw_get_sopt_space(sd, sizeof(*i));
+		KASSERT(i != 0, ("previously checked buffer is not enough"));
+		ta = tcfg->algo[n];
+		strlcpy(i->algoname, ta->name, sizeof(i->algoname));
+		i->type = ta->type;
+		i->refcnt = ta->refcnt;
+	}
+
+	IPFW_UH_RUNLOCK(ch);
+
+	return (0);
+}
+
 
 /*
  * Tables rewriting code 
@@ -1925,6 +1978,7 @@ link_table(struct ip_fw_chain *ch, struc
 		tc->ta->change_ti(tc->astate, ti);
 
 	tc->linked = 1;
+	tc->ta->refcnt++;
 }
 
 /*
@@ -1949,6 +2003,7 @@ unlink_table(struct ip_fw_chain *ch, str
 	ti = KIDX_TO_TI(ch, kidx);
 	memset(ti, 0, sizeof(struct table_info));
 	tc->linked = 0;
+	tc->ta->refcnt--;
 
 	/* Notify algo on real @ti address */
 	if (tc->ta->change_ti != NULL)

Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h	Tue Jul 29 22:29:32 2014	(r269275)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h	Tue Jul 29 22:44:26 2014	(r269276)
@@ -98,6 +98,9 @@ typedef int ta_find_tentry(void *ta_stat
 struct table_algo {
 	char		name[16];
 	int		idx;
+	int		type;
+	int		refcnt;
+	int		spare;
 	ta_init		*init;
 	ta_destroy	*destroy;
 	ta_prepare_add	*prepare_add;
@@ -140,6 +143,7 @@ int ipfw_manage_table_ent(struct ip_fw_c
     struct sockopt_data *sd);
 int ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
     struct sockopt_data *sd);
+int ipfw_list_table_algo(struct ip_fw_chain *ch, struct sockopt_data *sd);
 /* Exported to support legacy opcodes */
 int add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
     struct tentry_info *tei);

Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c	Tue Jul 29 22:29:32 2014	(r269275)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c	Tue Jul 29 22:44:26 2014	(r269276)
@@ -516,6 +516,7 @@ ta_flush_cidr_entry(struct ip_fw_chain *
 
 struct table_algo cidr_radix = {
 	.name		= "cidr:radix",
+	.type		= IPFW_TABLE_CIDR,
 	.init		= ta_init_radix,
 	.destroy	= ta_destroy_radix,
 	.prepare_add	= ta_prepare_add_cidr,
@@ -1194,6 +1195,7 @@ ta_flush_chash_entry(struct ip_fw_chain 
 
 struct table_algo cidr_hash = {
 	.name		= "cidr:hash",
+	.type		= IPFW_TABLE_CIDR,
 	.init		= ta_init_chash,
 	.destroy	= ta_destroy_chash,
 	.prepare_add	= ta_prepare_add_chash,
@@ -1846,6 +1848,7 @@ ta_foreach_ifidx(void *ta_state, struct 
 
 struct table_algo iface_idx = {
 	.name		= "iface:array",
+	.type		= IPFW_TABLE_INTERFACE,
 	.init		= ta_init_ifidx,
 	.destroy	= ta_destroy_ifidx,
 	.prepare_add	= ta_prepare_add_ifidx,


More information about the svn-src-projects mailing list