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 --- 12 unchanged lines hidden (view full) --- 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 208989 2010-06-10 16:45:30Z ae $"); |
30 31#include <sys/param.h> 32#include <sys/kernel.h> |
33#include <sys/ctype.h> |
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 |
50#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0)) |
51 52static int |
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 --- 90 unchanged lines hidden (view full) --- 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) + \ |
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; --- 20 unchanged lines hidden (view full) --- 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, *newconf; 199 union patch_val *newval; |
200 struct ng_mesg *msg; |
201 struct ng_mesg *resp; 202 int i, clear, error; |
203 |
204 clear = error = 0; 205 resp = NULL; |
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 { |
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; |
227 if (msg->header.arglen < 228 NG_PATCH_CONF_SIZE(conf->count)) { |
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: --- 7 unchanged lines hidden (view full) --- 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) { |
252 newconf = malloc( 253 NG_PATCH_CONF_SIZE(conf->count), |
254 M_NETGRAPH, M_WAIT); |
255 newval = malloc(conf->count * 256 sizeof(union patch_val), M_NETGRAPH, 257 M_WAIT); |
258 for(i = 0; i < conf->count; i++) { 259 switch (conf->ops[i].length) { 260 case 1: |
261 newval[i].v1 = 262 conf->ops[i].value; |
263 break; 264 case 2: |
265 newval[i].v2 = 266 conf->ops[i].value; |
267 break; 268 case 4: |
269 newval[i].v4 = 270 conf->ops[i].value; |
271 break; 272 case 8: |
273 newval[i].v8 = 274 conf->ops[i].value; |
275 break; 276 } 277 } |
278 bcopy(conf, newconf, 279 NG_PATCH_CONF_SIZE(conf->count)); |
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; --- 25 unchanged lines hidden (view full) --- 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{ |
321 struct ng_patch_config *conf; |
322 uint64_t buf; |
323 int i, patched; |
324 |
325 conf = privp->config; 326 patched = 0; |
327 for(i = 0; i < conf->count; i++) { |
328 if (conf->ops[i].offset + conf->ops[i].length > 329 m->m_pkthdr.len) |
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 } |
337 |
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; --- 210 unchanged lines hidden (view full) --- 556 NG_NODE_UNREF(node); 557 free(privdata, M_NETGRAPH); 558 return (0); 559} 560 561static int 562ng_patch_disconnect(hook_p hook) 563{ |
564 priv_p priv; |
565 |
566 priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); |
567 if (hook == priv->in) { 568 priv->in = NULL; 569 } 570 if (hook == priv->out) { 571 priv->out = NULL; 572 } |
573 if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 && 574 NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) /* already shutting down? */ |
575 ng_rmnode_self(NG_HOOK_NODE(hook)); 576 return (0); 577} 578 |