Deleted Added
full compact
ng_patch.c (208946) ng_patch.c (208989)
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