1/*- 2 * Copyright (C) 2010 by Maxim Ignatenko <gelraen.ua@gmail.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h>
| 1/*- 2 * Copyright (C) 2010 by Maxim Ignatenko <gelraen.ua@gmail.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h>
|
29__FBSDID("$FreeBSD: head/sys/netgraph/ng_patch.c 208946 2010-06-09 12:25:57Z ae $");
| 29__FBSDID("$FreeBSD: head/sys/netgraph/ng_patch.c 208989 2010-06-10 16:45:30Z ae $");
|
30 31#include <sys/param.h> 32#include <sys/kernel.h>
| 30 31#include <sys/param.h> 32#include <sys/kernel.h>
|
33#include <sys/mbuf.h> 34#include <sys/malloc.h>
| |
35#include <sys/ctype.h>
| 33#include <sys/ctype.h>
|
36#include <sys/errno.h>
| |
37#include <sys/endian.h> /* be64toh(), htobe64() */
| 34#include <sys/endian.h> /* be64toh(), htobe64() */
|
| 35#include <sys/errno.h> 36#include <sys/malloc.h> 37#include <sys/mbuf.h>
|
38#include <netgraph/ng_message.h> 39#include <netgraph/ng_parse.h> 40#include <netgraph/ng_patch.h> 41#include <netgraph/netgraph.h> 42 43static ng_constructor_t ng_patch_constructor; 44static ng_rcvmsg_t ng_patch_rcvmsg; 45static ng_shutdown_t ng_patch_shutdown; 46static ng_newhook_t ng_patch_newhook; 47static ng_rcvdata_t ng_patch_rcvdata; 48static ng_disconnect_t ng_patch_disconnect; 49
| 38#include <netgraph/ng_message.h> 39#include <netgraph/ng_parse.h> 40#include <netgraph/ng_patch.h> 41#include <netgraph/netgraph.h> 42 43static ng_constructor_t ng_patch_constructor; 44static ng_rcvmsg_t ng_patch_rcvmsg; 45static ng_shutdown_t ng_patch_shutdown; 46static ng_newhook_t ng_patch_newhook; 47static ng_rcvdata_t ng_patch_rcvdata; 48static ng_disconnect_t ng_patch_disconnect; 49
|
50#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0))
| 50#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0))
|
51 52static int
| 51 52static int
|
53ng_patch_config_getlen(const struct ng_parse_type *type, const u_char *start, 54 const u_char *buf)
| 53ng_patch_config_getlen(const struct ng_parse_type *type, 54 const u_char *start, const u_char *buf)
|
55{ 56 const struct ng_patch_config *p; 57 58 p = (const struct ng_patch_config *)(buf - 59 OFFSETOF(struct ng_patch_config, ops)); 60 return (p->count); 61} 62 63static const struct ng_parse_struct_field ng_patch_op_type_fields[] 64 = NG_PATCH_OP_TYPE_INFO; 65static const struct ng_parse_type ng_patch_op_type = { 66 &ng_parse_struct_type, 67 &ng_patch_op_type_fields 68}; 69 70static const struct ng_parse_array_info ng_patch_confarr_info = { 71 &ng_patch_op_type, 72 &ng_patch_config_getlen 73}; 74static const struct ng_parse_type ng_patch_confarr_type = { 75 &ng_parse_array_type, 76 &ng_patch_confarr_info 77}; 78 79static const struct ng_parse_struct_field ng_patch_config_type_fields[] 80 = NG_PATCH_CONFIG_TYPE_INFO; 81static const struct ng_parse_type ng_patch_config_type = { 82 &ng_parse_struct_type, 83 &ng_patch_config_type_fields 84}; 85 86static const struct ng_parse_struct_field ng_patch_stats_fields[] 87 = NG_PATCH_STATS_TYPE_INFO; 88static const struct ng_parse_type ng_patch_stats_type = { 89 &ng_parse_struct_type, 90 &ng_patch_stats_fields 91}; 92 93static const struct ng_cmdlist ng_patch_cmdlist[] = { 94 { 95 NGM_PATCH_COOKIE, 96 NGM_PATCH_GETCONFIG, 97 "getconfig", 98 NULL, 99 &ng_patch_config_type 100 }, 101 { 102 NGM_PATCH_COOKIE, 103 NGM_PATCH_SETCONFIG, 104 "setconfig", 105 &ng_patch_config_type, 106 NULL 107 }, 108 { 109 NGM_PATCH_COOKIE, 110 NGM_PATCH_GET_STATS, 111 "getstats", 112 NULL, 113 &ng_patch_stats_type 114 }, 115 { 116 NGM_PATCH_COOKIE, 117 NGM_PATCH_CLR_STATS, 118 "clrstats", 119 NULL, 120 NULL 121 }, 122 { 123 NGM_PATCH_COOKIE, 124 NGM_PATCH_GETCLR_STATS, 125 "getclrstats", 126 NULL, 127 &ng_patch_stats_type 128 }, 129 { 0 } 130}; 131 132static struct ng_type typestruct = { 133 .version = NG_ABI_VERSION, 134 .name = NG_PATCH_NODE_TYPE, 135 .constructor = ng_patch_constructor, 136 .rcvmsg = ng_patch_rcvmsg, 137 .shutdown = ng_patch_shutdown, 138 .newhook = ng_patch_newhook, 139 .rcvdata = ng_patch_rcvdata, 140 .disconnect = ng_patch_disconnect, 141 .cmdlist = ng_patch_cmdlist, 142}; 143NETGRAPH_INIT(patch, &typestruct); 144 145union patch_val { 146 uint8_t v1; 147 uint16_t v2; 148 uint32_t v4; 149 uint64_t v8; 150}; 151 152struct ng_patch_priv { 153 hook_p in; 154 hook_p out; 155 struct ng_patch_config *config; 156 union patch_val *val; 157 struct ng_patch_stats stats; 158}; 159typedef struct ng_patch_priv *priv_p; 160
| 55{ 56 const struct ng_patch_config *p; 57 58 p = (const struct ng_patch_config *)(buf - 59 OFFSETOF(struct ng_patch_config, ops)); 60 return (p->count); 61} 62 63static const struct ng_parse_struct_field ng_patch_op_type_fields[] 64 = NG_PATCH_OP_TYPE_INFO; 65static const struct ng_parse_type ng_patch_op_type = { 66 &ng_parse_struct_type, 67 &ng_patch_op_type_fields 68}; 69 70static const struct ng_parse_array_info ng_patch_confarr_info = { 71 &ng_patch_op_type, 72 &ng_patch_config_getlen 73}; 74static const struct ng_parse_type ng_patch_confarr_type = { 75 &ng_parse_array_type, 76 &ng_patch_confarr_info 77}; 78 79static const struct ng_parse_struct_field ng_patch_config_type_fields[] 80 = NG_PATCH_CONFIG_TYPE_INFO; 81static const struct ng_parse_type ng_patch_config_type = { 82 &ng_parse_struct_type, 83 &ng_patch_config_type_fields 84}; 85 86static const struct ng_parse_struct_field ng_patch_stats_fields[] 87 = NG_PATCH_STATS_TYPE_INFO; 88static const struct ng_parse_type ng_patch_stats_type = { 89 &ng_parse_struct_type, 90 &ng_patch_stats_fields 91}; 92 93static const struct ng_cmdlist ng_patch_cmdlist[] = { 94 { 95 NGM_PATCH_COOKIE, 96 NGM_PATCH_GETCONFIG, 97 "getconfig", 98 NULL, 99 &ng_patch_config_type 100 }, 101 { 102 NGM_PATCH_COOKIE, 103 NGM_PATCH_SETCONFIG, 104 "setconfig", 105 &ng_patch_config_type, 106 NULL 107 }, 108 { 109 NGM_PATCH_COOKIE, 110 NGM_PATCH_GET_STATS, 111 "getstats", 112 NULL, 113 &ng_patch_stats_type 114 }, 115 { 116 NGM_PATCH_COOKIE, 117 NGM_PATCH_CLR_STATS, 118 "clrstats", 119 NULL, 120 NULL 121 }, 122 { 123 NGM_PATCH_COOKIE, 124 NGM_PATCH_GETCLR_STATS, 125 "getclrstats", 126 NULL, 127 &ng_patch_stats_type 128 }, 129 { 0 } 130}; 131 132static struct ng_type typestruct = { 133 .version = NG_ABI_VERSION, 134 .name = NG_PATCH_NODE_TYPE, 135 .constructor = ng_patch_constructor, 136 .rcvmsg = ng_patch_rcvmsg, 137 .shutdown = ng_patch_shutdown, 138 .newhook = ng_patch_newhook, 139 .rcvdata = ng_patch_rcvdata, 140 .disconnect = ng_patch_disconnect, 141 .cmdlist = ng_patch_cmdlist, 142}; 143NETGRAPH_INIT(patch, &typestruct); 144 145union patch_val { 146 uint8_t v1; 147 uint16_t v2; 148 uint32_t v4; 149 uint64_t v8; 150}; 151 152struct ng_patch_priv { 153 hook_p in; 154 hook_p out; 155 struct ng_patch_config *config; 156 union patch_val *val; 157 struct ng_patch_stats stats; 158}; 159typedef struct ng_patch_priv *priv_p; 160
|
161#define NG_PATCH_CONF_SIZE(count) (sizeof(struct ng_patch_config) + \
| 161#define NG_PATCH_CONF_SIZE(count) (sizeof(struct ng_patch_config) + \
|
162 (count) * sizeof(struct ng_patch_op)) 163 164static void do_patch(priv_p conf, struct mbuf *m); 165 166static int 167ng_patch_constructor(node_p node) 168{ 169 priv_p privdata; 170 171 privdata = malloc(sizeof(*privdata), M_NETGRAPH, M_WAIT | M_ZERO); 172 NG_NODE_SET_PRIVATE(node, privdata); 173 privdata->in = NULL; 174 privdata->out = NULL; 175 privdata->config = NULL; 176 return (0); 177} 178 179static int 180ng_patch_newhook(node_p node, hook_p hook, const char *name) 181{ 182 const priv_p privp = NG_NODE_PRIVATE(node); 183 184 if (strncmp(name, NG_PATCH_HOOK_IN, strlen(NG_PATCH_HOOK_IN)) == 0) { 185 privp->in = hook; 186 } else if (strncmp(name, NG_PATCH_HOOK_OUT, 187 strlen(NG_PATCH_HOOK_OUT)) == 0) { 188 privp->out = hook; 189 } else 190 return (EINVAL); 191 return(0); 192} 193 194static int 195ng_patch_rcvmsg(node_p node, item_p item, hook_p lasthook) 196{ 197 const priv_p privp = NG_NODE_PRIVATE(node);
| 162 (count) * sizeof(struct ng_patch_op)) 163 164static void do_patch(priv_p conf, struct mbuf *m); 165 166static int 167ng_patch_constructor(node_p node) 168{ 169 priv_p privdata; 170 171 privdata = malloc(sizeof(*privdata), M_NETGRAPH, M_WAIT | M_ZERO); 172 NG_NODE_SET_PRIVATE(node, privdata); 173 privdata->in = NULL; 174 privdata->out = NULL; 175 privdata->config = NULL; 176 return (0); 177} 178 179static int 180ng_patch_newhook(node_p node, hook_p hook, const char *name) 181{ 182 const priv_p privp = NG_NODE_PRIVATE(node); 183 184 if (strncmp(name, NG_PATCH_HOOK_IN, strlen(NG_PATCH_HOOK_IN)) == 0) { 185 privp->in = hook; 186 } else if (strncmp(name, NG_PATCH_HOOK_OUT, 187 strlen(NG_PATCH_HOOK_OUT)) == 0) { 188 privp->out = hook; 189 } else 190 return (EINVAL); 191 return(0); 192} 193 194static int 195ng_patch_rcvmsg(node_p node, item_p item, hook_p lasthook) 196{ 197 const priv_p privp = NG_NODE_PRIVATE(node);
|
198 struct ng_patch_config *conf;
| 198 struct ng_patch_config *conf, *newconf; 199 union patch_val *newval;
|
199 struct ng_mesg *msg;
| 200 struct ng_mesg *msg;
|
200 struct ng_mesg *resp = NULL; 201 int i, clear = 0; 202 int error = 0;
| 201 struct ng_mesg *resp; 202 int i, clear, error;
|
203
| 203
|
| 204 clear = error = 0; 205 resp = NULL;
|
204 NGI_GET_MSG(item, msg); 205 switch (msg->header.typecookie) { 206 case NGM_PATCH_COOKIE: 207 switch (msg->header.cmd) { 208 case NGM_PATCH_GETCONFIG: 209 if (privp->config == NULL) 210 break; 211 NG_MKRESPONSE(resp, msg, 212 NG_PATCH_CONF_SIZE(privp->config->count), M_WAIT); 213 bcopy(privp->config, resp->data, 214 NG_PATCH_CONF_SIZE(privp->config->count)); 215 break; 216 case NGM_PATCH_SETCONFIG: 217 {
| 206 NGI_GET_MSG(item, msg); 207 switch (msg->header.typecookie) { 208 case NGM_PATCH_COOKIE: 209 switch (msg->header.cmd) { 210 case NGM_PATCH_GETCONFIG: 211 if (privp->config == NULL) 212 break; 213 NG_MKRESPONSE(resp, msg, 214 NG_PATCH_CONF_SIZE(privp->config->count), M_WAIT); 215 bcopy(privp->config, resp->data, 216 NG_PATCH_CONF_SIZE(privp->config->count)); 217 break; 218 case NGM_PATCH_SETCONFIG: 219 {
|
218 struct ng_patch_config *newconf; 219 union patch_val *newval; 220 221 if (msg->header.arglen < sizeof(struct ng_patch_config)) {
| 220 if (msg->header.arglen < 221 sizeof(struct ng_patch_config)) {
|
222 error = EINVAL; 223 break; 224 } 225 226 conf = (struct ng_patch_config *)msg->data;
| 222 error = EINVAL; 223 break; 224 } 225 226 conf = (struct ng_patch_config *)msg->data;
|
227 if (msg->header.arglen < NG_PATCH_CONF_SIZE(conf->count)) {
| 227 if (msg->header.arglen < 228 NG_PATCH_CONF_SIZE(conf->count)) {
|
228 error = EINVAL; 229 break; 230 } 231 232 for(i = 0; i < conf->count; i++) { 233 switch(conf->ops[i].length) { 234 case 1: 235 case 2: 236 case 4: 237 case 8: 238 break; 239 default: 240 error = EINVAL; 241 break; 242 } 243 if (error != 0) 244 break; 245 } 246 247 conf->csum_flags &= CSUM_IP | CSUM_TCP | CSUM_UDP | 248 CSUM_SCTP; 249 250 if (error == 0) {
| 229 error = EINVAL; 230 break; 231 } 232 233 for(i = 0; i < conf->count; i++) { 234 switch(conf->ops[i].length) { 235 case 1: 236 case 2: 237 case 4: 238 case 8: 239 break; 240 default: 241 error = EINVAL; 242 break; 243 } 244 if (error != 0) 245 break; 246 } 247 248 conf->csum_flags &= CSUM_IP | CSUM_TCP | CSUM_UDP | 249 CSUM_SCTP; 250 251 if (error == 0) {
|
251 newconf = malloc(NG_PATCH_CONF_SIZE(conf->count),
| 252 newconf = malloc( 253 NG_PATCH_CONF_SIZE(conf->count),
|
252 M_NETGRAPH, M_WAIT);
| 254 M_NETGRAPH, M_WAIT);
|
253 newval = malloc(conf->count * sizeof(union patch_val), 254 M_NETGRAPH, M_WAIT);
| 255 newval = malloc(conf->count * 256 sizeof(union patch_val), M_NETGRAPH, 257 M_WAIT);
|
255 for(i = 0; i < conf->count; i++) { 256 switch (conf->ops[i].length) { 257 case 1:
| 258 for(i = 0; i < conf->count; i++) { 259 switch (conf->ops[i].length) { 260 case 1:
|
258 newval[i].v1 = conf->ops[i].value;
| 261 newval[i].v1 = 262 conf->ops[i].value;
|
259 break; 260 case 2:
| 263 break; 264 case 2:
|
261 newval[i].v2 = conf->ops[i].value;
| 265 newval[i].v2 = 266 conf->ops[i].value;
|
262 break; 263 case 4:
| 267 break; 268 case 4:
|
264 newval[i].v4 = conf->ops[i].value;
| 269 newval[i].v4 = 270 conf->ops[i].value;
|
265 break; 266 case 8:
| 271 break; 272 case 8:
|
267 newval[i].v8 = conf->ops[i].value;
| 273 newval[i].v8 = 274 conf->ops[i].value;
|
268 break; 269 } 270 }
| 275 break; 276 } 277 }
|
271 bcopy(conf, newconf, NG_PATCH_CONF_SIZE(conf->count));
| 278 bcopy(conf, newconf, 279 NG_PATCH_CONF_SIZE(conf->count));
|
272 if (privp->val != NULL) 273 free(privp->val, M_NETGRAPH); 274 privp->val = newval; 275 if (privp->config != NULL) 276 free(privp->config, M_NETGRAPH); 277 privp->config = newconf; 278 } 279 break; 280 } 281 case NGM_PATCH_GETCLR_STATS: 282 clear = 1; 283 /* FALLTHROUGH */ 284 case NGM_PATCH_GET_STATS: 285 NG_MKRESPONSE(resp, msg, sizeof(struct ng_patch_stats), 286 M_WAIT); 287 bcopy(&(privp->stats), resp->data, 288 sizeof(struct ng_patch_stats)); 289 if (clear == 0) 290 break; 291 /* else FALLTHROUGH */ 292 case NGM_PATCH_CLR_STATS: 293 bzero(&(privp->stats), sizeof(struct ng_patch_stats)); 294 break; 295 default: 296 error = EINVAL; 297 break; 298 } 299 break; 300 default: 301 error = EINVAL; 302 break; 303 } 304 305 NG_RESPOND_MSG(error, node, item, resp); 306 NG_FREE_MSG(msg); 307 return(error); 308} 309 310static void 311do_patch(priv_p privp, struct mbuf *m) 312{
| 280 if (privp->val != NULL) 281 free(privp->val, M_NETGRAPH); 282 privp->val = newval; 283 if (privp->config != NULL) 284 free(privp->config, M_NETGRAPH); 285 privp->config = newconf; 286 } 287 break; 288 } 289 case NGM_PATCH_GETCLR_STATS: 290 clear = 1; 291 /* FALLTHROUGH */ 292 case NGM_PATCH_GET_STATS: 293 NG_MKRESPONSE(resp, msg, sizeof(struct ng_patch_stats), 294 M_WAIT); 295 bcopy(&(privp->stats), resp->data, 296 sizeof(struct ng_patch_stats)); 297 if (clear == 0) 298 break; 299 /* else FALLTHROUGH */ 300 case NGM_PATCH_CLR_STATS: 301 bzero(&(privp->stats), sizeof(struct ng_patch_stats)); 302 break; 303 default: 304 error = EINVAL; 305 break; 306 } 307 break; 308 default: 309 error = EINVAL; 310 break; 311 } 312 313 NG_RESPOND_MSG(error, node, item, resp); 314 NG_FREE_MSG(msg); 315 return(error); 316} 317 318static void 319do_patch(priv_p privp, struct mbuf *m) 320{
|
313 struct ng_patch_config *conf = privp->config;
| 321 struct ng_patch_config *conf;
|
314 uint64_t buf;
| 322 uint64_t buf;
|
315 int i, patched = 0;
| 323 int i, patched;
|
316
| 324
|
| 325 conf = privp->config; 326 patched = 0;
|
317 for(i = 0; i < conf->count; i++) {
| 327 for(i = 0; i < conf->count; i++) {
|
318 if (conf->ops[i].offset + conf->ops[i].length > m->m_pkthdr.len)
| 328 if (conf->ops[i].offset + conf->ops[i].length > 329 m->m_pkthdr.len)
|
319 continue; 320 321 /* for "=" operation we don't need to copy data from mbuf */ 322 if (conf->ops[i].mode != NG_PATCH_MODE_SET) { 323 m_copydata(m, conf->ops[i].offset, 324 conf->ops[i].length, (caddr_t)&buf); 325 }
| 330 continue; 331 332 /* for "=" operation we don't need to copy data from mbuf */ 333 if (conf->ops[i].mode != NG_PATCH_MODE_SET) { 334 m_copydata(m, conf->ops[i].offset, 335 conf->ops[i].length, (caddr_t)&buf); 336 }
|
326
| 337
|
327 switch (conf->ops[i].length) { 328 case 1: 329 switch (conf->ops[i].mode) { 330 case NG_PATCH_MODE_SET: 331 *((uint8_t *)&buf) = privp->val[i].v1; 332 break; 333 case NG_PATCH_MODE_ADD: 334 *((uint8_t *)&buf) += privp->val[i].v1; 335 break; 336 case NG_PATCH_MODE_SUB: 337 *((uint8_t *)&buf) -= privp->val[i].v1; 338 break; 339 case NG_PATCH_MODE_MUL: 340 *((uint8_t *)&buf) *= privp->val[i].v1; 341 break; 342 case NG_PATCH_MODE_DIV: 343 *((uint8_t *)&buf) /= privp->val[i].v1; 344 break; 345 case NG_PATCH_MODE_NEG: 346 *((int8_t *)&buf) = - *((int8_t *)&buf); 347 break; 348 case NG_PATCH_MODE_AND: 349 *((uint8_t *)&buf) &= privp->val[i].v1; 350 break; 351 case NG_PATCH_MODE_OR: 352 *((uint8_t *)&buf) |= privp->val[i].v1; 353 break; 354 case NG_PATCH_MODE_XOR: 355 *((uint8_t *)&buf) ^= privp->val[i].v1; 356 break; 357 case NG_PATCH_MODE_SHL: 358 *((uint8_t *)&buf) <<= privp->val[i].v1; 359 break; 360 case NG_PATCH_MODE_SHR: 361 *((uint8_t *)&buf) >>= privp->val[i].v1; 362 break; 363 } 364 break; 365 case 2: 366 *((int16_t *)&buf) = ntohs(*((int16_t *)&buf)); 367 switch (conf->ops[i].mode) { 368 case NG_PATCH_MODE_SET: 369 *((uint16_t *)&buf) = privp->val[i].v2; 370 break; 371 case NG_PATCH_MODE_ADD: 372 *((uint16_t *)&buf) += privp->val[i].v2; 373 break; 374 case NG_PATCH_MODE_SUB: 375 *((uint16_t *)&buf) -= privp->val[i].v2; 376 break; 377 case NG_PATCH_MODE_MUL: 378 *((uint16_t *)&buf) *= privp->val[i].v2; 379 break; 380 case NG_PATCH_MODE_DIV: 381 *((uint16_t *)&buf) /= privp->val[i].v2; 382 break; 383 case NG_PATCH_MODE_NEG: 384 *((int16_t *)&buf) = - *((int16_t *)&buf); 385 break; 386 case NG_PATCH_MODE_AND: 387 *((uint16_t *)&buf) &= privp->val[i].v2; 388 break; 389 case NG_PATCH_MODE_OR: 390 *((uint16_t *)&buf) |= privp->val[i].v2; 391 break; 392 case NG_PATCH_MODE_XOR: 393 *((uint16_t *)&buf) ^= privp->val[i].v2; 394 break; 395 case NG_PATCH_MODE_SHL: 396 *((uint16_t *)&buf) <<= privp->val[i].v2; 397 break; 398 case NG_PATCH_MODE_SHR: 399 *((uint16_t *)&buf) >>= privp->val[i].v2; 400 break; 401 } 402 *((int16_t *)&buf) = htons(*((int16_t *)&buf)); 403 break; 404 case 4: 405 *((int32_t *)&buf) = ntohl(*((int32_t *)&buf)); 406 switch (conf->ops[i].mode) { 407 case NG_PATCH_MODE_SET: 408 *((uint32_t *)&buf) = privp->val[i].v4; 409 break; 410 case NG_PATCH_MODE_ADD: 411 *((uint32_t *)&buf) += privp->val[i].v4; 412 break; 413 case NG_PATCH_MODE_SUB: 414 *((uint32_t *)&buf) -= privp->val[i].v4; 415 break; 416 case NG_PATCH_MODE_MUL: 417 *((uint32_t *)&buf) *= privp->val[i].v4; 418 break; 419 case NG_PATCH_MODE_DIV: 420 *((uint32_t *)&buf) /= privp->val[i].v4; 421 break; 422 case NG_PATCH_MODE_NEG: 423 *((int32_t *)&buf) = - *((int32_t *)&buf); 424 break; 425 case NG_PATCH_MODE_AND: 426 *((uint32_t *)&buf) &= privp->val[i].v4; 427 break; 428 case NG_PATCH_MODE_OR: 429 *((uint32_t *)&buf) |= privp->val[i].v4; 430 break; 431 case NG_PATCH_MODE_XOR: 432 *((uint32_t *)&buf) ^= privp->val[i].v4; 433 break; 434 case NG_PATCH_MODE_SHL: 435 *((uint32_t *)&buf) <<= privp->val[i].v4; 436 break; 437 case NG_PATCH_MODE_SHR: 438 *((uint32_t *)&buf) >>= privp->val[i].v4; 439 break; 440 } 441 *((int32_t *)&buf) = htonl(*((int32_t *)&buf)); 442 break; 443 case 8: 444 *((int64_t *)&buf) = be64toh(*((int64_t *)&buf)); 445 switch (conf->ops[i].mode) { 446 case NG_PATCH_MODE_SET: 447 *((uint64_t *)&buf) = privp->val[i].v8; 448 break; 449 case NG_PATCH_MODE_ADD: 450 *((uint64_t *)&buf) += privp->val[i].v8; 451 break; 452 case NG_PATCH_MODE_SUB: 453 *((uint64_t *)&buf) -= privp->val[i].v8; 454 break; 455 case NG_PATCH_MODE_MUL: 456 *((uint64_t *)&buf) *= privp->val[i].v8; 457 break; 458 case NG_PATCH_MODE_DIV: 459 *((uint64_t *)&buf) /= privp->val[i].v8; 460 break; 461 case NG_PATCH_MODE_NEG: 462 *((int64_t *)&buf) = - *((int64_t *)&buf); 463 break; 464 case NG_PATCH_MODE_AND: 465 *((uint64_t *)&buf) &= privp->val[i].v8; 466 break; 467 case NG_PATCH_MODE_OR: 468 *((uint64_t *)&buf) |= privp->val[i].v8; 469 break; 470 case NG_PATCH_MODE_XOR: 471 *((uint64_t *)&buf) ^= privp->val[i].v8; 472 break; 473 case NG_PATCH_MODE_SHL: 474 *((uint64_t *)&buf) <<= privp->val[i].v8; 475 break; 476 case NG_PATCH_MODE_SHR: 477 *((uint64_t *)&buf) >>= privp->val[i].v8; 478 break; 479 } 480 *((int64_t *)&buf) = htobe64(*((int64_t *)&buf)); 481 break; 482 } 483 484 m_copyback(m, conf->ops[i].offset, conf->ops[i].length, 485 (caddr_t)&buf); 486 patched = 1; 487 } 488 if (patched > 0) 489 privp->stats.patched++; 490} 491 492static int 493ng_patch_rcvdata(hook_p hook, item_p item) 494{ 495 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 496 struct mbuf *m; 497 hook_p target; 498 int error; 499 500 priv->stats.received++; 501 NGI_GET_M(item, m); 502 if (priv->config != NULL && hook == priv->in && 503 (m->m_flags & M_PKTHDR) != 0) { 504 m = m_unshare(m,M_NOWAIT); 505 if (m == NULL) { 506 priv->stats.dropped++; 507 NG_FREE_ITEM(item); 508 return (ENOMEM); 509 } 510 do_patch(priv, m); 511 m->m_flags |= priv->config->csum_flags; 512 } 513 514 target = NULL; 515 if (hook == priv->in) { 516 /* return frames on 'in' hook if 'out' not connected */ 517 if (priv->out != NULL) 518 target = priv->out; 519 else 520 target = priv->in; 521 } 522 if (hook == priv->out && priv->in != NULL) 523 target = priv->in; 524 525 if (target == NULL) { 526 priv->stats.dropped++; 527 NG_FREE_ITEM(item); 528 NG_FREE_M(m); 529 return (0); 530 } 531 NG_FWD_NEW_DATA(error, item, target, m); 532 return (error); 533} 534 535static int 536ng_patch_shutdown(node_p node) 537{ 538 const priv_p privdata = NG_NODE_PRIVATE(node); 539 540 if (privdata->val != NULL) 541 free(privdata->val, M_NETGRAPH); 542 if (privdata->config != NULL) 543 free(privdata->config, M_NETGRAPH); 544 NG_NODE_SET_PRIVATE(node, NULL); 545 NG_NODE_UNREF(node); 546 free(privdata, M_NETGRAPH); 547 return (0); 548} 549 550static int 551ng_patch_disconnect(hook_p hook) 552{
| 338 switch (conf->ops[i].length) { 339 case 1: 340 switch (conf->ops[i].mode) { 341 case NG_PATCH_MODE_SET: 342 *((uint8_t *)&buf) = privp->val[i].v1; 343 break; 344 case NG_PATCH_MODE_ADD: 345 *((uint8_t *)&buf) += privp->val[i].v1; 346 break; 347 case NG_PATCH_MODE_SUB: 348 *((uint8_t *)&buf) -= privp->val[i].v1; 349 break; 350 case NG_PATCH_MODE_MUL: 351 *((uint8_t *)&buf) *= privp->val[i].v1; 352 break; 353 case NG_PATCH_MODE_DIV: 354 *((uint8_t *)&buf) /= privp->val[i].v1; 355 break; 356 case NG_PATCH_MODE_NEG: 357 *((int8_t *)&buf) = - *((int8_t *)&buf); 358 break; 359 case NG_PATCH_MODE_AND: 360 *((uint8_t *)&buf) &= privp->val[i].v1; 361 break; 362 case NG_PATCH_MODE_OR: 363 *((uint8_t *)&buf) |= privp->val[i].v1; 364 break; 365 case NG_PATCH_MODE_XOR: 366 *((uint8_t *)&buf) ^= privp->val[i].v1; 367 break; 368 case NG_PATCH_MODE_SHL: 369 *((uint8_t *)&buf) <<= privp->val[i].v1; 370 break; 371 case NG_PATCH_MODE_SHR: 372 *((uint8_t *)&buf) >>= privp->val[i].v1; 373 break; 374 } 375 break; 376 case 2: 377 *((int16_t *)&buf) = ntohs(*((int16_t *)&buf)); 378 switch (conf->ops[i].mode) { 379 case NG_PATCH_MODE_SET: 380 *((uint16_t *)&buf) = privp->val[i].v2; 381 break; 382 case NG_PATCH_MODE_ADD: 383 *((uint16_t *)&buf) += privp->val[i].v2; 384 break; 385 case NG_PATCH_MODE_SUB: 386 *((uint16_t *)&buf) -= privp->val[i].v2; 387 break; 388 case NG_PATCH_MODE_MUL: 389 *((uint16_t *)&buf) *= privp->val[i].v2; 390 break; 391 case NG_PATCH_MODE_DIV: 392 *((uint16_t *)&buf) /= privp->val[i].v2; 393 break; 394 case NG_PATCH_MODE_NEG: 395 *((int16_t *)&buf) = - *((int16_t *)&buf); 396 break; 397 case NG_PATCH_MODE_AND: 398 *((uint16_t *)&buf) &= privp->val[i].v2; 399 break; 400 case NG_PATCH_MODE_OR: 401 *((uint16_t *)&buf) |= privp->val[i].v2; 402 break; 403 case NG_PATCH_MODE_XOR: 404 *((uint16_t *)&buf) ^= privp->val[i].v2; 405 break; 406 case NG_PATCH_MODE_SHL: 407 *((uint16_t *)&buf) <<= privp->val[i].v2; 408 break; 409 case NG_PATCH_MODE_SHR: 410 *((uint16_t *)&buf) >>= privp->val[i].v2; 411 break; 412 } 413 *((int16_t *)&buf) = htons(*((int16_t *)&buf)); 414 break; 415 case 4: 416 *((int32_t *)&buf) = ntohl(*((int32_t *)&buf)); 417 switch (conf->ops[i].mode) { 418 case NG_PATCH_MODE_SET: 419 *((uint32_t *)&buf) = privp->val[i].v4; 420 break; 421 case NG_PATCH_MODE_ADD: 422 *((uint32_t *)&buf) += privp->val[i].v4; 423 break; 424 case NG_PATCH_MODE_SUB: 425 *((uint32_t *)&buf) -= privp->val[i].v4; 426 break; 427 case NG_PATCH_MODE_MUL: 428 *((uint32_t *)&buf) *= privp->val[i].v4; 429 break; 430 case NG_PATCH_MODE_DIV: 431 *((uint32_t *)&buf) /= privp->val[i].v4; 432 break; 433 case NG_PATCH_MODE_NEG: 434 *((int32_t *)&buf) = - *((int32_t *)&buf); 435 break; 436 case NG_PATCH_MODE_AND: 437 *((uint32_t *)&buf) &= privp->val[i].v4; 438 break; 439 case NG_PATCH_MODE_OR: 440 *((uint32_t *)&buf) |= privp->val[i].v4; 441 break; 442 case NG_PATCH_MODE_XOR: 443 *((uint32_t *)&buf) ^= privp->val[i].v4; 444 break; 445 case NG_PATCH_MODE_SHL: 446 *((uint32_t *)&buf) <<= privp->val[i].v4; 447 break; 448 case NG_PATCH_MODE_SHR: 449 *((uint32_t *)&buf) >>= privp->val[i].v4; 450 break; 451 } 452 *((int32_t *)&buf) = htonl(*((int32_t *)&buf)); 453 break; 454 case 8: 455 *((int64_t *)&buf) = be64toh(*((int64_t *)&buf)); 456 switch (conf->ops[i].mode) { 457 case NG_PATCH_MODE_SET: 458 *((uint64_t *)&buf) = privp->val[i].v8; 459 break; 460 case NG_PATCH_MODE_ADD: 461 *((uint64_t *)&buf) += privp->val[i].v8; 462 break; 463 case NG_PATCH_MODE_SUB: 464 *((uint64_t *)&buf) -= privp->val[i].v8; 465 break; 466 case NG_PATCH_MODE_MUL: 467 *((uint64_t *)&buf) *= privp->val[i].v8; 468 break; 469 case NG_PATCH_MODE_DIV: 470 *((uint64_t *)&buf) /= privp->val[i].v8; 471 break; 472 case NG_PATCH_MODE_NEG: 473 *((int64_t *)&buf) = - *((int64_t *)&buf); 474 break; 475 case NG_PATCH_MODE_AND: 476 *((uint64_t *)&buf) &= privp->val[i].v8; 477 break; 478 case NG_PATCH_MODE_OR: 479 *((uint64_t *)&buf) |= privp->val[i].v8; 480 break; 481 case NG_PATCH_MODE_XOR: 482 *((uint64_t *)&buf) ^= privp->val[i].v8; 483 break; 484 case NG_PATCH_MODE_SHL: 485 *((uint64_t *)&buf) <<= privp->val[i].v8; 486 break; 487 case NG_PATCH_MODE_SHR: 488 *((uint64_t *)&buf) >>= privp->val[i].v8; 489 break; 490 } 491 *((int64_t *)&buf) = htobe64(*((int64_t *)&buf)); 492 break; 493 } 494 495 m_copyback(m, conf->ops[i].offset, conf->ops[i].length, 496 (caddr_t)&buf); 497 patched = 1; 498 } 499 if (patched > 0) 500 privp->stats.patched++; 501} 502 503static int 504ng_patch_rcvdata(hook_p hook, item_p item) 505{ 506 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 507 struct mbuf *m; 508 hook_p target; 509 int error; 510 511 priv->stats.received++; 512 NGI_GET_M(item, m); 513 if (priv->config != NULL && hook == priv->in && 514 (m->m_flags & M_PKTHDR) != 0) { 515 m = m_unshare(m,M_NOWAIT); 516 if (m == NULL) { 517 priv->stats.dropped++; 518 NG_FREE_ITEM(item); 519 return (ENOMEM); 520 } 521 do_patch(priv, m); 522 m->m_flags |= priv->config->csum_flags; 523 } 524 525 target = NULL; 526 if (hook == priv->in) { 527 /* return frames on 'in' hook if 'out' not connected */ 528 if (priv->out != NULL) 529 target = priv->out; 530 else 531 target = priv->in; 532 } 533 if (hook == priv->out && priv->in != NULL) 534 target = priv->in; 535 536 if (target == NULL) { 537 priv->stats.dropped++; 538 NG_FREE_ITEM(item); 539 NG_FREE_M(m); 540 return (0); 541 } 542 NG_FWD_NEW_DATA(error, item, target, m); 543 return (error); 544} 545 546static int 547ng_patch_shutdown(node_p node) 548{ 549 const priv_p privdata = NG_NODE_PRIVATE(node); 550 551 if (privdata->val != NULL) 552 free(privdata->val, M_NETGRAPH); 553 if (privdata->config != NULL) 554 free(privdata->config, M_NETGRAPH); 555 NG_NODE_SET_PRIVATE(node, NULL); 556 NG_NODE_UNREF(node); 557 free(privdata, M_NETGRAPH); 558 return (0); 559} 560 561static int 562ng_patch_disconnect(hook_p hook) 563{
|
553 priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
| 564 priv_p priv;
|
554
| 565
|
| 566 priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
|
555 if (hook == priv->in) { 556 priv->in = NULL; 557 } 558 if (hook == priv->out) { 559 priv->out = NULL; 560 }
| 567 if (hook == priv->in) { 568 priv->in = NULL; 569 } 570 if (hook == priv->out) { 571 priv->out = NULL; 572 }
|
561 if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 562 && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) /* already shutting down? */
| 573 if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 && 574 NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) /* already shutting down? */
|
563 ng_rmnode_self(NG_HOOK_NODE(hook)); 564 return (0); 565} 566
| 575 ng_rmnode_self(NG_HOOK_NODE(hook)); 576 return (0); 577} 578
|