From owner-svn-src-projects@FreeBSD.ORG Tue Nov 22 06:56:46 2011 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1B4EB106566B; Tue, 22 Nov 2011 06:56:46 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 096408FC16; Tue, 22 Nov 2011 06:56:46 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id pAM6ukZS078734; Tue, 22 Nov 2011 06:56:46 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id pAM6ujse078726; Tue, 22 Nov 2011 06:56:45 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <201111220656.pAM6ujse078726@svn.freebsd.org> From: Lawrence Stewart Date: Tue, 22 Nov 2011 06:56:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r227813 - in projects/diffused_head: etc/mtree include sbin/ipfw X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 22 Nov 2011 06:56:46 -0000 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 config "); +} + +void +print_classifier_usage() +{ + + printf("ipfw mlclass config [confirm]"); +} + +void +print_export_usage() +{ + + printf("ipfw export config target ://: "); + printf("[confirm ] [action ] [action-params ] "); + printf("[min-batch ] [max-batch ] "); + printf("[max-delay ]\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 ***