From 7e4a5049a909e56f254c0d76a7f2cd789a3254f8 Mon Sep 17 00:00:00 2001 From: ae Date: Wed, 9 Jun 2010 12:25:57 +0000 Subject: New netgraph node ng_patch(4). It performs data modification of packets passing through. Modifications are restricted to a subset of C language operations on unsigned integers of 8, 16, 32 or 64 bit size. These are: set to new value (=), addition (+=), subtraction (-=), multiplication (*=), division (/=), negation (= -), bitwise AND (&=), bitwise OR (|=), bitwise eXclusive OR (^=), shift left (<<=), shift right (>>=). Several operations are all applied to a packet sequentially in order they were specified by user. Submitted by: Maxim Ignatenko Vadim Goncharov Discussed with: net@ Approved by: mav (mentor) MFC after: 1 month --- sys/conf/NOTES | 1 + sys/conf/files | 1 + sys/conf/options | 1 + sys/modules/netgraph/Makefile | 1 + sys/modules/netgraph/patch/Makefile | 6 + sys/netgraph/ng_patch.c | 566 ++++++++++++++++++++++++++++++++++++ sys/netgraph/ng_patch.h | 107 +++++++ 7 files changed, 683 insertions(+) create mode 100644 sys/modules/netgraph/patch/Makefile create mode 100644 sys/netgraph/ng_patch.c create mode 100644 sys/netgraph/ng_patch.h (limited to 'sys') diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 6d12f99..8cad894 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -706,6 +706,7 @@ options NETGRAPH_MPPC_ENCRYPTION options NETGRAPH_NETFLOW options NETGRAPH_NAT options NETGRAPH_ONE2MANY +options NETGRAPG_PATCH options NETGRAPH_PIPE options NETGRAPH_PPP options NETGRAPH_PPPOE diff --git a/sys/conf/files b/sys/conf/files index 12f5e4d..0808e7f 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2470,6 +2470,7 @@ netgraph/ng_mppc.c optional netgraph_mppc_compression | \ netgraph/ng_nat.c optional netgraph_nat inet libalias netgraph/ng_one2many.c optional netgraph_one2many netgraph/ng_parse.c optional netgraph +netgraph/ng_patch.c optional netgraph_patch netgraph/ng_pipe.c optional netgraph_pipe netgraph/ng_ppp.c optional netgraph_ppp netgraph/ng_pppoe.c optional netgraph_pppoe diff --git a/sys/conf/options b/sys/conf/options index c58d901..9563cc8 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -486,6 +486,7 @@ NETGRAPH_MPPC_ENCRYPTION opt_netgraph.h NETGRAPH_NAT opt_netgraph.h NETGRAPH_NETFLOW opt_netgraph.h NETGRAPH_ONE2MANY opt_netgraph.h +NETGRAPH_PATCH opt_netgraph.h NETGRAPH_PIPE opt_netgraph.h NETGRAPH_PPP opt_netgraph.h NETGRAPH_PPPOE opt_netgraph.h diff --git a/sys/modules/netgraph/Makefile b/sys/modules/netgraph/Makefile index 70861cb..dc44ac7 100644 --- a/sys/modules/netgraph/Makefile +++ b/sys/modules/netgraph/Makefile @@ -35,6 +35,7 @@ SUBDIR= async \ netflow \ netgraph \ one2many \ + patch \ pipe \ ppp \ pppoe \ diff --git a/sys/modules/netgraph/patch/Makefile b/sys/modules/netgraph/patch/Makefile new file mode 100644 index 0000000..b6c4741 --- /dev/null +++ b/sys/modules/netgraph/patch/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= ng_patch +SRCS= ng_patch.c + +.include diff --git a/sys/netgraph/ng_patch.c b/sys/netgraph/ng_patch.c new file mode 100644 index 0000000..6969851 --- /dev/null +++ b/sys/netgraph/ng_patch.c @@ -0,0 +1,566 @@ +/*- + * Copyright (C) 2010 by Maxim Ignatenko + * All rights reserved. + * + * 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 /* be64toh(), htobe64() */ +#include +#include +#include +#include + +static ng_constructor_t ng_patch_constructor; +static ng_rcvmsg_t ng_patch_rcvmsg; +static ng_shutdown_t ng_patch_shutdown; +static ng_newhook_t ng_patch_newhook; +static ng_rcvdata_t ng_patch_rcvdata; +static ng_disconnect_t ng_patch_disconnect; + +#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0)) + +static int +ng_patch_config_getlen(const struct ng_parse_type *type, const u_char *start, + const u_char *buf) +{ + const struct ng_patch_config *p; + + p = (const struct ng_patch_config *)(buf - + OFFSETOF(struct ng_patch_config, ops)); + return (p->count); +} + +static const struct ng_parse_struct_field ng_patch_op_type_fields[] + = NG_PATCH_OP_TYPE_INFO; +static const struct ng_parse_type ng_patch_op_type = { + &ng_parse_struct_type, + &ng_patch_op_type_fields +}; + +static const struct ng_parse_array_info ng_patch_confarr_info = { + &ng_patch_op_type, + &ng_patch_config_getlen +}; +static const struct ng_parse_type ng_patch_confarr_type = { + &ng_parse_array_type, + &ng_patch_confarr_info +}; + +static const struct ng_parse_struct_field ng_patch_config_type_fields[] + = NG_PATCH_CONFIG_TYPE_INFO; +static const struct ng_parse_type ng_patch_config_type = { + &ng_parse_struct_type, + &ng_patch_config_type_fields +}; + +static const struct ng_parse_struct_field ng_patch_stats_fields[] + = NG_PATCH_STATS_TYPE_INFO; +static const struct ng_parse_type ng_patch_stats_type = { + &ng_parse_struct_type, + &ng_patch_stats_fields +}; + +static const struct ng_cmdlist ng_patch_cmdlist[] = { + { + NGM_PATCH_COOKIE, + NGM_PATCH_GETCONFIG, + "getconfig", + NULL, + &ng_patch_config_type + }, + { + NGM_PATCH_COOKIE, + NGM_PATCH_SETCONFIG, + "setconfig", + &ng_patch_config_type, + NULL + }, + { + NGM_PATCH_COOKIE, + NGM_PATCH_GET_STATS, + "getstats", + NULL, + &ng_patch_stats_type + }, + { + NGM_PATCH_COOKIE, + NGM_PATCH_CLR_STATS, + "clrstats", + NULL, + NULL + }, + { + NGM_PATCH_COOKIE, + NGM_PATCH_GETCLR_STATS, + "getclrstats", + NULL, + &ng_patch_stats_type + }, + { 0 } +}; + +static struct ng_type typestruct = { + .version = NG_ABI_VERSION, + .name = NG_PATCH_NODE_TYPE, + .constructor = ng_patch_constructor, + .rcvmsg = ng_patch_rcvmsg, + .shutdown = ng_patch_shutdown, + .newhook = ng_patch_newhook, + .rcvdata = ng_patch_rcvdata, + .disconnect = ng_patch_disconnect, + .cmdlist = ng_patch_cmdlist, +}; +NETGRAPH_INIT(patch, &typestruct); + +union patch_val { + uint8_t v1; + uint16_t v2; + uint32_t v4; + uint64_t v8; +}; + +struct ng_patch_priv { + hook_p in; + hook_p out; + struct ng_patch_config *config; + union patch_val *val; + struct ng_patch_stats stats; +}; +typedef struct ng_patch_priv *priv_p; + +#define NG_PATCH_CONF_SIZE(count) (sizeof(struct ng_patch_config) + \ + (count) * sizeof(struct ng_patch_op)) + +static void do_patch(priv_p conf, struct mbuf *m); + +static int +ng_patch_constructor(node_p node) +{ + priv_p privdata; + + privdata = malloc(sizeof(*privdata), M_NETGRAPH, M_WAIT | M_ZERO); + NG_NODE_SET_PRIVATE(node, privdata); + privdata->in = NULL; + privdata->out = NULL; + privdata->config = NULL; + return (0); +} + +static int +ng_patch_newhook(node_p node, hook_p hook, const char *name) +{ + const priv_p privp = NG_NODE_PRIVATE(node); + + if (strncmp(name, NG_PATCH_HOOK_IN, strlen(NG_PATCH_HOOK_IN)) == 0) { + privp->in = hook; + } else if (strncmp(name, NG_PATCH_HOOK_OUT, + strlen(NG_PATCH_HOOK_OUT)) == 0) { + privp->out = hook; + } else + return (EINVAL); + return(0); +} + +static int +ng_patch_rcvmsg(node_p node, item_p item, hook_p lasthook) +{ + const priv_p privp = NG_NODE_PRIVATE(node); + struct ng_patch_config *conf; + struct ng_mesg *msg; + struct ng_mesg *resp = NULL; + int i, clear = 0; + int error = 0; + + NGI_GET_MSG(item, msg); + switch (msg->header.typecookie) { + case NGM_PATCH_COOKIE: + switch (msg->header.cmd) { + case NGM_PATCH_GETCONFIG: + if (privp->config == NULL) + break; + NG_MKRESPONSE(resp, msg, + NG_PATCH_CONF_SIZE(privp->config->count), M_WAIT); + bcopy(privp->config, resp->data, + NG_PATCH_CONF_SIZE(privp->config->count)); + break; + case NGM_PATCH_SETCONFIG: + { + struct ng_patch_config *newconf; + union patch_val *newval; + + if (msg->header.arglen < sizeof(struct ng_patch_config)) { + error = EINVAL; + break; + } + + conf = (struct ng_patch_config *)msg->data; + if (msg->header.arglen < NG_PATCH_CONF_SIZE(conf->count)) { + error = EINVAL; + break; + } + + for(i = 0; i < conf->count; i++) { + switch(conf->ops[i].length) { + case 1: + case 2: + case 4: + case 8: + break; + default: + error = EINVAL; + break; + } + if (error != 0) + break; + } + + conf->csum_flags &= CSUM_IP | CSUM_TCP | CSUM_UDP | + CSUM_SCTP; + + if (error == 0) { + newconf = malloc(NG_PATCH_CONF_SIZE(conf->count), + M_NETGRAPH, M_WAIT); + newval = malloc(conf->count * sizeof(union patch_val), + M_NETGRAPH, M_WAIT); + for(i = 0; i < conf->count; i++) { + switch (conf->ops[i].length) { + case 1: + newval[i].v1 = conf->ops[i].value; + break; + case 2: + newval[i].v2 = conf->ops[i].value; + break; + case 4: + newval[i].v4 = conf->ops[i].value; + break; + case 8: + newval[i].v8 = conf->ops[i].value; + break; + } + } + bcopy(conf, newconf, NG_PATCH_CONF_SIZE(conf->count)); + if (privp->val != NULL) + free(privp->val, M_NETGRAPH); + privp->val = newval; + if (privp->config != NULL) + free(privp->config, M_NETGRAPH); + privp->config = newconf; + } + break; + } + case NGM_PATCH_GETCLR_STATS: + clear = 1; + /* FALLTHROUGH */ + case NGM_PATCH_GET_STATS: + NG_MKRESPONSE(resp, msg, sizeof(struct ng_patch_stats), + M_WAIT); + bcopy(&(privp->stats), resp->data, + sizeof(struct ng_patch_stats)); + if (clear == 0) + break; + /* else FALLTHROUGH */ + case NGM_PATCH_CLR_STATS: + bzero(&(privp->stats), sizeof(struct ng_patch_stats)); + break; + default: + error = EINVAL; + break; + } + break; + default: + error = EINVAL; + break; + } + + NG_RESPOND_MSG(error, node, item, resp); + NG_FREE_MSG(msg); + return(error); +} + +static void +do_patch(priv_p privp, struct mbuf *m) +{ + struct ng_patch_config *conf = privp->config; + uint64_t buf; + int i, patched = 0; + + for(i = 0; i < conf->count; i++) { + if (conf->ops[i].offset + conf->ops[i].length > m->m_pkthdr.len) + continue; + + /* for "=" operation we don't need to copy data from mbuf */ + if (conf->ops[i].mode != NG_PATCH_MODE_SET) { + m_copydata(m, conf->ops[i].offset, + conf->ops[i].length, (caddr_t)&buf); + } + + switch (conf->ops[i].length) { + case 1: + switch (conf->ops[i].mode) { + case NG_PATCH_MODE_SET: + *((uint8_t *)&buf) = privp->val[i].v1; + break; + case NG_PATCH_MODE_ADD: + *((uint8_t *)&buf) += privp->val[i].v1; + break; + case NG_PATCH_MODE_SUB: + *((uint8_t *)&buf) -= privp->val[i].v1; + break; + case NG_PATCH_MODE_MUL: + *((uint8_t *)&buf) *= privp->val[i].v1; + break; + case NG_PATCH_MODE_DIV: + *((uint8_t *)&buf) /= privp->val[i].v1; + break; + case NG_PATCH_MODE_NEG: + *((int8_t *)&buf) = - *((int8_t *)&buf); + break; + case NG_PATCH_MODE_AND: + *((uint8_t *)&buf) &= privp->val[i].v1; + break; + case NG_PATCH_MODE_OR: + *((uint8_t *)&buf) |= privp->val[i].v1; + break; + case NG_PATCH_MODE_XOR: + *((uint8_t *)&buf) ^= privp->val[i].v1; + break; + case NG_PATCH_MODE_SHL: + *((uint8_t *)&buf) <<= privp->val[i].v1; + break; + case NG_PATCH_MODE_SHR: + *((uint8_t *)&buf) >>= privp->val[i].v1; + break; + } + break; + case 2: + *((int16_t *)&buf) = ntohs(*((int16_t *)&buf)); + switch (conf->ops[i].mode) { + case NG_PATCH_MODE_SET: + *((uint16_t *)&buf) = privp->val[i].v2; + break; + case NG_PATCH_MODE_ADD: + *((uint16_t *)&buf) += privp->val[i].v2; + break; + case NG_PATCH_MODE_SUB: + *((uint16_t *)&buf) -= privp->val[i].v2; + break; + case NG_PATCH_MODE_MUL: + *((uint16_t *)&buf) *= privp->val[i].v2; + break; + case NG_PATCH_MODE_DIV: + *((uint16_t *)&buf) /= privp->val[i].v2; + break; + case NG_PATCH_MODE_NEG: + *((int16_t *)&buf) = - *((int16_t *)&buf); + break; + case NG_PATCH_MODE_AND: + *((uint16_t *)&buf) &= privp->val[i].v2; + break; + case NG_PATCH_MODE_OR: + *((uint16_t *)&buf) |= privp->val[i].v2; + break; + case NG_PATCH_MODE_XOR: + *((uint16_t *)&buf) ^= privp->val[i].v2; + break; + case NG_PATCH_MODE_SHL: + *((uint16_t *)&buf) <<= privp->val[i].v2; + break; + case NG_PATCH_MODE_SHR: + *((uint16_t *)&buf) >>= privp->val[i].v2; + break; + } + *((int16_t *)&buf) = htons(*((int16_t *)&buf)); + break; + case 4: + *((int32_t *)&buf) = ntohl(*((int32_t *)&buf)); + switch (conf->ops[i].mode) { + case NG_PATCH_MODE_SET: + *((uint32_t *)&buf) = privp->val[i].v4; + break; + case NG_PATCH_MODE_ADD: + *((uint32_t *)&buf) += privp->val[i].v4; + break; + case NG_PATCH_MODE_SUB: + *((uint32_t *)&buf) -= privp->val[i].v4; + break; + case NG_PATCH_MODE_MUL: + *((uint32_t *)&buf) *= privp->val[i].v4; + break; + case NG_PATCH_MODE_DIV: + *((uint32_t *)&buf) /= privp->val[i].v4; + break; + case NG_PATCH_MODE_NEG: + *((int32_t *)&buf) = - *((int32_t *)&buf); + break; + case NG_PATCH_MODE_AND: + *((uint32_t *)&buf) &= privp->val[i].v4; + break; + case NG_PATCH_MODE_OR: + *((uint32_t *)&buf) |= privp->val[i].v4; + break; + case NG_PATCH_MODE_XOR: + *((uint32_t *)&buf) ^= privp->val[i].v4; + break; + case NG_PATCH_MODE_SHL: + *((uint32_t *)&buf) <<= privp->val[i].v4; + break; + case NG_PATCH_MODE_SHR: + *((uint32_t *)&buf) >>= privp->val[i].v4; + break; + } + *((int32_t *)&buf) = htonl(*((int32_t *)&buf)); + break; + case 8: + *((int64_t *)&buf) = be64toh(*((int64_t *)&buf)); + switch (conf->ops[i].mode) { + case NG_PATCH_MODE_SET: + *((uint64_t *)&buf) = privp->val[i].v8; + break; + case NG_PATCH_MODE_ADD: + *((uint64_t *)&buf) += privp->val[i].v8; + break; + case NG_PATCH_MODE_SUB: + *((uint64_t *)&buf) -= privp->val[i].v8; + break; + case NG_PATCH_MODE_MUL: + *((uint64_t *)&buf) *= privp->val[i].v8; + break; + case NG_PATCH_MODE_DIV: + *((uint64_t *)&buf) /= privp->val[i].v8; + break; + case NG_PATCH_MODE_NEG: + *((int64_t *)&buf) = - *((int64_t *)&buf); + break; + case NG_PATCH_MODE_AND: + *((uint64_t *)&buf) &= privp->val[i].v8; + break; + case NG_PATCH_MODE_OR: + *((uint64_t *)&buf) |= privp->val[i].v8; + break; + case NG_PATCH_MODE_XOR: + *((uint64_t *)&buf) ^= privp->val[i].v8; + break; + case NG_PATCH_MODE_SHL: + *((uint64_t *)&buf) <<= privp->val[i].v8; + break; + case NG_PATCH_MODE_SHR: + *((uint64_t *)&buf) >>= privp->val[i].v8; + break; + } + *((int64_t *)&buf) = htobe64(*((int64_t *)&buf)); + break; + } + + m_copyback(m, conf->ops[i].offset, conf->ops[i].length, + (caddr_t)&buf); + patched = 1; + } + if (patched > 0) + privp->stats.patched++; +} + +static int +ng_patch_rcvdata(hook_p hook, item_p item) +{ + const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); + struct mbuf *m; + hook_p target; + int error; + + priv->stats.received++; + NGI_GET_M(item, m); + if (priv->config != NULL && hook == priv->in && + (m->m_flags & M_PKTHDR) != 0) { + m = m_unshare(m,M_NOWAIT); + if (m == NULL) { + priv->stats.dropped++; + NG_FREE_ITEM(item); + return (ENOMEM); + } + do_patch(priv, m); + m->m_flags |= priv->config->csum_flags; + } + + target = NULL; + if (hook == priv->in) { + /* return frames on 'in' hook if 'out' not connected */ + if (priv->out != NULL) + target = priv->out; + else + target = priv->in; + } + if (hook == priv->out && priv->in != NULL) + target = priv->in; + + if (target == NULL) { + priv->stats.dropped++; + NG_FREE_ITEM(item); + NG_FREE_M(m); + return (0); + } + NG_FWD_NEW_DATA(error, item, target, m); + return (error); +} + +static int +ng_patch_shutdown(node_p node) +{ + const priv_p privdata = NG_NODE_PRIVATE(node); + + if (privdata->val != NULL) + free(privdata->val, M_NETGRAPH); + if (privdata->config != NULL) + free(privdata->config, M_NETGRAPH); + NG_NODE_SET_PRIVATE(node, NULL); + NG_NODE_UNREF(node); + free(privdata, M_NETGRAPH); + return (0); +} + +static int +ng_patch_disconnect(hook_p hook) +{ + priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); + + if (hook == priv->in) { + priv->in = NULL; + } + if (hook == priv->out) { + priv->out = NULL; + } + if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) + && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) /* already shutting down? */ + ng_rmnode_self(NG_HOOK_NODE(hook)); + return (0); +} + diff --git a/sys/netgraph/ng_patch.h b/sys/netgraph/ng_patch.h new file mode 100644 index 0000000..fedde07 --- /dev/null +++ b/sys/netgraph/ng_patch.h @@ -0,0 +1,107 @@ +/*- + * Copyright (C) 2010 by Maxim Ignatenko + * All rights reserved. + * + * 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$ + */ + +#ifndef _NETGRAPH_NG_PATCH_H_ +#define _NETGRAPH_NG_PATCH_H_ + +/* Node type name. */ +#define NG_PATCH_NODE_TYPE "patch" + +/* Node type cookie. */ +#define NGM_PATCH_COOKIE 1262445509 + +/* Hook names */ +#define NG_PATCH_HOOK_IN "in" +#define NG_PATCH_HOOK_OUT "out" + +/* Netgraph commands understood by this node type */ +enum { + NGM_PATCH_SETCONFIG = 1, + NGM_PATCH_GETCONFIG, + NGM_PATCH_GET_STATS, + NGM_PATCH_CLR_STATS, + NGM_PATCH_GETCLR_STATS +}; + +/* Patching modes */ +enum { + NG_PATCH_MODE_SET = 1, + NG_PATCH_MODE_ADD = 2, + NG_PATCH_MODE_SUB = 3, + NG_PATCH_MODE_MUL = 4, + NG_PATCH_MODE_DIV = 5, + NG_PATCH_MODE_NEG = 6, + NG_PATCH_MODE_AND = 7, + NG_PATCH_MODE_OR = 8, + NG_PATCH_MODE_XOR = 9, + NG_PATCH_MODE_SHL = 10, + NG_PATCH_MODE_SHR = 11 +}; + +struct ng_patch_op { + uint64_t value; + uint32_t offset; + uint16_t length; /* 1,2,4 or 8 (bytes) */ + uint16_t mode; +}; + +#define NG_PATCH_OP_TYPE_INFO { \ + { "value", &ng_parse_uint64_type }, \ + { "offset", &ng_parse_uint32_type }, \ + { "length", &ng_parse_uint16_type }, \ + { "mode", &ng_parse_uint16_type }, \ + { NULL } \ +} + +struct ng_patch_config { + uint32_t count; + uint32_t csum_flags; + struct ng_patch_op ops[]; +}; + +#define NG_PATCH_CONFIG_TYPE_INFO { \ + { "count", &ng_parse_uint32_type }, \ + { "csum_flags", &ng_parse_uint32_type }, \ + { "ops", &ng_patch_confarr_type }, \ + { NULL } \ +} + +struct ng_patch_stats { + uint64_t received; + uint64_t patched; + uint64_t dropped; +}; + +#define NG_PATCH_STATS_TYPE_INFO { \ + { "received", &ng_parse_uint64_type }, \ + { "patched", &ng_parse_uint64_type }, \ + { "dropped", &ng_parse_uint64_type }, \ + { NULL } \ +} + +#endif /* _NETGRAPH_NG_PATCH_H_ */ -- cgit v1.1