blob: 64533060cc47b7659bba326c915eb6c8a5ec11ab [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:
110 p = malloc(sizeof(*p));
111 if (p) {
112 memset(p, 0, sizeof(*p));
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400113 strncpy(p->id, str, sizeof(p->id) - 1);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000114 p->parse_peopt = pedit_parse_nopopt;
115 goto reg;
116 }
117 return p;
118}
119
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400120int pack_key(struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000121{
122 int hwm = sel->nkeys;
123
124 if (hwm >= MAX_OFFS)
125 return -1;
126
127 if (tkey->off % 4) {
128 fprintf(stderr, "offsets MUST be in 32 bit boundaries\n");
129 return -1;
130 }
131
132 sel->keys[hwm].val = tkey->val;
133 sel->keys[hwm].mask = tkey->mask;
134 sel->keys[hwm].off = tkey->off;
135 sel->keys[hwm].at = tkey->at;
136 sel->keys[hwm].offmask = tkey->offmask;
137 sel->keys[hwm].shift = tkey->shift;
138 sel->nkeys++;
139 return 0;
140}
141
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400142int pack_key32(__u32 retain, struct tc_pedit_sel *sel,
143 struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000144{
145 if (tkey->off > (tkey->off & ~3)) {
146 fprintf(stderr,
147 "pack_key32: 32 bit offsets must begin in 32bit boundaries\n");
148 return -1;
149 }
150
151 tkey->val = htonl(tkey->val & retain);
152 tkey->mask = htonl(tkey->mask | ~retain);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700153 return pack_key(sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000154}
155
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400156int pack_key16(__u32 retain, struct tc_pedit_sel *sel,
157 struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000158{
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700159 int ind, stride;
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400160 __u32 m[4] = { 0x0000FFFF, 0xFF0000FF, 0xFFFF0000 };
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000161
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000162 if (tkey->val > 0xFFFF || tkey->mask > 0xFFFF) {
163 fprintf(stderr, "pack_key16 bad value\n");
164 return -1;
165 }
166
167 ind = tkey->off & 3;
168
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700169 if (ind == 3) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700170 fprintf(stderr, "pack_key16 bad index value %d\n", ind);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000171 return -1;
172 }
173
Phil Sutter77bed402016-03-22 15:16:22 +0100174 stride = 8 * (2 - ind);
175 tkey->val = htonl((tkey->val & retain) << stride);
176 tkey->mask = htonl(((tkey->mask | ~retain) << stride) | m[ind]);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000177
178 tkey->off &= ~3;
179
180 if (pedit_debug)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400181 printf("pack_key16: Final val %08x mask %08x\n",
182 tkey->val, tkey->mask);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700183 return pack_key(sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000184
185}
186
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400187int pack_key8(__u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000188{
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700189 int ind, stride;
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400190 __u32 m[4] = { 0x00FFFFFF, 0xFF00FFFF, 0xFFFF00FF, 0xFFFFFF00 };
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000191
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000192 if (tkey->val > 0xFF || tkey->mask > 0xFF) {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400193 fprintf(stderr, "pack_key8 bad value (val %x mask %x\n",
194 tkey->val, tkey->mask);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000195 return -1;
196 }
197
198 ind = tkey->off & 3;
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700199
Phil Sutter77bed402016-03-22 15:16:22 +0100200 stride = 8 * (3 - ind);
201 tkey->val = htonl((tkey->val & retain) << stride);
202 tkey->mask = htonl(((tkey->mask | ~retain) << stride) | m[ind]);
Maciej Żenczykowski0bbca042015-06-25 02:03:02 -0700203
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000204 tkey->off &= ~3;
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800205
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000206 if (pedit_debug)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400207 printf("pack_key8: Final word off %d val %08x mask %08x\n",
208 tkey->off, tkey->val, tkey->mask);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700209 return pack_key(sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000210}
211
Stephen Hemminger8b625172016-06-14 14:31:37 -0700212int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000213{
214 int argc = *argc_p;
215 char **argv = *argv_p;
216
217 if (argc <= 0)
218 return -1;
219
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700220 if (type == TINT)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400221 return get_integer((int *)val, *argv, 0);
shemmingerf332d162005-07-05 22:37:15 +0000222
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700223 if (type == TU32)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000224 return get_u32(val, *argv, 0);
shemmingerf332d162005-07-05 22:37:15 +0000225
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700226 if (type == TIPV4) {
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000227 inet_prefix addr;
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700228
Stephen Hemminger8b625172016-06-14 14:31:37 -0700229 if (get_prefix_1(&addr, *argv, AF_INET))
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000230 return -1;
Stephen Hemminger8b625172016-06-14 14:31:37 -0700231
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700232 *val = addr.data[0];
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000233 return 0;
234 }
Stephen Hemminger8b625172016-06-14 14:31:37 -0700235
236 if (type == TIPV6)
237 return -1; /* not implemented yet */
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000238
239 return -1;
240}
241
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400242int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain,
243 struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000244{
245 __u32 mask = 0, val = 0;
246 __u32 o = 0xFF;
247 int res = -1;
248 int argc = *argc_p;
249 char **argv = *argv_p;
250
251 if (argc <= 0)
252 return -1;
253
254 if (pedit_debug)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400255 printf("parse_cmd argc %d %s offset %d length %d\n",
256 argc, *argv, tkey->off, len);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000257
258 if (len == 2)
259 o = 0xFFFF;
260 if (len == 4)
261 o = 0xFFFFFFFF;
262
263 if (matches(*argv, "invert") == 0) {
Phil Sutterf440e9d2016-03-02 12:20:30 +0100264 val = mask = o;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000265 } else if (matches(*argv, "set") == 0) {
266 NEXT_ARG();
267 if (parse_val(&argc, &argv, &val, type))
268 return -1;
269 } else if (matches(*argv, "preserve") == 0) {
Phil Sutterf440e9d2016-03-02 12:20:30 +0100270 retain = 0;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000271 } else {
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800272 if (matches(*argv, "clear") != 0)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000273 return -1;
274 }
275
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400276 argc--;
277 argv++;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000278
279 if (argc && matches(*argv, "retain") == 0) {
280 NEXT_ARG();
281 if (parse_val(&argc, &argv, &retain, TU32))
282 return -1;
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400283 argc--;
284 argv++;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000285 }
286
287 tkey->val = val;
Phil Sutterf440e9d2016-03-02 12:20:30 +0100288 tkey->mask = mask;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000289
Phil Sutter77bed402016-03-22 15:16:22 +0100290 if (type == TIPV4)
291 tkey->val = ntohl(tkey->val);
292
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000293 if (len == 1) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700294 res = pack_key8(retain, sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000295 goto done;
296 }
297 if (len == 2) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700298 res = pack_key16(retain, sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000299 goto done;
300 }
301 if (len == 4) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700302 res = pack_key32(retain, sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000303 goto done;
304 }
305
306 return -1;
307done:
308 if (pedit_debug)
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400309 printf("parse_cmd done argc %d %s offset %d length %d\n",
310 argc, *argv, tkey->off, len);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000311 *argc_p = argc;
312 *argv_p = argv;
313 return res;
314
315}
316
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400317int parse_offset(int *argc_p, char ***argv_p, struct tc_pedit_sel *sel,
318 struct tc_pedit_key *tkey)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000319{
320 int off;
321 __u32 len, retain;
322 int argc = *argc_p;
323 char **argv = *argv_p;
324 int res = -1;
325
326 if (argc <= 0)
327 return -1;
328
329 if (get_integer(&off, *argv, 0))
330 return -1;
331 tkey->off = off;
332
333 argc--;
334 argv++;
335
336 if (argc <= 0)
337 return -1;
338
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000339 if (matches(*argv, "u32") == 0) {
340 len = 4;
341 retain = 0xFFFFFFFF;
342 goto done;
343 }
344 if (matches(*argv, "u16") == 0) {
345 len = 2;
Phil Suttera33786b2016-03-22 15:16:23 +0100346 retain = 0xffff;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000347 goto done;
348 }
349 if (matches(*argv, "u8") == 0) {
350 len = 1;
Phil Suttera33786b2016-03-22 15:16:23 +0100351 retain = 0xff;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000352 goto done;
353 }
354
355 return -1;
356
357done:
358
359 NEXT_ARG();
360
361 /* [at <someval> offmask <maskval> shift <shiftval>] */
362 if (matches(*argv, "at") == 0) {
363
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700364 __u32 atv = 0, offmask = 0x0, shift = 0;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000365
366 NEXT_ARG();
367 if (get_u32(&atv, *argv, 0))
368 return -1;
369 tkey->at = atv;
370
371 NEXT_ARG();
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800372
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000373 if (get_u32(&offmask, *argv, 16))
374 return -1;
375 tkey->offmask = offmask;
376
377 NEXT_ARG();
378
379 if (get_u32(&shift, *argv, 0))
380 return -1;
381 tkey->shift = shift;
382
383 NEXT_ARG();
384 }
385
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700386 res = parse_cmd(&argc, &argv, len, TU32, retain, sel, tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000387
388 *argc_p = argc;
389 *argv_p = argv;
390 return res;
391}
392
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400393static int parse_munge(int *argc_p, char ***argv_p, struct tc_pedit_sel *sel)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000394{
395 struct tc_pedit_key tkey;
396 int argc = *argc_p;
397 char **argv = *argv_p;
398 int res = -1;
399
400 if (argc <= 0)
401 return -1;
402
403 memset(&tkey, 0, sizeof(tkey));
404
405 if (matches(*argv, "offset") == 0) {
406 NEXT_ARG();
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700407 res = parse_offset(&argc, &argv, sel, &tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000408 goto done;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000409 } else {
410 char k[16];
411 struct m_pedit_util *p = NULL;
412
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700413 strncpy(k, *argv, sizeof(k) - 1);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000414
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700415 if (argc > 0) {
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000416 p = get_pedit_kind(k);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700417 if (p == NULL)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000418 goto bad_val;
Phil Sutterec0ceee2016-03-02 12:20:29 +0100419 NEXT_ARG();
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700420 res = p->parse_peopt(&argc, &argv, sel, &tkey);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000421 if (res < 0) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700422 fprintf(stderr, "bad pedit parsing\n");
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000423 goto bad_val;
424 }
425 goto done;
426 }
427 }
428
429bad_val:
430 return -1;
431
432done:
433
434 *argc_p = argc;
435 *argv_p = argv;
436 return res;
437}
438
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400439int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
440 struct nlmsghdr *n)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000441{
442 struct {
443 struct tc_pedit_sel sel;
444 struct tc_pedit_key keys[MAX_OFFS];
445 } sel;
446
447 int argc = *argc_p;
448 char **argv = *argv_p;
449 int ok = 0, iok = 0;
450 struct rtattr *tail;
451
452 memset(&sel, 0, sizeof(sel));
453
454 while (argc > 0) {
455 if (pedit_debug > 1)
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700456 fprintf(stderr, "while pedit (%d:%s)\n", argc, *argv);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000457 if (matches(*argv, "pedit") == 0) {
458 NEXT_ARG();
459 ok++;
460 continue;
Jamal Hadi Salimebf32082006-08-08 12:10:08 -0700461 } else if (matches(*argv, "help") == 0) {
462 usage();
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000463 } else if (matches(*argv, "munge") == 0) {
464 if (!ok) {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400465 fprintf(stderr, "Bad pedit construct (%s)\n",
466 *argv);
Jamal Hadi Salimebf32082006-08-08 12:10:08 -0700467 explain();
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000468 return -1;
469 }
470 NEXT_ARG();
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700471 if (parse_munge(&argc, &argv, &sel.sel)) {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400472 fprintf(stderr, "Bad pedit construct (%s)\n",
473 *argv);
Jamal Hadi Salimebf32082006-08-08 12:10:08 -0700474 explain();
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000475 return -1;
476 }
477 ok++;
478 } else {
479 break;
480 }
481
482 }
483
484 if (!ok) {
Jamal Hadi Salimebf32082006-08-08 12:10:08 -0700485 explain();
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000486 return -1;
487 }
488
489 if (argc) {
490 if (matches(*argv, "reclassify") == 0) {
491 sel.sel.action = TC_ACT_RECLASSIFY;
492 NEXT_ARG();
493 } else if (matches(*argv, "pipe") == 0) {
494 sel.sel.action = TC_ACT_PIPE;
495 NEXT_ARG();
496 } else if (matches(*argv, "drop") == 0 ||
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400497 matches(*argv, "shot") == 0) {
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000498 sel.sel.action = TC_ACT_SHOT;
499 NEXT_ARG();
500 } else if (matches(*argv, "continue") == 0) {
501 sel.sel.action = TC_ACT_UNSPEC;
502 NEXT_ARG();
Jamal Hadi Salim43726b72016-05-07 09:39:36 -0400503 } else if (matches(*argv, "pass") == 0 ||
504 matches(*argv, "ok") == 0) {
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000505 sel.sel.action = TC_ACT_OK;
506 NEXT_ARG();
507 }
508 }
509
510 if (argc) {
511 if (matches(*argv, "index") == 0) {
512 NEXT_ARG();
513 if (get_u32(&sel.sel.index, *argv, 10)) {
514 fprintf(stderr, "Pedit: Illegal \"index\"\n");
515 return -1;
516 }
517 argc--;
518 argv++;
519 iok++;
520 }
521 }
522
2!tgraffc78a8e2005-01-18 01:24:18 +0000523 tail = NLMSG_TAIL(n);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000524 addattr_l(n, MAX_MSG, tca_id, NULL, 0);
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400525 addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS, &sel,
526 sizeof(sel.sel) +
527 sel.sel.nkeys * sizeof(struct tc_pedit_key));
528 tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000529
530 *argc_p = argc;
531 *argv_p = argv;
532 return 0;
533}
534
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400535int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000536{
537 struct tc_pedit_sel *sel;
538 struct rtattr *tb[TCA_PEDIT_MAX + 1];
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700539
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000540 SPRINT_BUF(b1);
541
542 if (arg == NULL)
543 return -1;
544
2!tgraf78934002005-01-18 22:11:58 +0000545 parse_rtattr_nested(tb, TCA_PEDIT_MAX, arg);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000546
547 if (tb[TCA_PEDIT_PARMS] == NULL) {
548 fprintf(f, "[NULL pedit parameters]");
549 return -1;
550 }
551 sel = RTA_DATA(tb[TCA_PEDIT_PARMS]);
552
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400553 fprintf(f, " pedit action %s keys %d\n ",
554 action_n2a(sel->action, b1, sizeof(b1)), sel->nkeys);
555 fprintf(f, "\t index %d ref %d bind %d", sel->index, sel->refcnt,
556 sel->bindcnt);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000557
558 if (show_stats) {
559 if (tb[TCA_PEDIT_TM]) {
560 struct tcf_t *tm = RTA_DATA(tb[TCA_PEDIT_TM]);
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700561
562 print_tm(f, tm);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000563 }
564 }
565 if (sel->nkeys) {
566 int i;
567 struct tc_pedit_key *key = sel->keys;
568
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700569 for (i = 0; i < sel->nkeys; i++, key++) {
570 fprintf(f, "\n\t key #%d", i);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000571 fprintf(f, " at %d: val %08x mask %08x",
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400572 (unsigned int)key->off,
573 (unsigned int)ntohl(key->val),
574 (unsigned int)ntohl(key->mask));
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000575 }
576 } else {
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400577 fprintf(f, "\npedit %x keys %d is not LEGIT", sel->index,
578 sel->nkeys);
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000579 }
580
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000581 fprintf(f, "\n ");
582 return 0;
583}
584
Jamal Hadi Salimd8694a32016-06-12 17:40:34 -0400585int pedit_print_xstats(struct action_util *au, FILE *f, struct rtattr *xstats)
net[shemminger]!shemminger7e7c7372005-01-17 23:32:51 +0000586{
587 return 0;
588}
589
590struct action_util pedit_action_util = {
591 .id = "pedit",
592 .parse_aopt = parse_pedit,
593 .print_aopt = print_pedit,
594};