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 (at) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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