blob: 891c2ec7b788eb6d25ce9070fed7c3d3ea47d5ea [file] [log] [blame]
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +00001/*
Stephen Hemmingerae665a52006-12-05 10:10:22 -08002 * m_pedit.c generic packet editor actions module
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +00003 *
4 * This program is free software; you can distribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
Stephen Hemmingerae665a52006-12-05 10:10:22 -08009 * Authors: J Hadi Salim (hadi@cyberus.ca)
10 *
11 * TODO:
Stephen Hemminger3d0b7432014-12-20 15:47:17 -080012 * 1) Big endian broken in some spots
13 * 2) A lot of this stuff was added on the fly; get a big double-double
14 * and clean it up at some point.
Stephen Hemmingerae665a52006-12-05 10:10:22 -080015 *
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000016 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#include <syslog.h>
22#include <fcntl.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26#include <string.h>
27#include <dlfcn.h>
28#include "utils.h"
29#include "tc_util.h"
30#include "m_pedit.h"
31
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000032static struct m_pedit_util *pedit_list;
WANG Cong1c9af052014-01-29 15:12:59 -080033static int pedit_debug;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000034
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -040035static void explain(void)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000036{
Phil Sutter1672f422016-03-22 15:48:33 +010037 fprintf(stderr, "Usage: ... pedit munge <MUNGE> [CONTROL]\n");
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000038 fprintf(stderr,
Stephen Hemmingerae665a52006-12-05 10:10:22 -080039 "Where: MUNGE := <RAW>|<LAYERED>\n"
Stephen Hemminger8b625172016-06-14 14:31:37 -070040 "\t<RAW>:= <OFFSETC>[ATC]<CMD>\n \t\tOFFSETC:= offset <offval> <u8|u16|u32>\n"
41 "\t\tATC:= at <atval> offmask <maskval> shift <shiftval>\n"
42 "\t\tNOTE: offval is byte offset, must be multiple of 4\n"
43 "\t\tNOTE: maskval is a 32 bit hex number\n \t\tNOTE: shiftval is a is a shift value\n"
44 "\t\tCMD:= clear | invert | set <setval>| retain\n"
45 "\t<LAYERED>:= ip <ipdata> | ip6 <ip6data>\n"
Stephen Hemminger32a121c2016-03-21 11:48:36 -070046 " \t\t| udp <udpdata> | tcp <tcpdata> | icmp <icmpdata>\n"
Phil Sutter1672f422016-03-22 15:48:33 +010047 "\tCONTROL:= reclassify | pipe | drop | continue | pass\n"
Jamal Hadi Salimebf32082006-08-08 12:10:08 -070048 "For Example usage look at the examples directory\n");
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000049
50}
51
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -040052static void usage(void)
Jamal Hadi Salimebf32082006-08-08 12:10:08 -070053{
54 explain();
55 exit(-1);
56}
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000057
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -040058static int pedit_parse_nopopt(int *argc_p, char ***argv_p,
59 struct tc_pedit_sel *sel,
60 struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000061{
62 int argc = *argc_p;
63 char **argv = *argv_p;
64
65 if (argc) {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -040066 fprintf(stderr,
67 "Unknown action hence option \"%s\" is unparsable\n",
68 *argv);
69 return -1;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000070 }
71
72 return 0;
73
74}
75
Stephen Hemmingerd1f28cf2013-02-12 11:09:03 -080076static struct m_pedit_util *get_pedit_kind(const char *str)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000077{
2!tgraffe102f62005-01-18 00:09:02 +000078 static void *pBODY;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000079 void *dlh;
80 char buf[256];
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -040081 struct m_pedit_util *p;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +000082
83 for (p = pedit_list; p; p = p->next) {
84 if (strcmp(p->id, str) == 0)
85 return p;
86 }
87
88 snprintf(buf, sizeof(buf), "p_%s.so", str);
89 dlh = dlopen(buf, RTLD_LAZY);
90 if (dlh == NULL) {
91 dlh = pBODY;
92 if (dlh == NULL) {
93 dlh = pBODY = dlopen(NULL, RTLD_LAZY);
94 if (dlh == NULL)
95 goto noexist;
96 }
97 }
98
99 snprintf(buf, sizeof(buf), "p_pedit_%s", str);
100 p = dlsym(dlh, buf);
101 if (p == NULL)
102 goto noexist;
103
104reg:
105 p->next = pedit_list;
106 pedit_list = p;
107 return p;
108
109noexist:
Phil Sutterf89bb022016-07-18 16:48:43 +0200110 p = calloc(1, sizeof(*p));
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000111 if (p) {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400112 strncpy(p->id, str, sizeof(p->id) - 1);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000113 p->parse_peopt = pedit_parse_nopopt;
114 goto reg;
115 }
116 return p;
117}
118
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400119int pack_key(struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000120{
121 int hwm = sel->nkeys;
122
123 if (hwm >= MAX_OFFS)
124 return -1;
125
126 if (tkey->off % 4) {
127 fprintf(stderr, "offsets MUST be in 32 bit boundaries\n");
128 return -1;
129 }
130
131 sel->keys[hwm].val = tkey->val;
132 sel->keys[hwm].mask = tkey->mask;
133 sel->keys[hwm].off = tkey->off;
134 sel->keys[hwm].at = tkey->at;
135 sel->keys[hwm].offmask = tkey->offmask;
136 sel->keys[hwm].shift = tkey->shift;
137 sel->nkeys++;
138 return 0;
139}
140
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400141int pack_key32(__u32 retain, struct tc_pedit_sel *sel,
142 struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000143{
144 if (tkey->off > (tkey->off & ~3)) {
145 fprintf(stderr,
146 "pack_key32: 32 bit offsets must begin in 32bit boundaries\n");
147 return -1;
148 }
149
150 tkey->val = htonl(tkey->val & retain);
151 tkey->mask = htonl(tkey->mask | ~retain);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700152 return pack_key(sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000153}
154
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400155int pack_key16(__u32 retain, struct tc_pedit_sel *sel,
156 struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000157{
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700158 int ind, stride;
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400159 __u32 m[4] = { 0x0000FFFF, 0xFF0000FF, 0xFFFF0000 };
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000160
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000161 if (tkey->val > 0xFFFF || tkey->mask > 0xFFFF) {
162 fprintf(stderr, "pack_key16 bad value\n");
163 return -1;
164 }
165
166 ind = tkey->off & 3;
167
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700168 if (ind == 3) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700169 fprintf(stderr, "pack_key16 bad index value %d\n", ind);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000170 return -1;
171 }
172
Phil Sutter77bed402016-03-22 15:16:22 +0100173 stride = 8 * (2 - ind);
174 tkey->val = htonl((tkey->val & retain) << stride);
175 tkey->mask = htonl(((tkey->mask | ~retain) << stride) | m[ind]);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000176
177 tkey->off &= ~3;
178
179 if (pedit_debug)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400180 printf("pack_key16: Final val %08x mask %08x\n",
181 tkey->val, tkey->mask);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700182 return pack_key(sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000183
184}
185
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400186int pack_key8(__u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000187{
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700188 int ind, stride;
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400189 __u32 m[4] = { 0x00FFFFFF, 0xFF00FFFF, 0xFFFF00FF, 0xFFFFFF00 };
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000190
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000191 if (tkey->val > 0xFF || tkey->mask > 0xFF) {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400192 fprintf(stderr, "pack_key8 bad value (val %x mask %x\n",
193 tkey->val, tkey->mask);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000194 return -1;
195 }
196
197 ind = tkey->off & 3;
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700198
Phil Sutter77bed402016-03-22 15:16:22 +0100199 stride = 8 * (3 - ind);
200 tkey->val = htonl((tkey->val & retain) << stride);
201 tkey->mask = htonl(((tkey->mask | ~retain) << stride) | m[ind]);
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700202
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000203 tkey->off &= ~3;
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800204
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000205 if (pedit_debug)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400206 printf("pack_key8: Final word off %d val %08x mask %08x\n",
207 tkey->off, tkey->val, tkey->mask);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700208 return pack_key(sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000209}
210
Stephen Hemminger8b625172016-06-14 14:31:37 -0700211int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000212{
213 int argc = *argc_p;
214 char **argv = *argv_p;
215
216 if (argc <= 0)
217 return -1;
218
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700219 if (type == TINT)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400220 return get_integer((int *)val, *argv, 0);
shemmingerf332d162005-07-05 22:37:15 +0000221
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700222 if (type == TU32)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000223 return get_u32(val, *argv, 0);
shemmingerf332d162005-07-05 22:37:15 +0000224
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700225 if (type == TIPV4) {
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000226 inet_prefix addr;
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700227
Stephen Hemminger8b625172016-06-14 14:31:37 -0700228 if (get_prefix_1(&addr, *argv, AF_INET))
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000229 return -1;
Stephen Hemminger8b625172016-06-14 14:31:37 -0700230
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700231 *val = addr.data[0];
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000232 return 0;
233 }
Stephen Hemminger8b625172016-06-14 14:31:37 -0700234
235 if (type == TIPV6)
236 return -1; /* not implemented yet */
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000237
238 return -1;
239}
240
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400241int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain,
242 struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000243{
244 __u32 mask = 0, val = 0;
245 __u32 o = 0xFF;
246 int res = -1;
247 int argc = *argc_p;
248 char **argv = *argv_p;
249
250 if (argc <= 0)
251 return -1;
252
253 if (pedit_debug)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400254 printf("parse_cmd argc %d %s offset %d length %d\n",
255 argc, *argv, tkey->off, len);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000256
257 if (len == 2)
258 o = 0xFFFF;
259 if (len == 4)
260 o = 0xFFFFFFFF;
261
262 if (matches(*argv, "invert") == 0) {
Phil Sutterf440e9d2016-03-02 12:20:30 +0100263 val = mask = o;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000264 } else if (matches(*argv, "set") == 0) {
265 NEXT_ARG();
266 if (parse_val(&argc, &argv, &val, type))
267 return -1;
268 } else if (matches(*argv, "preserve") == 0) {
Phil Sutterf440e9d2016-03-02 12:20:30 +0100269 retain = 0;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000270 } else {
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800271 if (matches(*argv, "clear") != 0)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000272 return -1;
273 }
274
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400275 argc--;
276 argv++;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000277
278 if (argc && matches(*argv, "retain") == 0) {
279 NEXT_ARG();
280 if (parse_val(&argc, &argv, &retain, TU32))
281 return -1;
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400282 argc--;
283 argv++;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000284 }
285
286 tkey->val = val;
Phil Sutterf440e9d2016-03-02 12:20:30 +0100287 tkey->mask = mask;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000288
Phil Sutter77bed402016-03-22 15:16:22 +0100289 if (type == TIPV4)
290 tkey->val = ntohl(tkey->val);
291
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000292 if (len == 1) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700293 res = pack_key8(retain, sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000294 goto done;
295 }
296 if (len == 2) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700297 res = pack_key16(retain, sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000298 goto done;
299 }
300 if (len == 4) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700301 res = pack_key32(retain, sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000302 goto done;
303 }
304
305 return -1;
306done:
307 if (pedit_debug)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400308 printf("parse_cmd done argc %d %s offset %d length %d\n",
309 argc, *argv, tkey->off, len);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000310 *argc_p = argc;
311 *argv_p = argv;
312 return res;
313
314}
315
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400316int parse_offset(int *argc_p, char ***argv_p, struct tc_pedit_sel *sel,
317 struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000318{
319 int off;
320 __u32 len, retain;
321 int argc = *argc_p;
322 char **argv = *argv_p;
323 int res = -1;
324
325 if (argc <= 0)
326 return -1;
327
328 if (get_integer(&off, *argv, 0))
329 return -1;
330 tkey->off = off;
331
332 argc--;
333 argv++;
334
335 if (argc <= 0)
336 return -1;
337
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000338 if (matches(*argv, "u32") == 0) {
339 len = 4;
340 retain = 0xFFFFFFFF;
341 goto done;
342 }
343 if (matches(*argv, "u16") == 0) {
344 len = 2;
Phil Suttera33786b2016-03-22 15:16:23 +0100345 retain = 0xffff;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000346 goto done;
347 }
348 if (matches(*argv, "u8") == 0) {
349 len = 1;
Phil Suttera33786b2016-03-22 15:16:23 +0100350 retain = 0xff;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000351 goto done;
352 }
353
354 return -1;
355
356done:
357
358 NEXT_ARG();
359
360 /* [at <someval> offmask <maskval> shift <shiftval>] */
361 if (matches(*argv, "at") == 0) {
362
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700363 __u32 atv = 0, offmask = 0x0, shift = 0;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000364
365 NEXT_ARG();
366 if (get_u32(&atv, *argv, 0))
367 return -1;
368 tkey->at = atv;
369
370 NEXT_ARG();
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800371
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000372 if (get_u32(&offmask, *argv, 16))
373 return -1;
374 tkey->offmask = offmask;
375
376 NEXT_ARG();
377
378 if (get_u32(&shift, *argv, 0))
379 return -1;
380 tkey->shift = shift;
381
382 NEXT_ARG();
383 }
384
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700385 res = parse_cmd(&argc, &argv, len, TU32, retain, sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000386
387 *argc_p = argc;
388 *argv_p = argv;
389 return res;
390}
391
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400392static int parse_munge(int *argc_p, char ***argv_p, struct tc_pedit_sel *sel)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000393{
Phil Sutterd17b1362016-07-18 16:48:42 +0200394 struct tc_pedit_key tkey = {};
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000395 int argc = *argc_p;
396 char **argv = *argv_p;
397 int res = -1;
398
399 if (argc <= 0)
400 return -1;
401
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000402 if (matches(*argv, "offset") == 0) {
403 NEXT_ARG();
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700404 res = parse_offset(&argc, &argv, sel, &tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000405 goto done;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000406 } else {
407 char k[16];
408 struct m_pedit_util *p = NULL;
409
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700410 strncpy(k, *argv, sizeof(k) - 1);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000411
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700412 if (argc > 0) {
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000413 p = get_pedit_kind(k);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700414 if (p == NULL)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000415 goto bad_val;
Phil Sutterec0ceee2016-03-02 12:20:29 +0100416 NEXT_ARG();
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700417 res = p->parse_peopt(&argc, &argv, sel, &tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000418 if (res < 0) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700419 fprintf(stderr, "bad pedit parsing\n");
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000420 goto bad_val;
421 }
422 goto done;
423 }
424 }
425
426bad_val:
427 return -1;
428
429done:
430
431 *argc_p = argc;
432 *argv_p = argv;
433 return res;
434}
435
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400436int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
437 struct nlmsghdr *n)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000438{
439 struct {
440 struct tc_pedit_sel sel;
441 struct tc_pedit_key keys[MAX_OFFS];
Phil Sutterd17b1362016-07-18 16:48:42 +0200442 } sel = {};
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000443
444 int argc = *argc_p;
445 char **argv = *argv_p;
446 int ok = 0, iok = 0;
447 struct rtattr *tail;
448
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000449 while (argc > 0) {
450 if (pedit_debug > 1)
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700451 fprintf(stderr, "while pedit (%d:%s)\n", argc, *argv);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000452 if (matches(*argv, "pedit") == 0) {
453 NEXT_ARG();
454 ok++;
455 continue;
Jamal Hadi Salimebf32082006-08-08 12:10:08 -0700456 } else if (matches(*argv, "help") == 0) {
457 usage();
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000458 } else if (matches(*argv, "munge") == 0) {
459 if (!ok) {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400460 fprintf(stderr, "Bad pedit construct (%s)\n",
461 *argv);
Jamal Hadi Salimebf32082006-08-08 12:10:08 -0700462 explain();
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000463 return -1;
464 }
465 NEXT_ARG();
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700466 if (parse_munge(&argc, &argv, &sel.sel)) {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400467 fprintf(stderr, "Bad pedit construct (%s)\n",
468 *argv);
Jamal Hadi Salimebf32082006-08-08 12:10:08 -0700469 explain();
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000470 return -1;
471 }
472 ok++;
473 } else {
474 break;
475 }
476
477 }
478
479 if (!ok) {
Jamal Hadi Salimebf32082006-08-08 12:10:08 -0700480 explain();
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000481 return -1;
482 }
483
Phil Sutter69f5aff2016-07-23 13:28:09 +0200484 if (argc && !action_a2n(*argv, &sel.sel.action, false))
485 NEXT_ARG();
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000486
487 if (argc) {
488 if (matches(*argv, "index") == 0) {
489 NEXT_ARG();
490 if (get_u32(&sel.sel.index, *argv, 10)) {
491 fprintf(stderr, "Pedit: Illegal \"index\"\n");
492 return -1;
493 }
494 argc--;
495 argv++;
496 iok++;
497 }
498 }
499
2!tgraffc78a8e2005-01-18 01:24:18 +0000500 tail = NLMSG_TAIL(n);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000501 addattr_l(n, MAX_MSG, tca_id, NULL, 0);
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400502 addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS, &sel,
503 sizeof(sel.sel) +
504 sel.sel.nkeys * sizeof(struct tc_pedit_key));
505 tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000506
507 *argc_p = argc;
508 *argv_p = argv;
509 return 0;
510}
511
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400512int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000513{
514 struct tc_pedit_sel *sel;
515 struct rtattr *tb[TCA_PEDIT_MAX + 1];
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700516
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000517 if (arg == NULL)
518 return -1;
519
2!tgraf78934002005-01-18 22:11:58 +0000520 parse_rtattr_nested(tb, TCA_PEDIT_MAX, arg);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000521
522 if (tb[TCA_PEDIT_PARMS] == NULL) {
523 fprintf(f, "[NULL pedit parameters]");
524 return -1;
525 }
526 sel = RTA_DATA(tb[TCA_PEDIT_PARMS]);
527
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400528 fprintf(f, " pedit action %s keys %d\n ",
Phil Sutter70932002016-07-23 13:28:10 +0200529 action_n2a(sel->action), sel->nkeys);
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400530 fprintf(f, "\t index %d ref %d bind %d", sel->index, sel->refcnt,
531 sel->bindcnt);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000532
533 if (show_stats) {
534 if (tb[TCA_PEDIT_TM]) {
535 struct tcf_t *tm = RTA_DATA(tb[TCA_PEDIT_TM]);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700536
537 print_tm(f, tm);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000538 }
539 }
540 if (sel->nkeys) {
541 int i;
542 struct tc_pedit_key *key = sel->keys;
543
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700544 for (i = 0; i < sel->nkeys; i++, key++) {
545 fprintf(f, "\n\t key #%d", i);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000546 fprintf(f, " at %d: val %08x mask %08x",
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400547 (unsigned int)key->off,
548 (unsigned int)ntohl(key->val),
549 (unsigned int)ntohl(key->mask));
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000550 }
551 } else {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400552 fprintf(f, "\npedit %x keys %d is not LEGIT", sel->index,
553 sel->nkeys);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000554 }
555
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000556 fprintf(f, "\n ");
557 return 0;
558}
559
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400560int pedit_print_xstats(struct action_util *au, FILE *f, struct rtattr *xstats)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000561{
562 return 0;
563}
564
565struct action_util pedit_action_util = {
566 .id = "pedit",
567 .parse_aopt = parse_pedit,
568 .print_aopt = print_pedit,
569};