1 /*
2 * q_u32.c U32 filter.
3 *
4 * This program is free software; you can u32istribute 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 *
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 * Match mark added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro> [5 nov 2004]
11 *
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <syslog.h>
18 #include <fcntl.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <string.h>
23 #include <linux/if.h>
24 #include <linux/if_ether.h>
25
26 #include "utils.h"
27 #include "tc_util.h"
28
29 extern int show_pretty;
30
explain(void)31 static void explain(void)
32 {
33 fprintf(stderr,
34 "Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]\n"
35 " [ action ACTION_SPEC ] [ offset OFFSET_SPEC ]\n"
36 " [ ht HTID ] [ hashkey HASHKEY_SPEC ]\n"
37 " [ sample SAMPLE ] [skip_hw | skip_sw]\n"
38 "or u32 divisor DIVISOR\n"
39 "\n"
40 "Where: SELECTOR := SAMPLE SAMPLE ...\n"
41 " SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark }\n"
42 " SAMPLE_ARGS [ divisor DIVISOR ]\n"
43 " FILTERID := X:Y:Z\n"
44 "\nNOTE: CLASSID is parsed at hexadecimal input.\n");
45 }
46
get_u32_handle(__u32 * handle,const char * str)47 static int get_u32_handle(__u32 *handle, const char *str)
48 {
49 __u32 htid = 0, hash = 0, nodeid = 0;
50 char *tmp = strchr(str, ':');
51
52 if (tmp == NULL) {
53 if (memcmp("0x", str, 2) == 0)
54 return get_u32(handle, str, 16);
55 return -1;
56 }
57 htid = strtoul(str, &tmp, 16);
58 if (tmp == str && *str != ':' && *str != 0)
59 return -1;
60 if (htid >= 0x1000)
61 return -1;
62 if (*tmp) {
63 str = tmp + 1;
64 hash = strtoul(str, &tmp, 16);
65 if (tmp == str && *str != ':' && *str != 0)
66 return -1;
67 if (hash >= 0x100)
68 return -1;
69 if (*tmp) {
70 str = tmp + 1;
71 nodeid = strtoul(str, &tmp, 16);
72 if (tmp == str && *str != 0)
73 return -1;
74 if (nodeid >= 0x1000)
75 return -1;
76 }
77 }
78 *handle = (htid<<20)|(hash<<12)|nodeid;
79 return 0;
80 }
81
sprint_u32_handle(__u32 handle,char * buf)82 static char *sprint_u32_handle(__u32 handle, char *buf)
83 {
84 int bsize = SPRINT_BSIZE-1;
85 __u32 htid = TC_U32_HTID(handle);
86 __u32 hash = TC_U32_HASH(handle);
87 __u32 nodeid = TC_U32_NODE(handle);
88 char *b = buf;
89
90 if (handle == 0) {
91 snprintf(b, bsize, "none");
92 return b;
93 }
94 if (htid) {
95 int l = snprintf(b, bsize, "%x:", htid>>20);
96
97 bsize -= l;
98 b += l;
99 }
100 if (nodeid|hash) {
101 if (hash) {
102 int l = snprintf(b, bsize, "%x", hash);
103
104 bsize -= l;
105 b += l;
106 }
107 if (nodeid) {
108 int l = snprintf(b, bsize, ":%x", nodeid);
109
110 bsize -= l;
111 b += l;
112 }
113 }
114 if (show_raw)
115 snprintf(b, bsize, "[%08x] ", handle);
116 return buf;
117 }
118
pack_key(struct tc_u32_sel * sel,__u32 key,__u32 mask,int off,int offmask)119 static int pack_key(struct tc_u32_sel *sel, __u32 key, __u32 mask,
120 int off, int offmask)
121 {
122 int i;
123 int hwm = sel->nkeys;
124
125 key &= mask;
126
127 for (i = 0; i < hwm; i++) {
128 if (sel->keys[i].off == off && sel->keys[i].offmask == offmask) {
129 __u32 intersect = mask & sel->keys[i].mask;
130
131 if ((key ^ sel->keys[i].val) & intersect)
132 return -1;
133 sel->keys[i].val |= key;
134 sel->keys[i].mask |= mask;
135 return 0;
136 }
137 }
138
139 if (hwm >= 128)
140 return -1;
141 if (off % 4)
142 return -1;
143 sel->keys[hwm].val = key;
144 sel->keys[hwm].mask = mask;
145 sel->keys[hwm].off = off;
146 sel->keys[hwm].offmask = offmask;
147 sel->nkeys++;
148 return 0;
149 }
150
pack_key32(struct tc_u32_sel * sel,__u32 key,__u32 mask,int off,int offmask)151 static int pack_key32(struct tc_u32_sel *sel, __u32 key, __u32 mask,
152 int off, int offmask)
153 {
154 key = htonl(key);
155 mask = htonl(mask);
156 return pack_key(sel, key, mask, off, offmask);
157 }
158
pack_key16(struct tc_u32_sel * sel,__u32 key,__u32 mask,int off,int offmask)159 static int pack_key16(struct tc_u32_sel *sel, __u32 key, __u32 mask,
160 int off, int offmask)
161 {
162 if (key > 0xFFFF || mask > 0xFFFF)
163 return -1;
164
165 if ((off & 3) == 0) {
166 key <<= 16;
167 mask <<= 16;
168 }
169 off &= ~3;
170 key = htonl(key);
171 mask = htonl(mask);
172
173 return pack_key(sel, key, mask, off, offmask);
174 }
175
pack_key8(struct tc_u32_sel * sel,__u32 key,__u32 mask,int off,int offmask)176 static int pack_key8(struct tc_u32_sel *sel, __u32 key, __u32 mask, int off,
177 int offmask)
178 {
179 if (key > 0xFF || mask > 0xFF)
180 return -1;
181
182 if ((off & 3) == 0) {
183 key <<= 24;
184 mask <<= 24;
185 } else if ((off & 3) == 1) {
186 key <<= 16;
187 mask <<= 16;
188 } else if ((off & 3) == 2) {
189 key <<= 8;
190 mask <<= 8;
191 }
192 off &= ~3;
193 key = htonl(key);
194 mask = htonl(mask);
195
196 return pack_key(sel, key, mask, off, offmask);
197 }
198
199
parse_at(int * argc_p,char *** argv_p,int * off,int * offmask)200 static int parse_at(int *argc_p, char ***argv_p, int *off, int *offmask)
201 {
202 int argc = *argc_p;
203 char **argv = *argv_p;
204 char *p = *argv;
205
206 if (argc <= 0)
207 return -1;
208
209 if (strlen(p) > strlen("nexthdr+") &&
210 memcmp(p, "nexthdr+", strlen("nexthdr+")) == 0) {
211 *offmask = -1;
212 p += strlen("nexthdr+");
213 } else if (matches(*argv, "nexthdr+") == 0) {
214 NEXT_ARG();
215 *offmask = -1;
216 p = *argv;
217 }
218
219 if (get_integer(off, p, 0))
220 return -1;
221 argc--; argv++;
222
223 *argc_p = argc;
224 *argv_p = argv;
225 return 0;
226 }
227
228
parse_u32(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off,int offmask)229 static int parse_u32(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
230 int off, int offmask)
231 {
232 int res = -1;
233 int argc = *argc_p;
234 char **argv = *argv_p;
235 __u32 key;
236 __u32 mask;
237
238 if (argc < 2)
239 return -1;
240
241 if (get_u32(&key, *argv, 0))
242 return -1;
243 argc--; argv++;
244
245 if (get_u32(&mask, *argv, 16))
246 return -1;
247 argc--; argv++;
248
249 if (argc > 0 && strcmp(argv[0], "at") == 0) {
250 NEXT_ARG();
251 if (parse_at(&argc, &argv, &off, &offmask))
252 return -1;
253 }
254
255 res = pack_key32(sel, key, mask, off, offmask);
256 *argc_p = argc;
257 *argv_p = argv;
258 return res;
259 }
260
parse_u16(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off,int offmask)261 static int parse_u16(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
262 int off, int offmask)
263 {
264 int res = -1;
265 int argc = *argc_p;
266 char **argv = *argv_p;
267 __u32 key;
268 __u32 mask;
269
270 if (argc < 2)
271 return -1;
272
273 if (get_u32(&key, *argv, 0))
274 return -1;
275 argc--; argv++;
276
277 if (get_u32(&mask, *argv, 16))
278 return -1;
279 argc--; argv++;
280
281 if (argc > 0 && strcmp(argv[0], "at") == 0) {
282 NEXT_ARG();
283 if (parse_at(&argc, &argv, &off, &offmask))
284 return -1;
285 }
286 res = pack_key16(sel, key, mask, off, offmask);
287 *argc_p = argc;
288 *argv_p = argv;
289 return res;
290 }
291
parse_u8(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off,int offmask)292 static int parse_u8(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
293 int off, int offmask)
294 {
295 int res = -1;
296 int argc = *argc_p;
297 char **argv = *argv_p;
298 __u32 key;
299 __u32 mask;
300
301 if (argc < 2)
302 return -1;
303
304 if (get_u32(&key, *argv, 0))
305 return -1;
306 argc--; argv++;
307
308 if (get_u32(&mask, *argv, 16))
309 return -1;
310 argc--; argv++;
311
312 if (key > 0xFF || mask > 0xFF)
313 return -1;
314
315 if (argc > 0 && strcmp(argv[0], "at") == 0) {
316 NEXT_ARG();
317 if (parse_at(&argc, &argv, &off, &offmask))
318 return -1;
319 }
320
321 res = pack_key8(sel, key, mask, off, offmask);
322 *argc_p = argc;
323 *argv_p = argv;
324 return res;
325 }
326
parse_ip_addr(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off)327 static int parse_ip_addr(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
328 int off)
329 {
330 int res = -1;
331 int argc = *argc_p;
332 char **argv = *argv_p;
333 inet_prefix addr;
334 __u32 mask;
335 int offmask = 0;
336
337 if (argc < 1)
338 return -1;
339
340 if (get_prefix_1(&addr, *argv, AF_INET))
341 return -1;
342 argc--; argv++;
343
344 if (argc > 0 && strcmp(argv[0], "at") == 0) {
345 NEXT_ARG();
346 if (parse_at(&argc, &argv, &off, &offmask))
347 return -1;
348 }
349
350 mask = 0;
351 if (addr.bitlen)
352 mask = htonl(0xFFFFFFFF << (32 - addr.bitlen));
353 if (pack_key(sel, addr.data[0], mask, off, offmask) < 0)
354 return -1;
355 res = 0;
356
357 *argc_p = argc;
358 *argv_p = argv;
359 return res;
360 }
361
parse_ip6_addr(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off)362 static int parse_ip6_addr(int *argc_p, char ***argv_p,
363 struct tc_u32_sel *sel, int off)
364 {
365 int res = -1;
366 int argc = *argc_p;
367 char **argv = *argv_p;
368 int plen = 128;
369 int i;
370 inet_prefix addr;
371 int offmask = 0;
372
373 if (argc < 1)
374 return -1;
375
376 if (get_prefix_1(&addr, *argv, AF_INET6))
377 return -1;
378 argc--; argv++;
379
380 if (argc > 0 && strcmp(argv[0], "at") == 0) {
381 NEXT_ARG();
382 if (parse_at(&argc, &argv, &off, &offmask))
383 return -1;
384 }
385
386 plen = addr.bitlen;
387 for (i = 0; i < plen; i += 32) {
388 if (i + 31 < plen) {
389 res = pack_key(sel, addr.data[i / 32],
390 0xFFFFFFFF, off + 4 * (i / 32), offmask);
391 if (res < 0)
392 return -1;
393 } else if (i < plen) {
394 __u32 mask = htonl(0xFFFFFFFF << (32 - (plen - i)));
395
396 res = pack_key(sel, addr.data[i / 32],
397 mask, off + 4 * (i / 32), offmask);
398 if (res < 0)
399 return -1;
400 }
401 }
402 res = 0;
403
404 *argc_p = argc;
405 *argv_p = argv;
406 return res;
407 }
408
parse_ip6_class(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)409 static int parse_ip6_class(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
410 {
411 int res = -1;
412 int argc = *argc_p;
413 char **argv = *argv_p;
414 __u32 key;
415 __u32 mask;
416 int off = 0;
417 int offmask = 0;
418
419 if (argc < 2)
420 return -1;
421
422 if (get_u32(&key, *argv, 0))
423 return -1;
424 argc--; argv++;
425
426 if (get_u32(&mask, *argv, 16))
427 return -1;
428 argc--; argv++;
429
430 if (key > 0xFF || mask > 0xFF)
431 return -1;
432
433 key <<= 20;
434 mask <<= 20;
435 key = htonl(key);
436 mask = htonl(mask);
437
438 res = pack_key(sel, key, mask, off, offmask);
439 if (res < 0)
440 return -1;
441
442 *argc_p = argc;
443 *argv_p = argv;
444 return 0;
445 }
446
parse_ether_addr(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off)447 static int parse_ether_addr(int *argc_p, char ***argv_p,
448 struct tc_u32_sel *sel, int off)
449 {
450 int res = -1;
451 int argc = *argc_p;
452 char **argv = *argv_p;
453 __u8 addr[6];
454 int offmask = 0;
455 int i;
456
457 if (argc < 1)
458 return -1;
459
460 if (sscanf(*argv, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
461 addr + 0, addr + 1, addr + 2,
462 addr + 3, addr + 4, addr + 5) != 6) {
463 fprintf(stderr, "parse_ether_addr: improperly formed address '%s'\n",
464 *argv);
465 return -1;
466 }
467
468 argc--; argv++;
469 if (argc > 0 && strcmp(argv[0], "at") == 0) {
470 NEXT_ARG();
471 if (parse_at(&argc, &argv, &off, &offmask))
472 return -1;
473 }
474
475 for (i = 0; i < 6; i++) {
476 res = pack_key8(sel, addr[i], 0xFF, off + i, offmask);
477 if (res < 0)
478 return -1;
479 }
480
481 *argc_p = argc;
482 *argv_p = argv;
483 return res;
484 }
485
parse_ip(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)486 static int parse_ip(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
487 {
488 int res = -1;
489 int argc = *argc_p;
490 char **argv = *argv_p;
491
492 if (argc < 2)
493 return -1;
494
495 if (strcmp(*argv, "src") == 0) {
496 NEXT_ARG();
497 res = parse_ip_addr(&argc, &argv, sel, 12);
498 } else if (strcmp(*argv, "dst") == 0) {
499 NEXT_ARG();
500 res = parse_ip_addr(&argc, &argv, sel, 16);
501 } else if (strcmp(*argv, "tos") == 0 ||
502 matches(*argv, "dsfield") == 0 ||
503 matches(*argv, "precedence") == 0) {
504 NEXT_ARG();
505 res = parse_u8(&argc, &argv, sel, 1, 0);
506 } else if (strcmp(*argv, "ihl") == 0) {
507 NEXT_ARG();
508 res = parse_u8(&argc, &argv, sel, 0, 0);
509 } else if (strcmp(*argv, "protocol") == 0) {
510 NEXT_ARG();
511 res = parse_u8(&argc, &argv, sel, 9, 0);
512 } else if (strcmp(*argv, "nofrag") == 0) {
513 argc--; argv++;
514 res = pack_key16(sel, 0, 0x3FFF, 6, 0);
515 } else if (strcmp(*argv, "firstfrag") == 0) {
516 argc--; argv++;
517 res = pack_key16(sel, 0x2000, 0x3FFF, 6, 0);
518 } else if (strcmp(*argv, "df") == 0) {
519 argc--; argv++;
520 res = pack_key16(sel, 0x4000, 0x4000, 6, 0);
521 } else if (strcmp(*argv, "mf") == 0) {
522 argc--; argv++;
523 res = pack_key16(sel, 0x2000, 0x2000, 6, 0);
524 } else if (strcmp(*argv, "dport") == 0) {
525 NEXT_ARG();
526 res = parse_u16(&argc, &argv, sel, 22, 0);
527 } else if (strcmp(*argv, "sport") == 0) {
528 NEXT_ARG();
529 res = parse_u16(&argc, &argv, sel, 20, 0);
530 } else if (strcmp(*argv, "icmp_type") == 0) {
531 NEXT_ARG();
532 res = parse_u8(&argc, &argv, sel, 20, 0);
533 } else if (strcmp(*argv, "icmp_code") == 0) {
534 NEXT_ARG();
535 res = parse_u8(&argc, &argv, sel, 21, 0);
536 } else
537 return -1;
538
539 *argc_p = argc;
540 *argv_p = argv;
541 return res;
542 }
543
parse_ip6(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)544 static int parse_ip6(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
545 {
546 int res = -1;
547 int argc = *argc_p;
548 char **argv = *argv_p;
549
550 if (argc < 2)
551 return -1;
552
553 if (strcmp(*argv, "src") == 0) {
554 NEXT_ARG();
555 res = parse_ip6_addr(&argc, &argv, sel, 8);
556 } else if (strcmp(*argv, "dst") == 0) {
557 NEXT_ARG();
558 res = parse_ip6_addr(&argc, &argv, sel, 24);
559 } else if (strcmp(*argv, "priority") == 0) {
560 NEXT_ARG();
561 res = parse_ip6_class(&argc, &argv, sel);
562 } else if (strcmp(*argv, "protocol") == 0) {
563 NEXT_ARG();
564 res = parse_u8(&argc, &argv, sel, 6, 0);
565 } else if (strcmp(*argv, "flowlabel") == 0) {
566 NEXT_ARG();
567 res = parse_u32(&argc, &argv, sel, 0, 0);
568 } else if (strcmp(*argv, "dport") == 0) {
569 NEXT_ARG();
570 res = parse_u16(&argc, &argv, sel, 42, 0);
571 } else if (strcmp(*argv, "sport") == 0) {
572 NEXT_ARG();
573 res = parse_u16(&argc, &argv, sel, 40, 0);
574 } else if (strcmp(*argv, "icmp_type") == 0) {
575 NEXT_ARG();
576 res = parse_u8(&argc, &argv, sel, 40, 0);
577 } else if (strcmp(*argv, "icmp_code") == 0) {
578 NEXT_ARG();
579 res = parse_u8(&argc, &argv, sel, 41, 1);
580 } else
581 return -1;
582
583 *argc_p = argc;
584 *argv_p = argv;
585 return res;
586 }
587
parse_ether(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)588 static int parse_ether(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
589 {
590 int res = -1;
591 int argc = *argc_p;
592 char **argv = *argv_p;
593
594 if (argc < 2)
595 return -1;
596
597 if (strcmp(*argv, "src") == 0) {
598 NEXT_ARG();
599 res = parse_ether_addr(&argc, &argv, sel, -8);
600 } else if (strcmp(*argv, "dst") == 0) {
601 NEXT_ARG();
602 res = parse_ether_addr(&argc, &argv, sel, -14);
603 } else {
604 fprintf(stderr, "Unknown match: ether %s\n", *argv);
605 return -1;
606 }
607
608 *argc_p = argc;
609 *argv_p = argv;
610 return res;
611 }
612
613 #define parse_tcp parse_udp
parse_udp(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)614 static int parse_udp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
615 {
616 int res = -1;
617 int argc = *argc_p;
618 char **argv = *argv_p;
619
620 if (argc < 2)
621 return -1;
622
623 if (strcmp(*argv, "src") == 0) {
624 NEXT_ARG();
625 res = parse_u16(&argc, &argv, sel, 0, -1);
626 } else if (strcmp(*argv, "dst") == 0) {
627 NEXT_ARG();
628 res = parse_u16(&argc, &argv, sel, 2, -1);
629 } else
630 return -1;
631
632 *argc_p = argc;
633 *argv_p = argv;
634 return res;
635 }
636
637
parse_icmp(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)638 static int parse_icmp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
639 {
640 int res = -1;
641 int argc = *argc_p;
642 char **argv = *argv_p;
643
644 if (argc < 2)
645 return -1;
646
647 if (strcmp(*argv, "type") == 0) {
648 NEXT_ARG();
649 res = parse_u8(&argc, &argv, sel, 0, -1);
650 } else if (strcmp(*argv, "code") == 0) {
651 NEXT_ARG();
652 res = parse_u8(&argc, &argv, sel, 1, -1);
653 } else
654 return -1;
655
656 *argc_p = argc;
657 *argv_p = argv;
658 return res;
659 }
660
parse_mark(int * argc_p,char *** argv_p,struct nlmsghdr * n)661 static int parse_mark(int *argc_p, char ***argv_p, struct nlmsghdr *n)
662 {
663 int res = -1;
664 int argc = *argc_p;
665 char **argv = *argv_p;
666 struct tc_u32_mark mark;
667
668 if (argc <= 1)
669 return -1;
670
671 if (get_u32(&mark.val, *argv, 0)) {
672 fprintf(stderr, "Illegal \"mark\" value\n");
673 return -1;
674 }
675 NEXT_ARG();
676
677 if (get_u32(&mark.mask, *argv, 0)) {
678 fprintf(stderr, "Illegal \"mark\" mask\n");
679 return -1;
680 }
681 NEXT_ARG();
682
683 if ((mark.val & mark.mask) != mark.val) {
684 fprintf(stderr, "Illegal \"mark\" (impossible combination)\n");
685 return -1;
686 }
687
688 addattr_l(n, MAX_MSG, TCA_U32_MARK, &mark, sizeof(mark));
689 res = 0;
690
691 *argc_p = argc;
692 *argv_p = argv;
693 return res;
694 }
695
parse_selector(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,struct nlmsghdr * n)696 static int parse_selector(int *argc_p, char ***argv_p,
697 struct tc_u32_sel *sel, struct nlmsghdr *n)
698 {
699 int argc = *argc_p;
700 char **argv = *argv_p;
701 int res = -1;
702
703 if (argc <= 0)
704 return -1;
705
706 if (matches(*argv, "u32") == 0) {
707 NEXT_ARG();
708 res = parse_u32(&argc, &argv, sel, 0, 0);
709 } else if (matches(*argv, "u16") == 0) {
710 NEXT_ARG();
711 res = parse_u16(&argc, &argv, sel, 0, 0);
712 } else if (matches(*argv, "u8") == 0) {
713 NEXT_ARG();
714 res = parse_u8(&argc, &argv, sel, 0, 0);
715 } else if (matches(*argv, "ip") == 0) {
716 NEXT_ARG();
717 res = parse_ip(&argc, &argv, sel);
718 } else if (matches(*argv, "ip6") == 0) {
719 NEXT_ARG();
720 res = parse_ip6(&argc, &argv, sel);
721 } else if (matches(*argv, "udp") == 0) {
722 NEXT_ARG();
723 res = parse_udp(&argc, &argv, sel);
724 } else if (matches(*argv, "tcp") == 0) {
725 NEXT_ARG();
726 res = parse_tcp(&argc, &argv, sel);
727 } else if (matches(*argv, "icmp") == 0) {
728 NEXT_ARG();
729 res = parse_icmp(&argc, &argv, sel);
730 } else if (matches(*argv, "mark") == 0) {
731 NEXT_ARG();
732 res = parse_mark(&argc, &argv, n);
733 } else if (matches(*argv, "ether") == 0) {
734 NEXT_ARG();
735 res = parse_ether(&argc, &argv, sel);
736 } else
737 return -1;
738
739 *argc_p = argc;
740 *argv_p = argv;
741 return res;
742 }
743
parse_offset(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)744 static int parse_offset(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
745 {
746 int argc = *argc_p;
747 char **argv = *argv_p;
748
749 while (argc > 0) {
750 if (matches(*argv, "plus") == 0) {
751 int off;
752
753 NEXT_ARG();
754 if (get_integer(&off, *argv, 0))
755 return -1;
756 sel->off = off;
757 sel->flags |= TC_U32_OFFSET;
758 } else if (matches(*argv, "at") == 0) {
759 int off;
760
761 NEXT_ARG();
762 if (get_integer(&off, *argv, 0))
763 return -1;
764 sel->offoff = off;
765 if (off%2) {
766 fprintf(stderr, "offset \"at\" must be even\n");
767 return -1;
768 }
769 sel->flags |= TC_U32_VAROFFSET;
770 } else if (matches(*argv, "mask") == 0) {
771 NEXT_ARG();
772 if (get_be16(&sel->offmask, *argv, 16))
773 return -1;
774 sel->flags |= TC_U32_VAROFFSET;
775 } else if (matches(*argv, "shift") == 0) {
776 int shift;
777
778 NEXT_ARG();
779 if (get_integer(&shift, *argv, 0))
780 return -1;
781 sel->offshift = shift;
782 sel->flags |= TC_U32_VAROFFSET;
783 } else if (matches(*argv, "eat") == 0) {
784 sel->flags |= TC_U32_EAT;
785 } else {
786 break;
787 }
788 argc--; argv++;
789 }
790
791 *argc_p = argc;
792 *argv_p = argv;
793 return 0;
794 }
795
parse_hashkey(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)796 static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
797 {
798 int argc = *argc_p;
799 char **argv = *argv_p;
800
801 while (argc > 0) {
802 if (matches(*argv, "mask") == 0) {
803 NEXT_ARG();
804 if (get_be32(&sel->hmask, *argv, 16))
805 return -1;
806 } else if (matches(*argv, "at") == 0) {
807 int num;
808
809 NEXT_ARG();
810 if (get_integer(&num, *argv, 0))
811 return -1;
812 if (num%4)
813 return -1;
814 sel->hoff = num;
815 } else {
816 break;
817 }
818 argc--; argv++;
819 }
820
821 *argc_p = argc;
822 *argv_p = argv;
823 return 0;
824 }
825
print_ipv4(FILE * f,const struct tc_u32_key * key)826 static void print_ipv4(FILE *f, const struct tc_u32_key *key)
827 {
828 char abuf[256];
829
830 switch (key->off) {
831 case 0:
832 switch (ntohl(key->mask)) {
833 case 0x0f000000:
834 fprintf(f, "\n match IP ihl %u",
835 ntohl(key->val) >> 24);
836 return;
837 case 0x00ff0000:
838 fprintf(f, "\n match IP dsfield %#x",
839 ntohl(key->val) >> 16);
840 return;
841 }
842 break;
843 case 8:
844 if (ntohl(key->mask) == 0x00ff0000) {
845 fprintf(f, "\n match IP protocol %d",
846 ntohl(key->val) >> 16);
847 return;
848 }
849 break;
850 case 12:
851 case 16: {
852 int bits = mask2bits(key->mask);
853
854 if (bits >= 0) {
855 fprintf(f, "\n %s %s/%d",
856 key->off == 12 ? "match IP src" : "match IP dst",
857 inet_ntop(AF_INET, &key->val,
858 abuf, sizeof(abuf)),
859 bits);
860 return;
861 }
862 }
863 break;
864
865 case 20:
866 switch (ntohl(key->mask)) {
867 case 0x0000ffff:
868 fprintf(f, "\n match dport %u",
869 ntohl(key->val) & 0xffff);
870 return;
871 case 0xffff0000:
872 fprintf(f, "\n match sport %u",
873 ntohl(key->val) >> 16);
874 return;
875 case 0xffffffff:
876 fprintf(f, "\n match dport %u, match sport %u",
877 ntohl(key->val) & 0xffff,
878 ntohl(key->val) >> 16);
879
880 return;
881 }
882 /* XXX: Default print_raw */
883 }
884 }
885
print_ipv6(FILE * f,const struct tc_u32_key * key)886 static void print_ipv6(FILE *f, const struct tc_u32_key *key)
887 {
888 char abuf[256];
889
890 switch (key->off) {
891 case 0:
892 switch (ntohl(key->mask)) {
893 case 0x0f000000:
894 fprintf(f, "\n match IP ihl %u",
895 ntohl(key->val) >> 24);
896 return;
897 case 0x00ff0000:
898 fprintf(f, "\n match IP dsfield %#x",
899 ntohl(key->val) >> 16);
900 return;
901 }
902 break;
903 case 8:
904 if (ntohl(key->mask) == 0x00ff0000) {
905 fprintf(f, "\n match IP protocol %d",
906 ntohl(key->val) >> 16);
907 return;
908 }
909 break;
910 case 12:
911 case 16: {
912 int bits = mask2bits(key->mask);
913
914 if (bits >= 0) {
915 fprintf(f, "\n %s %s/%d",
916 key->off == 12 ? "match IP src" : "match IP dst",
917 inet_ntop(AF_INET, &key->val,
918 abuf, sizeof(abuf)),
919 bits);
920 return;
921 }
922 }
923 break;
924
925 case 20:
926 switch (ntohl(key->mask)) {
927 case 0x0000ffff:
928 fprintf(f, "\n match sport %u",
929 ntohl(key->val) & 0xffff);
930 return;
931 case 0xffff0000:
932 fprintf(f, "\n match dport %u",
933 ntohl(key->val) >> 16);
934 return;
935 case 0xffffffff:
936 fprintf(f, "\n match sport %u, match dport %u",
937 ntohl(key->val) & 0xffff,
938 ntohl(key->val) >> 16);
939
940 return;
941 }
942 /* XXX: Default print_raw */
943 }
944 }
945
print_raw(FILE * f,const struct tc_u32_key * key)946 static void print_raw(FILE *f, const struct tc_u32_key *key)
947 {
948 fprintf(f, "\n match %08x/%08x at %s%d",
949 (unsigned int)ntohl(key->val),
950 (unsigned int)ntohl(key->mask),
951 key->offmask ? "nexthdr+" : "",
952 key->off);
953 }
954
955 static const struct {
956 __u16 proto;
957 __u16 pad;
958 void (*pprinter)(FILE *f, const struct tc_u32_key *key);
959 } u32_pprinters[] = {
960 {0, 0, print_raw},
961 {ETH_P_IP, 0, print_ipv4},
962 {ETH_P_IPV6, 0, print_ipv6},
963 };
964
show_keys(FILE * f,const struct tc_u32_key * key)965 static void show_keys(FILE *f, const struct tc_u32_key *key)
966 {
967 int i = 0;
968
969 if (!show_pretty)
970 goto show_k;
971
972 for (i = 0; i < ARRAY_SIZE(u32_pprinters); i++) {
973 if (u32_pprinters[i].proto == ntohs(f_proto)) {
974 show_k:
975 u32_pprinters[i].pprinter(f, key);
976 return;
977 }
978 }
979
980 i = 0;
981 goto show_k;
982 }
983
u32_parse_opt(struct filter_util * qu,char * handle,int argc,char ** argv,struct nlmsghdr * n)984 static int u32_parse_opt(struct filter_util *qu, char *handle,
985 int argc, char **argv, struct nlmsghdr *n)
986 {
987 struct {
988 struct tc_u32_sel sel;
989 struct tc_u32_key keys[128];
990 } sel = {};
991 struct tcmsg *t = NLMSG_DATA(n);
992 struct rtattr *tail;
993 int sel_ok = 0, terminal_ok = 0;
994 int sample_ok = 0;
995 __u32 htid = 0;
996 __u32 order = 0;
997 __u32 flags = 0;
998
999 if (handle && get_u32_handle(&t->tcm_handle, handle)) {
1000 fprintf(stderr, "Illegal filter ID\n");
1001 return -1;
1002 }
1003
1004 if (argc == 0)
1005 return 0;
1006
1007 tail = NLMSG_TAIL(n);
1008 addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
1009
1010 while (argc > 0) {
1011 if (matches(*argv, "match") == 0) {
1012 NEXT_ARG();
1013 if (parse_selector(&argc, &argv, &sel.sel, n)) {
1014 fprintf(stderr, "Illegal \"match\"\n");
1015 return -1;
1016 }
1017 sel_ok++;
1018 continue;
1019 } else if (matches(*argv, "offset") == 0) {
1020 NEXT_ARG();
1021 if (parse_offset(&argc, &argv, &sel.sel)) {
1022 fprintf(stderr, "Illegal \"offset\"\n");
1023 return -1;
1024 }
1025 continue;
1026 } else if (matches(*argv, "hashkey") == 0) {
1027 NEXT_ARG();
1028 if (parse_hashkey(&argc, &argv, &sel.sel)) {
1029 fprintf(stderr, "Illegal \"hashkey\"\n");
1030 return -1;
1031 }
1032 continue;
1033 } else if (matches(*argv, "classid") == 0 ||
1034 strcmp(*argv, "flowid") == 0) {
1035 unsigned int flowid;
1036
1037 NEXT_ARG();
1038 if (get_tc_classid(&flowid, *argv)) {
1039 fprintf(stderr, "Illegal \"classid\"\n");
1040 return -1;
1041 }
1042 addattr_l(n, MAX_MSG, TCA_U32_CLASSID, &flowid, 4);
1043 sel.sel.flags |= TC_U32_TERMINAL;
1044 } else if (matches(*argv, "divisor") == 0) {
1045 unsigned int divisor;
1046
1047 NEXT_ARG();
1048 if (get_unsigned(&divisor, *argv, 0) ||
1049 divisor == 0 ||
1050 divisor > 0x100 || ((divisor - 1) & divisor)) {
1051 fprintf(stderr, "Illegal \"divisor\"\n");
1052 return -1;
1053 }
1054 addattr_l(n, MAX_MSG, TCA_U32_DIVISOR, &divisor, 4);
1055 } else if (matches(*argv, "order") == 0) {
1056 NEXT_ARG();
1057 if (get_u32(&order, *argv, 0)) {
1058 fprintf(stderr, "Illegal \"order\"\n");
1059 return -1;
1060 }
1061 } else if (strcmp(*argv, "link") == 0) {
1062 unsigned int linkid;
1063
1064 NEXT_ARG();
1065 if (get_u32_handle(&linkid, *argv)) {
1066 fprintf(stderr, "Illegal \"link\"\n");
1067 return -1;
1068 }
1069 if (linkid && TC_U32_NODE(linkid)) {
1070 fprintf(stderr, "\"link\" must be a hash table.\n");
1071 return -1;
1072 }
1073 addattr_l(n, MAX_MSG, TCA_U32_LINK, &linkid, 4);
1074 } else if (strcmp(*argv, "ht") == 0) {
1075 unsigned int ht;
1076
1077 NEXT_ARG();
1078 if (get_u32_handle(&ht, *argv)) {
1079 fprintf(stderr, "Illegal \"ht\"\n");
1080 return -1;
1081 }
1082 if (handle && TC_U32_NODE(ht)) {
1083 fprintf(stderr, "\"ht\" must be a hash table.\n");
1084 return -1;
1085 }
1086 if (sample_ok)
1087 htid = (htid & 0xFF000) | (ht & 0xFFF00000);
1088 else
1089 htid = (ht & 0xFFFFF000);
1090 } else if (strcmp(*argv, "sample") == 0) {
1091 __u32 hash;
1092 unsigned int divisor = 0x100;
1093 struct {
1094 struct tc_u32_sel sel;
1095 struct tc_u32_key keys[4];
1096 } sel2 = {};
1097
1098 NEXT_ARG();
1099 if (parse_selector(&argc, &argv, &sel2.sel, n)) {
1100 fprintf(stderr, "Illegal \"sample\"\n");
1101 return -1;
1102 }
1103 if (sel2.sel.nkeys != 1) {
1104 fprintf(stderr, "\"sample\" must contain exactly ONE key.\n");
1105 return -1;
1106 }
1107 if (*argv != 0 && strcmp(*argv, "divisor") == 0) {
1108 NEXT_ARG();
1109 if (get_unsigned(&divisor, *argv, 0) ||
1110 divisor == 0 || divisor > 0x100 ||
1111 ((divisor - 1) & divisor)) {
1112 fprintf(stderr, "Illegal sample \"divisor\"\n");
1113 return -1;
1114 }
1115 NEXT_ARG();
1116 }
1117 hash = sel2.sel.keys[0].val & sel2.sel.keys[0].mask;
1118 hash ^= hash >> 16;
1119 hash ^= hash >> 8;
1120 htid = ((hash % divisor) << 12) | (htid & 0xFFF00000);
1121 sample_ok = 1;
1122 continue;
1123 } else if (strcmp(*argv, "indev") == 0) {
1124 char ind[IFNAMSIZ + 1] = {};
1125
1126 argc--;
1127 argv++;
1128 if (argc < 1) {
1129 fprintf(stderr, "Illegal indev\n");
1130 return -1;
1131 }
1132 strncpy(ind, *argv, sizeof(ind) - 1);
1133 addattr_l(n, MAX_MSG, TCA_U32_INDEV, ind,
1134 strlen(ind) + 1);
1135
1136 } else if (matches(*argv, "action") == 0) {
1137 NEXT_ARG();
1138 if (parse_action(&argc, &argv, TCA_U32_ACT, n)) {
1139 fprintf(stderr, "Illegal \"action\"\n");
1140 return -1;
1141 }
1142 terminal_ok++;
1143 continue;
1144
1145 } else if (matches(*argv, "police") == 0) {
1146 NEXT_ARG();
1147 if (parse_police(&argc, &argv, TCA_U32_POLICE, n)) {
1148 fprintf(stderr, "Illegal \"police\"\n");
1149 return -1;
1150 }
1151 terminal_ok++;
1152 continue;
1153 } else if (strcmp(*argv, "skip_hw") == 0) {
1154 NEXT_ARG();
1155 flags |= TCA_CLS_FLAGS_SKIP_HW;
1156 continue;
1157 } else if (strcmp(*argv, "skip_sw") == 0) {
1158 NEXT_ARG();
1159 flags |= TCA_CLS_FLAGS_SKIP_SW;
1160 continue;
1161 } else if (strcmp(*argv, "help") == 0) {
1162 explain();
1163 return -1;
1164 } else {
1165 fprintf(stderr, "What is \"%s\"?\n", *argv);
1166 explain();
1167 return -1;
1168 }
1169 argc--; argv++;
1170 }
1171
1172 /* We dont necessarily need class/flowids */
1173 if (terminal_ok)
1174 sel.sel.flags |= TC_U32_TERMINAL;
1175
1176 if (order) {
1177 if (TC_U32_NODE(t->tcm_handle) &&
1178 order != TC_U32_NODE(t->tcm_handle)) {
1179 fprintf(stderr, "\"order\" contradicts \"handle\"\n");
1180 return -1;
1181 }
1182 t->tcm_handle |= order;
1183 }
1184
1185 if (htid)
1186 addattr_l(n, MAX_MSG, TCA_U32_HASH, &htid, 4);
1187 if (sel_ok)
1188 addattr_l(n, MAX_MSG, TCA_U32_SEL, &sel,
1189 sizeof(sel.sel) +
1190 sel.sel.nkeys * sizeof(struct tc_u32_key));
1191 if (flags) {
1192 if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW |
1193 TCA_CLS_FLAGS_SKIP_SW))) {
1194 fprintf(stderr,
1195 "skip_hw and skip_sw are mutually exclusive\n");
1196 return -1;
1197 }
1198 addattr_l(n, MAX_MSG, TCA_U32_FLAGS, &flags, 4);
1199 }
1200
1201 tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
1202 return 0;
1203 }
1204
u32_print_opt(struct filter_util * qu,FILE * f,struct rtattr * opt,__u32 handle)1205 static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
1206 __u32 handle)
1207 {
1208 struct rtattr *tb[TCA_U32_MAX + 1];
1209 struct tc_u32_sel *sel = NULL;
1210 struct tc_u32_pcnt *pf = NULL;
1211
1212 if (opt == NULL)
1213 return 0;
1214
1215 parse_rtattr_nested(tb, TCA_U32_MAX, opt);
1216
1217 if (handle) {
1218 SPRINT_BUF(b1);
1219 fprintf(f, "fh %s ", sprint_u32_handle(handle, b1));
1220 }
1221
1222 if (TC_U32_NODE(handle))
1223 fprintf(f, "order %d ", TC_U32_NODE(handle));
1224
1225 if (tb[TCA_U32_SEL]) {
1226 if (RTA_PAYLOAD(tb[TCA_U32_SEL]) < sizeof(*sel))
1227 return -1;
1228
1229 sel = RTA_DATA(tb[TCA_U32_SEL]);
1230 }
1231
1232 if (tb[TCA_U32_DIVISOR]) {
1233 fprintf(f, "ht divisor %d ",
1234 rta_getattr_u32(tb[TCA_U32_DIVISOR]));
1235 } else if (tb[TCA_U32_HASH]) {
1236 __u32 htid = rta_getattr_u32(tb[TCA_U32_HASH]);
1237
1238 fprintf(f, "key ht %x bkt %x ", TC_U32_USERHTID(htid),
1239 TC_U32_HASH(htid));
1240 } else {
1241 fprintf(f, "??? ");
1242 }
1243 if (tb[TCA_U32_CLASSID]) {
1244 SPRINT_BUF(b1);
1245 fprintf(f, "%sflowid %s ",
1246 !sel || !(sel->flags & TC_U32_TERMINAL) ? "*" : "",
1247 sprint_tc_classid(rta_getattr_u32(tb[TCA_U32_CLASSID]),
1248 b1));
1249 } else if (sel && sel->flags & TC_U32_TERMINAL) {
1250 fprintf(f, "terminal flowid ??? ");
1251 }
1252 if (tb[TCA_U32_LINK]) {
1253 SPRINT_BUF(b1);
1254 fprintf(f, "link %s ",
1255 sprint_u32_handle(rta_getattr_u32(tb[TCA_U32_LINK]),
1256 b1));
1257 }
1258
1259 if (tb[TCA_U32_FLAGS]) {
1260 __u32 flags = rta_getattr_u32(tb[TCA_U32_FLAGS]);
1261
1262 if (flags & TCA_CLS_FLAGS_SKIP_HW)
1263 fprintf(f, "skip_hw ");
1264 if (flags & TCA_CLS_FLAGS_SKIP_SW)
1265 fprintf(f, "skip_sw ");
1266
1267 if (flags & TCA_CLS_FLAGS_IN_HW)
1268 fprintf(f, "in_hw ");
1269 else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
1270 fprintf(f, "not_in_hw ");
1271 }
1272
1273 if (tb[TCA_U32_PCNT]) {
1274 if (RTA_PAYLOAD(tb[TCA_U32_PCNT]) < sizeof(*pf)) {
1275 fprintf(f, "Broken perf counters\n");
1276 return -1;
1277 }
1278 pf = RTA_DATA(tb[TCA_U32_PCNT]);
1279 }
1280
1281 if (sel && show_stats && NULL != pf)
1282 fprintf(f, " (rule hit %llu success %llu)",
1283 (unsigned long long) pf->rcnt,
1284 (unsigned long long) pf->rhit);
1285
1286 if (tb[TCA_U32_MARK]) {
1287 struct tc_u32_mark *mark = RTA_DATA(tb[TCA_U32_MARK]);
1288
1289 if (RTA_PAYLOAD(tb[TCA_U32_MARK]) < sizeof(*mark)) {
1290 fprintf(f, "\n Invalid mark (kernel&iproute2 mismatch)\n");
1291 } else {
1292 fprintf(f, "\n mark 0x%04x 0x%04x (success %d)",
1293 mark->val, mark->mask, mark->success);
1294 }
1295 }
1296
1297 if (sel) {
1298 if (sel->nkeys) {
1299 int i;
1300
1301 for (i = 0; i < sel->nkeys; i++) {
1302 show_keys(f, sel->keys + i);
1303 if (show_stats && NULL != pf)
1304 fprintf(f, " (success %llu ) ",
1305 (unsigned long long) pf->kcnts[i]);
1306 }
1307 }
1308
1309 if (sel->flags & (TC_U32_VAROFFSET | TC_U32_OFFSET)) {
1310 fprintf(f, "\n offset ");
1311 if (sel->flags & TC_U32_VAROFFSET)
1312 fprintf(f, "%04x>>%d at %d ",
1313 ntohs(sel->offmask),
1314 sel->offshift, sel->offoff);
1315 if (sel->off)
1316 fprintf(f, "plus %d ", sel->off);
1317 }
1318 if (sel->flags & TC_U32_EAT)
1319 fprintf(f, " eat ");
1320
1321 if (sel->hmask) {
1322 fprintf(f, "\n hash mask %08x at %d ",
1323 (unsigned int)htonl(sel->hmask), sel->hoff);
1324 }
1325 }
1326
1327 if (tb[TCA_U32_POLICE]) {
1328 fprintf(f, "\n");
1329 tc_print_police(f, tb[TCA_U32_POLICE]);
1330 }
1331
1332 if (tb[TCA_U32_INDEV]) {
1333 struct rtattr *idev = tb[TCA_U32_INDEV];
1334
1335 fprintf(f, "\n input dev %s\n", rta_getattr_str(idev));
1336 }
1337
1338 if (tb[TCA_U32_ACT])
1339 tc_print_action(f, tb[TCA_U32_ACT], 0);
1340
1341 return 0;
1342 }
1343
1344 struct filter_util u32_filter_util = {
1345 .id = "u32",
1346 .parse_fopt = u32_parse_opt,
1347 .print_fopt = u32_print_opt,
1348 };
1349