Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Nov 2011 06:56:45 +0000 (UTC)
From:      Lawrence Stewart <lstewart@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r227813 - in projects/diffused_head: etc/mtree include sbin/ipfw
Message-ID:  <201111220656.pAM6ujse078726@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: lstewart
Date: Tue Nov 22 06:56:45 2011
New Revision: 227813
URL: http://svn.freebsd.org/changeset/base/227813

Log:
  Integrate DIFFUSE related functionality into the IPFW userspace control utility.
  The code extends sbin/ipfw to manage, parse and output DIFFUSE specific
  configuration exchanged with the DIFFUSE kernel module via the DIFFUSE control
  raw socket. The UI extension for features and classifiers is kept modular to
  minimise the overhead involved in adding new features and classifiers in future.
  
  Sponsored by:	FreeBSD Foundation
  Reviewed by:	bz

Added:
  projects/diffused_head/sbin/ipfw/diffuse_modules.c   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_proto.h   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui.c   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui.h   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui_classifier_c45.c   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui_classifier_nbayes.c   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui_feature_iat.c   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui_feature_iatbd.c   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui_feature_pcnt.c   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui_feature_plen.c   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui_feature_plenbd.c   (contents, props changed)
  projects/diffused_head/sbin/ipfw/diffuse_ui_feature_skype.c   (contents, props changed)
Modified:
  projects/diffused_head/etc/mtree/BSD.include.dist
  projects/diffused_head/include/Makefile
  projects/diffused_head/sbin/ipfw/Makefile
  projects/diffused_head/sbin/ipfw/ipfw2.c
  projects/diffused_head/sbin/ipfw/ipfw2.h
  projects/diffused_head/sbin/ipfw/main.c

Modified: projects/diffused_head/etc/mtree/BSD.include.dist
==============================================================================
--- projects/diffused_head/etc/mtree/BSD.include.dist	Tue Nov 22 02:50:24 2011	(r227812)
+++ projects/diffused_head/etc/mtree/BSD.include.dist	Tue Nov 22 06:56:45 2011	(r227813)
@@ -258,6 +258,8 @@
         ..
     ..
     netinet
+        ipfw
+        ..
     ..
     netinet6
     ..

Modified: projects/diffused_head/include/Makefile
==============================================================================
--- projects/diffused_head/include/Makefile	Tue Nov 22 02:50:24 2011	(r227812)
+++ projects/diffused_head/include/Makefile	Tue Nov 22 06:56:45 2011	(r227813)
@@ -215,6 +215,15 @@ copies:
 	cd ${.CURDIR}/../sys/rpc; \
 	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 types.h \
 	    ${DESTDIR}${INCLUDEDIR}/rpc
+	cd ${.CURDIR}/../sys/netinet/ipfw; \
+	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 diffuse_feature*.h \
+	    ${DESTDIR}${INCLUDEDIR}/netinet/ipfw; \
+	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 diffuse_classifier*.h \
+	    ${DESTDIR}${INCLUDEDIR}/netinet/ipfw; \
+	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 diffuse_common.h \
+	    ${DESTDIR}${INCLUDEDIR}/netinet/ipfw; \
+	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 diffuse_user_compat.h \
+	    ${DESTDIR}${INCLUDEDIR}/netinet/ipfw
 
 symlinks:
 	@${ECHO} "Setting up symlinks to kernel source tree..."
@@ -315,3 +324,12 @@ symlinks:
 		ln -fs ../../../sys/rpc/$$h \
 		    ${DESTDIR}${INCLUDEDIR}/rpc; \
 	done
+	cd ${.CURDIR}/../sys/netinet/ipfw; \
+	for h in diffuse_classifier*.h diffuse_feature*.h; do \
+		ln -fs ../../../../sys/netinet/ipfw/$$h \
+			${DESTDIR}${INCLUDEDIR}/netinet/ipfw; \
+	done; \
+	ln -fs ../../../../sys/netinet/ipfw/diffuse_common.h \
+	    ${DESTDIR}${INCLUDEDIR}/netinet/ipfw; \
+	ln -fs ../../../../sys/netinet/ipfw/diffuse_user_compat.h \
+	    ${DESTDIR}${INCLUDEDIR}/netinet/ipfw

Modified: projects/diffused_head/sbin/ipfw/Makefile
==============================================================================
--- projects/diffused_head/sbin/ipfw/Makefile	Tue Nov 22 02:50:24 2011	(r227812)
+++ projects/diffused_head/sbin/ipfw/Makefile	Tue Nov 22 06:56:45 2011	(r227813)
@@ -2,9 +2,15 @@
 
 PROG=	ipfw
 SRCS=	ipfw2.c dummynet.c ipv6.c main.c nat.c altq.c
+SRCS+=	diffuse_ui.c diffuse_modules.c diffuse_ui_classifier_c45.c
+SRCS+=	diffuse_ui_classifier_nbayes.c diffuse_ui_feature_iat.c
+SRCS+=	diffuse_ui_feature_iatbd.c diffuse_ui_feature_pcnt.c
+SRCS+=	diffuse_ui_feature_plen.c diffuse_ui_feature_plenbd.c
+SRCS+=	diffuse_ui_feature_skype.c
 WARNS?=	2
 DPADD=	${LIBUTIL}
-LDADD=	-lutil
+DPADD+=	${LIBM}
+LDADD=	-lutil -lm
 MAN=	ipfw.8
 
 .include <bsd.prog.mk>

Added: projects/diffused_head/sbin/ipfw/diffuse_modules.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/diffused_head/sbin/ipfw/diffuse_modules.c	Tue Nov 22 06:56:45 2011	(r227813)
@@ -0,0 +1,165 @@
+/*-
+ * Copyright (c) 2010-2011
+ * 	Swinburne University of Technology, Melbourne, Australia.
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Sebastian Zander, made
+ * possible in part by a gift from The Cisco University Research Program Fund, a
+ * corporate advised fund of Silicon Valley Community Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Description:
+ * Functions to manage classifier and feature UI modules.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/ip_fw.h>
+#include <netinet/ip_diffuse.h>
+
+#include <netinet/ipfw/diffuse_feature.h>
+#include <netinet/ipfw/diffuse_classifier_nbayes.h>
+#include <netinet/ipfw/diffuse_classifier_c45.h>
+#include <netinet/ipfw/diffuse_feature_iat.h>
+#include <netinet/ipfw/diffuse_feature_iatbd.h>
+#include <netinet/ipfw/diffuse_feature_pcnt.h>
+#include <netinet/ipfw/diffuse_feature_plen_common.h>
+#include <netinet/ipfw/diffuse_feature_plen.h>
+#include <netinet/ipfw/diffuse_feature_plenbd.h>
+#include <netinet/ipfw/diffuse_feature_skype.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "diffuse_ui.h"
+
+SLIST_HEAD(di_featuremods_head, di_feature_module);
+SLIST_HEAD(di_classifiermods_head, di_classifier_module);
+
+/* List of feature modules. */
+static struct di_featuremods_head *featuremods =
+    SLIST_HEAD_INITIALIZER(featuremods);
+
+/* List of classifier modules. */
+static struct di_classifiermods_head *classifiermods =
+    SLIST_HEAD_INITIALIZER(classifiermods);
+
+struct di_classifier_module *
+find_classifier_module(const char *name)
+{
+	struct di_classifier_module *tmp;
+
+	tmp = NULL;
+
+	SLIST_FOREACH(tmp, classifiermods, next) {
+		if (strcmp(tmp->name, name) == 0)
+			break;
+	}
+
+	return (tmp);
+}
+
+void
+print_classifier_modules()
+{
+	struct di_classifier_module *tmp;
+
+	SLIST_FOREACH(tmp, classifiermods, next) {
+		printf("%s ", tmp->name);
+	}
+	printf("\n");
+}
+
+struct di_feature_module *
+find_feature_module(const char *name)
+{
+	struct di_feature_module *tmp;
+
+	tmp = NULL;
+
+	SLIST_FOREACH(tmp, featuremods, next) {
+		if (strcmp(tmp->name, name) == 0)
+			break;
+	}
+
+	return (tmp);
+}
+
+void
+print_feature_modules()
+{
+	struct di_feature_module *tmp;
+
+	SLIST_FOREACH(tmp, featuremods, next) {
+		printf("%s ", tmp->name);
+	}
+	printf("\n");
+}
+
+void
+diffuse_classifier_modules_init()
+{
+
+	SLIST_INIT(classifiermods);
+	SLIST_INSERT_HEAD(classifiermods, c45_module(), next);
+	SLIST_INSERT_HEAD(classifiermods, nbayes_module(), next);
+}
+
+void
+diffuse_feature_modules_init()
+{
+
+	SLIST_INIT(featuremods);
+	SLIST_INSERT_HEAD(featuremods, iat_module(), next);
+	SLIST_INSERT_HEAD(featuremods, iatbd_module(), next);
+	SLIST_INSERT_HEAD(featuremods, pcnt_module(), next);
+	SLIST_INSERT_HEAD(featuremods, plen_module(), next);
+	SLIST_INSERT_HEAD(featuremods, plenbd_module(), next);
+	SLIST_INSERT_HEAD(featuremods, skype_module(), next);
+}
+
+void
+diffuse_modules_init()
+{
+
+	diffuse_feature_modules_init();
+	diffuse_classifier_modules_init();
+#ifdef DIFFFUSE_DEBUG
+	printf("Known features: ");
+	print_feature_modules();
+	printf("Known classifiers: ");
+	print_classifier_modules();
+#endif
+}

Added: projects/diffused_head/sbin/ipfw/diffuse_proto.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/diffused_head/sbin/ipfw/diffuse_proto.h	Tue Nov 22 06:56:45 2011	(r227813)
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2010-2011
+ * 	Swinburne University of Technology, Melbourne, Australia.
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Sebastian Zander, made
+ * possible in part by a gift from The Cisco University Research Program Fund, a
+ * corporate advised fund of Silicon Valley Community Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Description:
+ * Functions for control protocol.
+ */
+
+#ifndef _SBIN_IPFW_DIFFUSE_PROTO_H_
+#define _SBIN_IPFW_DIFFUSE_PROTO_H_
+
+#define	DI_COLLECTOR_DEFAULT_LISTEN_PORT	3191
+#define	DI_EXPORTER_DEFAULT_LISTEN_PORT		4377
+
+/* Template list. */
+
+struct di_template {
+	uint16_t		id;		/* Template id. */
+	struct dip_info_element	fields[64];	/* Fields. */
+	int			fcnt;		/* Number of template fields. */
+	RB_ENTRY(di_template)	node;
+};
+
+static inline int
+template_compare(struct di_template *a, struct di_template *b)
+{
+
+	return ((a->id != b->id) ? (a->id < b->id ? -1 : 1) : 0);
+}
+
+RB_HEAD(di_template_head, di_template);
+RB_PROTOTYPE(di_template_head, di_template, node, template_compare);
+
+struct dip_info_descr diffuse_proto_get_info(uint16_t id);
+void diffuse_proto_print_msg(char *buf, struct di_template_head *templ_list);
+
+#endif /* _SBIN_IPFW_DIFFUSE_PROTO_H_ */

Added: projects/diffused_head/sbin/ipfw/diffuse_ui.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/diffused_head/sbin/ipfw/diffuse_ui.c	Tue Nov 22 06:56:45 2011	(r227813)
@@ -0,0 +1,2309 @@
+/*-
+ * Copyright (c) 2010-2011
+ * 	Swinburne University of Technology, Melbourne, Australia.
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Sebastian Zander, made
+ * possible in part by a gift from The Cisco University Research Program Fund, a
+ * corporate advised fund of Silicon Valley Community Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/tree.h>
+#include <sys/types.h>
+
+#include <arpa/inet.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/ip_fw.h>
+#include <netinet/ip_diffuse.h>
+#include <netinet/ip_diffuse_export.h>
+
+#include <netinet/ipfw/diffuse_common.h>
+#include <netinet/ipfw/diffuse_user_compat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+#include "diffuse_ui.h"
+#include "diffuse_proto.h"
+#include "ipfw2.h"
+
+/* Takes an *ipfw_insn as cmd. */
+#define	GENERATE_FEATURES(cmd) do {					\
+	if (!features) {						\
+		(cmd)->opcode = O_DI_FEATURES_IMPLICIT;			\
+		fill_features((ipfw_insn_features *)(cmd), NULL);	\
+		features = (ipfw_insn_features *)(cmd);			\
+		(cmd) = next_cmd(cmd);					\
+	}								\
+} while(0)
+
+/* New tokens used by DIFFUSE in rule sets. */
+static struct di_option diffuse_main_params[] = {
+	{ "module",		DI_OPTION_ARG_STR,	0, 0,
+	    TOK_DI_MODULE },
+	{ "algorithm",		DI_OPTION_ARG_STR,	0, 0,
+	    TOK_DI_ALGORITHM },
+	{ "use-feature-stats",	DI_OPTION_ARG_STR,	0, 0,
+	    TOK_DI_USE_FEATURE_STATS },
+	{ "class-names",	DI_OPTION_ARG_STR,	0, 0,
+	    TOK_DI_CLASS_NAMES },
+	{ "expired",		DI_OPTION_ARG_NOARG,	0, 0,
+	    TOK_DI_EXPIRED },
+	{ "target",		DI_OPTION_ARG_STR,	0, 0,
+	    TOK_DI_EXP_TARGET },
+	{ "confirm",		DI_OPTION_ARG_UINT,	1, 65535,
+	    TOK_DI_CONFIRM },
+	{ "min-batch",		DI_OPTION_ARG_UINT,	1, 65535,
+	    TOK_DI_EXP_MIN_BATCH },
+	{ "max-batch",		DI_OPTION_ARG_UINT,	1, 65535,
+	    TOK_DI_EXP_MAX_BATCH },
+	{ "max-delay",		DI_OPTION_ARG_UINT,	1, 65535,
+	    TOK_DI_EXP_MAX_DELAY },
+	{ "flow-key",		DI_OPTION_ARG_STR,	0, 0,
+	    TOK_DI_EXP_FLOW_KEY },
+	{ "features",		DI_OPTION_ARG_STR,	0, 0,
+	    TOK_DI_EXP_FEATURES },
+	{ "action",		DI_OPTION_ARG_STR,	0, 0,
+	    TOK_DI_EXP_ACTION },
+	{ "action-params",	DI_OPTION_ARG_STR,	0, 0,
+	    TOK_DI_EXP_ACTION_PARAMS },
+	{ "unidirectional",	DI_OPTION_ARG_NOARG,	0, 0,
+	    TOK_DI_EXP_ACTION_UNIDIR },
+	{ NULL, 0, 0, 0, 0 }
+};
+
+/* Main parameters plus parameters of registered features/classifiers. */
+static struct di_option *diffuse_all_params = NULL;
+
+/* Globals for parsing functions. */
+ipfw_insn_features *features = NULL;		/* Ptr to features cmd. */
+ipfw_insn_ml_classify *classifier = NULL;	/* Ptr to classify action. */
+int have_feature_match;
+
+/*
+ * Merge feature module params (called from module).
+ * opts must be a NULL terminated array of struct di_option.
+ */
+int
+diffuse_add_params(struct di_option *opts, int size)
+{
+	struct di_option *o;
+	int old;
+
+	if (diffuse_all_params == NULL) {
+		diffuse_all_params = (struct di_option *)safe_calloc(1, size);
+		memcpy(diffuse_all_params, opts, size);
+	} else {
+		old = sizeof(diffuse_main_params);
+		diffuse_all_params =
+		    (struct di_option *)safe_realloc(diffuse_all_params,
+		    old + size);
+		o = diffuse_all_params;
+		/*
+		 * The last element of diffuse_all_params is always an empty
+		 * struct di_option so the below will copy opts over the top of
+		 * the empty struct di_option in diffuse_all_params.
+		 */
+		while (o->name != NULL)
+			o++;
+		memcpy(o, opts, size);
+	}
+
+	return (0);
+}
+
+/*
+ * Helper stuff for building commands, etc.
+ */
+
+#define	O_NEXT(p, len) ((void *)(((char *)(p)) + (len)))
+
+void
+diffuse_rec_fill(struct di_oid *oid, int len, int type, uintptr_t id)
+{
+
+	oid->len = len;
+	oid->type = type;
+	oid->subtype = 0;
+	oid->id = id;
+}
+
+/* Make room in the buffer and move the pointer forward. */
+void *
+diffuse_rec_next(struct di_oid **o, int len, int type)
+{
+	struct di_oid *ret;
+
+	ret = *o;
+	diffuse_rec_fill(ret, len, type, 0);
+	*o = O_NEXT(*o, len);
+
+	return (ret);
+}
+
+/*
+ * Takes a table and a string, returns the value associated
+ * with the string (NULL in case of failure).
+ */
+struct di_option *
+diffuse_match_token(struct di_option *table, char *string)
+{
+	struct di_option *pt;
+
+	pt = NULL;
+	if (strlen(string) > 0) {
+		for (pt = table; pt->name != NULL; pt++)
+			if (strcmp(pt->name, string) == 0)
+				break;
+	}
+
+	return (pt);
+}
+
+void
+print_tokens(void)
+{
+	struct di_option *pt;
+
+	for (pt = diffuse_all_params; pt->name != NULL; pt++)
+		printf("t %s\n", pt->name);
+}
+
+/* Test if string only contains alphanumeric characters. */
+int
+str_isalnum(char *s)
+{
+
+	while (isalnum(*s))
+		++s;
+
+	return (*s == '\0');
+}
+
+/*
+ * List functions.
+ */
+
+/* List flow table. */
+static void
+list_ft(struct di_oid *oid, struct di_oid *end,
+    struct di_feature_arr_entry *features, int counters)
+{
+	struct di_feature_module *f;
+	struct di_ft_export_entry *p;
+	struct in_addr a;
+	struct protoent *pe;
+	char *cname, *cp, *fname, *mod_name;
+	char buf[INET6_ADDRSTRLEN];
+	int i, j;
+	int32_t *bck_svals, *fwd_svals;
+	uint16_t *class;
+	uint8_t *fidx, *scnt;
+
+#ifdef DIFFUSE_DEBUG2
+	printf("list_ft\n");
+#endif
+	if (oid->type != DI_FLOW_TABLE)
+		return;
+
+	cp = (char *)oid + sizeof(struct di_oid);
+	while (cp < (char *)end) {
+		p = (struct di_ft_export_entry *)cp;
+
+		printf("%05d", p->ruleno);
+		printf(" %05d", p->bucket);
+
+		if (counters > 0) {
+			printf(" ");
+			pr_u64(&p->pcnt, pr_u64(&p->pcnt, 0));
+			pr_u64(&p->bcnt, pr_u64(&p->bcnt, 0));
+			printf("(%ds)", p->expire);
+		}
+		if ((pe = getprotobynumber(p->id.proto)) != NULL)
+			printf(" %s", pe->p_name);
+		else
+			printf(" proto %u", p->id.proto);
+
+		/*
+		 * The DIFFUSE kernel code stores the flow ID address and port
+		 * in host byte order.
+		 */
+		if (p->id.addr_type == 4) {
+			a.s_addr = htonl(p->id.src_ip);
+			printf(" %s %u", inet_ntoa(a), p->id.src_port);
+
+			a.s_addr = htonl(p->id.dst_ip);
+			if (p->ftype & DI_FLOW_TYPE_BIDIRECTIONAL)
+				printf(" <-> ");
+			else
+				printf(" -> ");
+
+			printf("%s %u", inet_ntoa(a), p->id.dst_port);
+		} else if (p->id.addr_type == 6) {
+			printf(" %s %u", inet_ntop(AF_INET6, &p->id.src_ip6,
+			    buf, sizeof(buf)), p->id.src_port);
+			if (p->ftype & DI_FLOW_TYPE_BIDIRECTIONAL)
+				printf(" <-> ");
+			else
+				printf(" -> ");
+
+			printf("%s %u", inet_ntop(AF_INET6, &p->id.dst_ip6,
+			    buf, sizeof(buf)), p->id.dst_port);
+		} else {
+			printf(" UNKNOWN <-> UNKNOWN\n");
+		}
+
+		cp += sizeof(struct di_ft_export_entry);
+		fidx = (uint8_t *)cp;
+		cp += p->fcnt*sizeof(uint8_t);
+		scnt = (uint8_t *)cp;
+		cp += p->fcnt * sizeof(uint8_t);
+		printf(" ");
+
+		for (i = 0; i < p->fcnt; i++) {
+			/*
+			 * Need to have feature name and algo name
+			 * lookup stat names via algo.
+			 */
+			fname = features[fidx[i]].name;
+			mod_name = features[fidx[i]].mod_name;
+			f = find_feature_module(mod_name);
+
+			if (!(f->type & DI_FEATURE_ALG_BIDIRECTIONAL) &&
+			    p->ftype & DI_FLOW_TYPE_BIDIRECTIONAL) {
+				fwd_svals = (int32_t *)cp;
+				cp += scnt[i] * sizeof(int32_t);
+				bck_svals = (int32_t * )cp;
+				cp += scnt[i] * sizeof(int32_t);
+
+				for (j = 0; j < scnt[i]; j++) {
+					printf("fwd.%s.%s=%d ",
+					    f->get_stat_name(j), fname,
+					    fwd_svals[j]);
+				}
+				for (j = 0; j < scnt[i]; j++) {
+					printf("bck.%s.%s=%d ",
+					    f->get_stat_name(j), fname,
+					    bck_svals[j]);
+				}
+			} else {
+				fwd_svals = (int32_t *)cp;
+				cp += scnt[i] * sizeof(int32_t);
+
+				for (j = 0; j < scnt[i]; j++) {
+					printf("%s.%s=%d ", f->get_stat_name(j),
+					    fname, fwd_svals[j]);
+				}
+			}
+		}
+		for (i = 0; i < p->tcnt; i++) {
+			cname = cp;
+			cp += DI_MAX_NAME_STR_LEN;
+			class = (uint16_t *)cp;
+			cp += sizeof(uint16_t);
+			printf("%s:%c%u ", cname, DI_CLASS_NO_CHAR, *class);
+		}
+		printf("\n");
+	}
+}
+
+/* List features and flow table. */
+static void
+list_features(struct di_oid *oid, struct di_oid *end)
+{
+	struct di_ctl_feature *f;
+	struct di_feature_module *last_mod;
+	struct di_feature_arr_entry feature_arr[DI_MAX_FEATURES];
+	int fcnt;
+
+	last_mod = NULL;
+
+	for (fcnt = 0; oid != end; oid = O_NEXT(oid, oid->len)) {
+		if (oid->len < sizeof(*oid))
+			errx(1, "invalid oid len %d", oid->len);
+
+		switch (oid->type) {
+		case DI_CMD_GET:
+			if (co.verbose)
+				printf("answer for cmd %d, len %d\n", oid->type,
+				    oid->id);
+			break;
+
+		case DI_FEATURE:
+		{
+
+			f = (struct di_ctl_feature *)oid;
+			printf("feature %s (algorithm %s)\n", f->name,
+			    f->mod_name);
+			/*
+			 * DI_FEATURE oid's are always paired with a
+			 * DI_FEATURE_CONFIG oid, so we set last_mod here which
+			 * will be used for the next oid which will be the
+			 * corresponding DI_FEATURE_CONFIG.
+			 */
+			last_mod = find_feature_module(f->mod_name);
+			strcpy(feature_arr[fcnt].name, f->name);
+			strcpy(feature_arr[fcnt].mod_name, f->mod_name);
+			fcnt++;
+			break;
+		}
+
+		case DI_FEATURE_CONFIG:
+			if (last_mod != NULL) {
+				last_mod->print_opts(oid);
+				last_mod = NULL;
+			} else {
+				printf("  unrecognized feature\n");
+			}
+			break;
+
+		case DI_FLOW_TABLE:
+			list_ft(oid, end, feature_arr, 1);
+			break;
+
+		default:
+			printf("unrecognized object %d size %d\n", oid->type,
+			    oid->len);
+			break;
+		}
+	}
+}
+
+/* List classifiers. */
+static void
+list_classifiers(struct di_oid *oid, struct di_oid *end)
+{
+	struct di_classifier_module *last_mod;
+	struct di_ctl_classifier *c;
+	int i;
+
+	last_mod = NULL;
+
+	for (; oid != end; oid = O_NEXT(oid, oid->len)) {
+		if (oid->len < sizeof(*oid))
+			errx(1, "invalid oid len %d", oid->len);
+
+		switch (oid->type) {
+		case DI_CMD_CONFIG:
+			break;
+
+		case DI_CMD_GET:
+			if (co.verbose)
+				printf("answer for cmd %d, len %d\n", oid->type,
+				    oid->id);
+			break;
+
+		case DI_CLASSIFIER:
+		{
+			c = (struct di_ctl_classifier *)oid;
+
+			printf("classifier %s (algorithm %s)\n", c->name,
+			    c->mod_name);
+			printf("  features: %d\n", c->fscnt);
+			for (i = 0; i < c->fscnt; i++) {
+				printf("    %s%s.%s\n",
+				    c->fstats[i].fdir == DI_MATCH_DIR_NONE ?
+				    "" : (c->fstats[i].fdir == DI_MATCH_DIR_FWD ?
+				    "fwd." : "bck."),
+				    c->fstats[i].sname,
+				    c->fstats[i].fname);
+			}
+			printf("  classes: %d\n", c->ccnt);
+			for (i = 0; i < c->ccnt; i++)
+				printf("    %s\n", c->fstats[c->fscnt+i].fname);
+
+			printf("  confirm: %d\n", c->confirm);
+			/*
+			 * DI_CLASSIFIER oid's are always paired with a
+			 * DI_CLASSIFIER_CONFIG oid, so we set last_mod here
+			 * which will be used for the next oid which will be the
+			 * corresponding DI_CLASSIFIER_CONFIG.
+			 */
+			last_mod = find_classifier_module(c->mod_name);
+			break;
+		}
+
+		case DI_CLASSIFIER_CONFIG:
+			if (last_mod != NULL) {
+				last_mod->print_opts(oid);
+				last_mod = NULL;
+			} else {
+				printf("  unrecognized feature\n");
+			}
+			break;
+
+		default:
+			printf("unrecognized object %d size %d\n", oid->type,
+			    oid->len);
+			break;
+		}
+	}
+}
+
+/* List exports. */
+static void
+list_exports(struct di_oid *oid, struct di_oid *end)
+{
+	struct di_ctl_export *e;
+	struct in_addr a;
+
+	for (; oid != end; oid = O_NEXT(oid, oid->len)) {
+		if (oid->len < sizeof(*oid))
+			errx(1, "invalid oid len %d", oid->len);
+
+		switch (oid->type) {
+		case DI_CMD_GET:
+			if (co.verbose)
+				printf("answer for cmd %d, len %d\n", oid->type,
+				    oid->id);
+			break;
+
+		case DI_EXPORT:
+		{
+			e = (struct di_ctl_export *)oid;
+
+			printf("export %s\n", e->name);
+			/* XXX: IPv6 missing */
+			a.s_addr = htonl(e->conf.ip.s_addr);
+			printf("  target udp://%s:%d\n", inet_ntoa(a),
+			    e->conf.port);
+			printf("  confirm %d\n", e->conf.confirm);
+			printf("  min_batch %d\n", e->conf.min_batch);
+			printf("  max_batch %d\n", e->conf.max_batch);
+			printf("  max_delay %d\n", e->conf.max_delay);
+			printf("  action %s %s\n", e->conf.action,
+			    e->conf.action_param); /* XXX: Define types. */
+			if (e->conf.atype & DI_ACTION_TYPE_BIDIRECTIONAL)
+				printf("  bidirectional\n");
+			else
+				printf("  unidirectional\n");
+			break;
+		}
+
+		default:
+			printf("unrecognized object %d size %d\n", oid->type,
+			    oid->len);
+			break;
+		}
+	}
+}
+
+/*
+ * Main functions called from ipfw.
+ */
+
+void
+print_feature_usage()
+{
+
+	printf("ipfw feature <name> config ");
+}
+
+void
+print_classifier_usage()
+{
+
+	printf("ipfw mlclass <name> config [confirm]");
+}
+
+void
+print_export_usage()
+{
+
+	printf("ipfw export <name> config target <proto>://<ip>:<port> ");
+	printf("[confirm <number>] [action <name>] [action-params <string>] ");
+	printf("[min-batch <number>] [max-batch <number>] ");
+	printf("[max-delay <number>]\n");
+}
+
+void
+diffuse_init()
+{
+
+	diffuse_modules_init();
+	diffuse_add_params(diffuse_main_params, sizeof(diffuse_main_params));
+	/* XXX: Modules are not deregistered at the end. */
+}
+
+/*
+ * Only support one feature/classifier/export name now.
+ * XXX: extend to comma separated list.
+ */
+void
+diffuse_delete(int ac, char *av[], int type)
+{
+	struct di_ctl_classifier *class;
+	struct di_ctl_export *exp;
+	struct di_ctl_feature *feature;
+	struct di_oid *buf, *base;
+	char *name;
+	int lmax;
+
+	feature = NULL;
+	class = NULL;
+	exp = NULL;
+
+#ifdef DIFFFUSE_DEBUG2
+	printf("diffuse delete\n");
+#endif
+
+	lmax = sizeof(struct di_oid); /* Command header. */
+	if (type == DI_FEATURE)
+		lmax += sizeof(struct di_ctl_feature);
+	else if (type == DI_CLASSIFIER)
+		lmax += sizeof(struct di_ctl_classifier);
+	else if (type == DI_EXPORT)
+		lmax += sizeof(struct di_ctl_export);
+	else
+		errx(1, "invalid DIFFUSE deletion type %d", type);
+
+	base = buf = safe_calloc(1, lmax);
+	/* All commands start with a 'DELETE' and a version. */
+	diffuse_rec_next(&buf, sizeof(struct di_oid), DI_CMD_DELETE);
+	base->id = DI_API_VERSION;
+
+	if (type == DI_FEATURE) {
+		feature = diffuse_rec_next(&buf, sizeof(*feature), DI_FEATURE);
+		name = feature->name;
+	} else if (type == DI_CLASSIFIER) {
+		class = diffuse_rec_next(&buf, sizeof(*class), DI_CLASSIFIER);
+		name = class->name;
+	} else if (type == DI_EXPORT) {
+		exp = diffuse_rec_next(&buf, sizeof(*exp), DI_EXPORT);
+		name = exp->name;
+	}
+
+	av++; ac--;
+
+	/* Set name. */
+	if (ac) {
+		strncpy(name, *av, DI_MAX_NAME_STR_LEN - 1);
+		name[DI_MAX_NAME_STR_LEN - 1] = '\0';
+		av++; ac--;
+	} else {
+		errx(EX_USAGE, "need a feature/classifier/export name");
+	}
+
+	if (do_cmd(IP_DIFFUSE, base, (char *)buf - (char *)base))
+		err(1, "%s: setsockopt(%s)", "IP_DIFFUSE_DELETE", name);
+}
+
+static void
+check_option_val(int ac, char **av, struct di_option *opt)
+{
+	double val;
+	char *endptr;
+
+	if (opt == NULL)
+		errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
+
+	if (opt->arg_type == DI_OPTION_ARG_NOARG)
+		return;
+
+	if (ac > 0 && (*av)) {
+		if (opt->arg_type == DI_OPTION_ARG_UINT ||
+		    opt->arg_type == DI_OPTION_ARG_INT ||
+		    opt->arg_type == DI_OPTION_ARG_DOUBLE) {
+			if (opt->arg_type == DI_OPTION_ARG_UINT)
+				val = (double)strtoul(*av, &endptr, 0);
+			else if (opt->arg_type == DI_OPTION_ARG_INT)
+				val = (double)strtol(*av, &endptr, 0);
+			else
+				val = strtod(*av, &endptr);
+
+			if (*endptr) {
+				errx(EX_DATAERR, "value of option %s "
+				    "has wrong format at '%s'",
+				    opt->name, endptr);
+			}
+
+			if (val < opt->arg_min || val > opt->arg_max) {
+				errx(EX_DATAERR, "value of option %s "
+				    "not in allowed range %.2f to %.2f",
+				    opt->name, opt->arg_min,
+				    opt->arg_max);
+			}
+		}
+	} else {
+		if (opt->arg_max > opt->arg_min) {
+			errx(EX_USAGE, "option %s needs an argument "
+			    "%.2f ... %.2f", opt->name, opt->arg_min,
+			    opt->arg_max);
+		} else {
+			errx(EX_USAGE, "option %s needs an argument",
+			    opt->name);
+		}
+	}
+}
+
+/* Configuration of features. */
+static void
+feature_config(int ac, char **av)
+{
+	struct di_ctl_feature *feature;
+	struct di_feature_module *f;
+	struct di_oid *buf, *cmd, *base;
+	struct di_option *opt, *opts;
+	int fconf_len, len, size;
+
+	feature = NULL;
+	len = 0;
+	
+#ifdef DIFFUSE_DEBUG2
+	printf("diffuse feature config\n");
+#endif
+
+	/* Allocate space for 1 header + 1 feature. */
+	len = sizeof(struct di_oid) + sizeof(struct di_feature);
+	base = buf = safe_calloc(1, len);
+
+	/* All commands start with a CONFIG and a version. */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201111220656.pAM6ujse078726>