1 /* 2 * f_flower.c Flower Classifier 3 * 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 * 9 * Authors: Jiri Pirko <jiri (at) resnulli.us> 10 */ 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <unistd.h> 15 #include <syslog.h> 16 #include <string.h> 17 #include <net/if.h> 18 #include <linux/if_arp.h> 19 #include <linux/if_ether.h> 20 #include <linux/ip.h> 21 #include <linux/tc_act/tc_vlan.h> 22 23 #include "utils.h" 24 #include "tc_util.h" 25 #include "rt_names.h" 26 27 enum flower_matching_flags { 28 FLOWER_IP_FLAGS, 29 }; 30 31 enum flower_endpoint { 32 FLOWER_ENDPOINT_SRC, 33 FLOWER_ENDPOINT_DST 34 }; 35 36 enum flower_icmp_field { 37 FLOWER_ICMP_FIELD_TYPE, 38 FLOWER_ICMP_FIELD_CODE 39 }; 40 41 static void explain(void) 42 { 43 fprintf(stderr, 44 "Usage: ... flower [ MATCH-LIST ]\n" 45 " [ skip_sw | skip_hw ]\n" 46 " [ action ACTION-SPEC ] [ classid CLASSID ]\n" 47 "\n" 48 "Where: MATCH-LIST := [ MATCH-LIST ] MATCH\n" 49 " MATCH := { indev DEV-NAME |\n" 50 " vlan_id VID |\n" 51 " vlan_prio PRIORITY |\n" 52 " vlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n" 53 " dst_mac MASKED-LLADDR |\n" 54 " src_mac MASKED-LLADDR |\n" 55 " ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n" 56 " ip_tos MASKED-IP_TOS |\n" 57 " ip_ttl MASKED-IP_TTL |\n" 58 " dst_ip PREFIX |\n" 59 " src_ip PREFIX |\n" 60 " dst_port PORT-NUMBER |\n" 61 " src_port PORT-NUMBER |\n" 62 " tcp_flags MASKED-TCP_FLAGS |\n" 63 " type MASKED-ICMP-TYPE |\n" 64 " code MASKED-ICMP-CODE |\n" 65 " arp_tip IPV4-PREFIX |\n" 66 " arp_sip IPV4-PREFIX |\n" 67 " arp_op [ request | reply | OP ] |\n" 68 " arp_tha MASKED-LLADDR |\n" 69 " arp_sha MASKED-LLADDR |\n" 70 " enc_dst_ip [ IPV4-ADDR | IPV6-ADDR ] |\n" 71 " enc_src_ip [ IPV4-ADDR | IPV6-ADDR ] |\n" 72 " enc_key_id [ KEY-ID ] |\n" 73 " ip_flags IP-FLAGS | \n" 74 " enc_dst_port [ port_number ] }\n" 75 " FILTERID := X:Y:Z\n" 76 " MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n" 77 " ACTION-SPEC := ... look at individual actions\n" 78 "\n" 79 "NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n" 80 "NOTE: There can be only used one mask per one prio. If user needs\n" 81 " to specify different mask, he has to use different prio.\n"); 82 } 83 84 static int flower_parse_eth_addr(char *str, int addr_type, int mask_type, 85 struct nlmsghdr *n) 86 { 87 int ret, err = -1; 88 char addr[ETH_ALEN], *slash; 89 90 slash = strchr(str, '/'); 91 if (slash) 92 *slash = '\0'; 93 94 ret = ll_addr_a2n(addr, sizeof(addr), str); 95 if (ret < 0) 96 goto err; 97 addattr_l(n, MAX_MSG, addr_type, addr, sizeof(addr)); 98 99 if (slash) { 100 unsigned bits; 101 102 if (!get_unsigned(&bits, slash + 1, 10)) { 103 uint64_t mask; 104 105 /* Extra 16 bit shift to push mac address into 106 * high bits of uint64_t 107 */ 108 mask = htonll(0xffffffffffffULL << (16 + 48 - bits)); 109 memcpy(addr, &mask, ETH_ALEN); 110 } else { 111 ret = ll_addr_a2n(addr, sizeof(addr), slash + 1); 112 if (ret < 0) 113 goto err; 114 } 115 } else { 116 memset(addr, 0xff, ETH_ALEN); 117 } 118 addattr_l(n, MAX_MSG, mask_type, addr, sizeof(addr)); 119 120 err = 0; 121 err: 122 if (slash) 123 *slash = '/'; 124 return err; 125 } 126 127 static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type, 128 __be16 *p_vlan_eth_type, 129 struct nlmsghdr *n) 130 { 131 __be16 vlan_eth_type; 132 133 if (eth_type != htons(ETH_P_8021Q)) { 134 fprintf(stderr, 135 "Can't set \"vlan_ethtype\" if ethertype isn't 802.1Q\n"); 136 return -1; 137 } 138 139 if (ll_proto_a2n(&vlan_eth_type, str)) 140 invarg("invalid vlan_ethtype", str); 141 addattr16(n, MAX_MSG, type, vlan_eth_type); 142 *p_vlan_eth_type = vlan_eth_type; 143 return 0; 144 } 145 146 struct flag_to_string { 147 int flag; 148 enum flower_matching_flags type; 149 char *string; 150 }; 151 152 static struct flag_to_string flags_str[] = { 153 { TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOWER_IP_FLAGS, "frag" }, 154 }; 155 156 static int flower_parse_matching_flags(char *str, 157 enum flower_matching_flags type, 158 __u32 *mtf, __u32 *mtf_mask) 159 { 160 char *token; 161 bool no; 162 bool found; 163 int i; 164 165 token = strtok(str, "/"); 166 167 while (token) { 168 if (!strncmp(token, "no", 2)) { 169 no = true; 170 token += 2; 171 } else 172 no = false; 173 174 found = false; 175 for (i = 0; i < ARRAY_SIZE(flags_str); i++) { 176 if (type != flags_str[i].type) 177 continue; 178 179 if (!strcmp(token, flags_str[i].string)) { 180 if (no) 181 *mtf &= ~flags_str[i].flag; 182 else 183 *mtf |= flags_str[i].flag; 184 185 *mtf_mask |= flags_str[i].flag; 186 found = true; 187 break; 188 } 189 } 190 if (!found) 191 return -1; 192 193 token = strtok(NULL, "/"); 194 } 195 196 return 0; 197 } 198 199 static int flower_parse_ip_proto(char *str, __be16 eth_type, int type, 200 __u8 *p_ip_proto, struct nlmsghdr *n) 201 { 202 int ret; 203 __u8 ip_proto; 204 205 if (eth_type != htons(ETH_P_IP) && eth_type != htons(ETH_P_IPV6)) 206 goto err; 207 208 if (matches(str, "tcp") == 0) { 209 ip_proto = IPPROTO_TCP; 210 } else if (matches(str, "udp") == 0) { 211 ip_proto = IPPROTO_UDP; 212 } else if (matches(str, "sctp") == 0) { 213 ip_proto = IPPROTO_SCTP; 214 } else if (matches(str, "icmp") == 0) { 215 if (eth_type != htons(ETH_P_IP)) 216 goto err; 217 ip_proto = IPPROTO_ICMP; 218 } else if (matches(str, "icmpv6") == 0) { 219 if (eth_type != htons(ETH_P_IPV6)) 220 goto err; 221 ip_proto = IPPROTO_ICMPV6; 222 } else { 223 ret = get_u8(&ip_proto, str, 16); 224 if (ret) 225 return -1; 226 } 227 addattr8(n, MAX_MSG, type, ip_proto); 228 *p_ip_proto = ip_proto; 229 return 0; 230 231 err: 232 fprintf(stderr, "Illegal \"eth_type\" for ip proto\n"); 233 return -1; 234 } 235 236 static int __flower_parse_ip_addr(char *str, int family, 237 int addr4_type, int mask4_type, 238 int addr6_type, int mask6_type, 239 struct nlmsghdr *n) 240 { 241 int ret; 242 inet_prefix addr; 243 int bits; 244 int i; 245 246 ret = get_prefix(&addr, str, family); 247 if (ret) 248 return -1; 249 250 if (family && (addr.family != family)) { 251 fprintf(stderr, "Illegal \"eth_type\" for ip address\n"); 252 return -1; 253 } 254 255 addattr_l(n, MAX_MSG, addr.family == AF_INET ? addr4_type : addr6_type, 256 addr.data, addr.bytelen); 257 258 memset(addr.data, 0xff, addr.bytelen); 259 bits = addr.bitlen; 260 for (i = 0; i < addr.bytelen / 4; i++) { 261 if (!bits) { 262 addr.data[i] = 0; 263 } else if (bits / 32 >= 1) { 264 bits -= 32; 265 } else { 266 addr.data[i] <<= 32 - bits; 267 addr.data[i] = htonl(addr.data[i]); 268 bits = 0; 269 } 270 } 271 272 addattr_l(n, MAX_MSG, addr.family == AF_INET ? mask4_type : mask6_type, 273 addr.data, addr.bytelen); 274 275 return 0; 276 } 277 278 static int flower_parse_ip_addr(char *str, __be16 eth_type, 279 int addr4_type, int mask4_type, 280 int addr6_type, int mask6_type, 281 struct nlmsghdr *n) 282 { 283 int family; 284 285 if (eth_type == htons(ETH_P_IP)) { 286 family = AF_INET; 287 } else if (eth_type == htons(ETH_P_IPV6)) { 288 family = AF_INET6; 289 } else if (!eth_type) { 290 family = AF_UNSPEC; 291 } else { 292 return -1; 293 } 294 295 return __flower_parse_ip_addr(str, family, addr4_type, mask4_type, 296 addr6_type, mask6_type, n); 297 } 298 299 static bool flower_eth_type_arp(__be16 eth_type) 300 { 301 return eth_type == htons(ETH_P_ARP) || eth_type == htons(ETH_P_RARP); 302 } 303 304 static int flower_parse_arp_ip_addr(char *str, __be16 eth_type, 305 int addr_type, int mask_type, 306 struct nlmsghdr *n) 307 { 308 if (!flower_eth_type_arp(eth_type)) 309 return -1; 310 311 return __flower_parse_ip_addr(str, AF_INET, addr_type, mask_type, 312 TCA_FLOWER_UNSPEC, TCA_FLOWER_UNSPEC, n); 313 } 314 315 static int flower_parse_u8(char *str, int value_type, int mask_type, 316 int (*value_from_name)(const char *str, 317 __u8 *value), 318 bool (*value_validate)(__u8 value), 319 struct nlmsghdr *n) 320 { 321 char *slash; 322 int ret, err = -1; 323 __u8 value, mask; 324 325 slash = strchr(str, '/'); 326 if (slash) 327 *slash = '\0'; 328 329 ret = value_from_name ? value_from_name(str, &value) : -1; 330 if (ret < 0) { 331 ret = get_u8(&value, str, 10); 332 if (ret) 333 goto err; 334 } 335 336 if (value_validate && !value_validate(value)) 337 goto err; 338 339 if (slash) { 340 ret = get_u8(&mask, slash + 1, 10); 341 if (ret) 342 goto err; 343 } 344 else { 345 mask = UINT8_MAX; 346 } 347 348 addattr8(n, MAX_MSG, value_type, value); 349 addattr8(n, MAX_MSG, mask_type, mask); 350 351 err = 0; 352 err: 353 if (slash) 354 *slash = '/'; 355 return err; 356 } 357 358 static const char *flower_print_arp_op_to_name(__u8 op) 359 { 360 switch (op) { 361 case ARPOP_REQUEST: 362 return "request"; 363 case ARPOP_REPLY: 364 return "reply"; 365 default: 366 return NULL; 367 } 368 } 369 370 static int flower_arp_op_from_name(const char *name, __u8 *op) 371 { 372 if (!strcmp(name, "request")) 373 *op = ARPOP_REQUEST; 374 else if (!strcmp(name, "reply")) 375 *op = ARPOP_REPLY; 376 else 377 return -1; 378 379 return 0; 380 } 381 382 static bool flow_arp_op_validate(__u8 op) 383 { 384 return !op || op == ARPOP_REQUEST || op == ARPOP_REPLY; 385 } 386 387 static int flower_parse_arp_op(char *str, __be16 eth_type, 388 int op_type, int mask_type, 389 struct nlmsghdr *n) 390 { 391 if (!flower_eth_type_arp(eth_type)) 392 return -1; 393 394 return flower_parse_u8(str, op_type, mask_type, flower_arp_op_from_name, 395 flow_arp_op_validate, n); 396 } 397 398 static int flower_icmp_attr_type(__be16 eth_type, __u8 ip_proto, 399 enum flower_icmp_field field) 400 { 401 if (eth_type == htons(ETH_P_IP) && ip_proto == IPPROTO_ICMP) 402 return field == FLOWER_ICMP_FIELD_CODE ? 403 TCA_FLOWER_KEY_ICMPV4_CODE : 404 TCA_FLOWER_KEY_ICMPV4_TYPE; 405 else if (eth_type == htons(ETH_P_IPV6) && ip_proto == IPPROTO_ICMPV6) 406 return field == FLOWER_ICMP_FIELD_CODE ? 407 TCA_FLOWER_KEY_ICMPV6_CODE : 408 TCA_FLOWER_KEY_ICMPV6_TYPE; 409 410 return -1; 411 } 412 413 static int flower_icmp_attr_mask_type(__be16 eth_type, __u8 ip_proto, 414 enum flower_icmp_field field) 415 { 416 if (eth_type == htons(ETH_P_IP) && ip_proto == IPPROTO_ICMP) 417 return field == FLOWER_ICMP_FIELD_CODE ? 418 TCA_FLOWER_KEY_ICMPV4_CODE_MASK : 419 TCA_FLOWER_KEY_ICMPV4_TYPE_MASK; 420 else if (eth_type == htons(ETH_P_IPV6) && ip_proto == IPPROTO_ICMPV6) 421 return field == FLOWER_ICMP_FIELD_CODE ? 422 TCA_FLOWER_KEY_ICMPV6_CODE_MASK : 423 TCA_FLOWER_KEY_ICMPV6_TYPE_MASK; 424 425 return -1; 426 } 427 428 static int flower_parse_icmp(char *str, __u16 eth_type, __u8 ip_proto, 429 enum flower_icmp_field field, struct nlmsghdr *n) 430 { 431 int value_type, mask_type; 432 433 value_type = flower_icmp_attr_type(eth_type, ip_proto, field); 434 mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto, field); 435 if (value_type < 0 || mask_type < 0) 436 return -1; 437 438 return flower_parse_u8(str, value_type, mask_type, NULL, NULL, n); 439 } 440 441 static int flower_port_attr_type(__u8 ip_proto, enum flower_endpoint endpoint) 442 { 443 if (ip_proto == IPPROTO_TCP) 444 return endpoint == FLOWER_ENDPOINT_SRC ? 445 TCA_FLOWER_KEY_TCP_SRC : 446 TCA_FLOWER_KEY_TCP_DST; 447 else if (ip_proto == IPPROTO_UDP) 448 return endpoint == FLOWER_ENDPOINT_SRC ? 449 TCA_FLOWER_KEY_UDP_SRC : 450 TCA_FLOWER_KEY_UDP_DST; 451 else if (ip_proto == IPPROTO_SCTP) 452 return endpoint == FLOWER_ENDPOINT_SRC ? 453 TCA_FLOWER_KEY_SCTP_SRC : 454 TCA_FLOWER_KEY_SCTP_DST; 455 else 456 return -1; 457 } 458 459 static int flower_parse_port(char *str, __u8 ip_proto, 460 enum flower_endpoint endpoint, 461 struct nlmsghdr *n) 462 { 463 int ret; 464 int type; 465 __be16 port; 466 467 type = flower_port_attr_type(ip_proto, endpoint); 468 if (type < 0) 469 return -1; 470 471 ret = get_be16(&port, str, 10); 472 if (ret) 473 return -1; 474 475 addattr16(n, MAX_MSG, type, port); 476 477 return 0; 478 } 479 480 #define TCP_FLAGS_MAX_MASK 0xfff 481 482 static int flower_parse_tcp_flags(char *str, int flags_type, int mask_type, 483 struct nlmsghdr *n) 484 { 485 char *slash; 486 int ret, err = -1; 487 __u16 flags; 488 489 slash = strchr(str, '/'); 490 if (slash) 491 *slash = '\0'; 492 493 ret = get_u16(&flags, str, 16); 494 if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK) 495 goto err; 496 497 addattr16(n, MAX_MSG, flags_type, htons(flags)); 498 499 if (slash) { 500 ret = get_u16(&flags, slash + 1, 16); 501 if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK) 502 goto err; 503 } else { 504 flags = TCP_FLAGS_MAX_MASK; 505 } 506 addattr16(n, MAX_MSG, mask_type, htons(flags)); 507 508 err = 0; 509 err: 510 if (slash) 511 *slash = '/'; 512 return err; 513 } 514 515 static int flower_parse_ip_tos_ttl(char *str, int key_type, int mask_type, 516 struct nlmsghdr *n) 517 { 518 char *slash; 519 int ret, err = -1; 520 __u8 tos_ttl; 521 522 slash = strchr(str, '/'); 523 if (slash) 524 *slash = '\0'; 525 526 ret = get_u8(&tos_ttl, str, 10); 527 if (ret < 0) 528 ret = get_u8(&tos_ttl, str, 16); 529 if (ret < 0) 530 goto err; 531 532 addattr8(n, MAX_MSG, key_type, tos_ttl); 533 534 if (slash) { 535 ret = get_u8(&tos_ttl, slash + 1, 16); 536 if (ret < 0) 537 goto err; 538 } else { 539 tos_ttl = 0xff; 540 } 541 addattr8(n, MAX_MSG, mask_type, tos_ttl); 542 543 err = 0; 544 err: 545 if (slash) 546 *slash = '/'; 547 return err; 548 } 549 550 static int flower_parse_key_id(const char *str, int type, struct nlmsghdr *n) 551 { 552 int ret; 553 __be32 key_id; 554 555 ret = get_be32(&key_id, str, 10); 556 if (!ret) 557 addattr32(n, MAX_MSG, type, key_id); 558 559 return ret; 560 } 561 562 static int flower_parse_enc_port(char *str, int type, struct nlmsghdr *n) 563 { 564 int ret; 565 __be16 port; 566 567 ret = get_be16(&port, str, 10); 568 if (ret) 569 return -1; 570 571 addattr16(n, MAX_MSG, type, port); 572 573 return 0; 574 } 575 576 static int flower_parse_opt(struct filter_util *qu, char *handle, 577 int argc, char **argv, struct nlmsghdr *n) 578 { 579 int ret; 580 struct tcmsg *t = NLMSG_DATA(n); 581 struct rtattr *tail; 582 __be16 eth_type = TC_H_MIN(t->tcm_info); 583 __be16 vlan_ethtype = 0; 584 __u8 ip_proto = 0xff; 585 __u32 flags = 0; 586 __u32 mtf = 0; 587 __u32 mtf_mask = 0; 588 589 if (handle) { 590 ret = get_u32(&t->tcm_handle, handle, 0); 591 if (ret) { 592 fprintf(stderr, "Illegal \"handle\"\n"); 593 return -1; 594 } 595 } 596 597 tail = (struct rtattr *) (((void *) n) + NLMSG_ALIGN(n->nlmsg_len)); 598 addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0); 599 600 if (argc == 0) { 601 /*at minimal we will match all ethertype packets */ 602 goto parse_done; 603 } 604 605 while (argc > 0) { 606 if (matches(*argv, "classid") == 0 || 607 matches(*argv, "flowid") == 0) { 608 unsigned int handle; 609 610 NEXT_ARG(); 611 ret = get_tc_classid(&handle, *argv); 612 if (ret) { 613 fprintf(stderr, "Illegal \"classid\"\n"); 614 return -1; 615 } 616 addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle, 4); 617 } else if (matches(*argv, "ip_flags") == 0) { 618 NEXT_ARG(); 619 ret = flower_parse_matching_flags(*argv, 620 FLOWER_IP_FLAGS, 621 &mtf, 622 &mtf_mask); 623 if (ret < 0) { 624 fprintf(stderr, "Illegal \"ip_flags\"\n"); 625 return -1; 626 } 627 } else if (matches(*argv, "skip_hw") == 0) { 628 flags |= TCA_CLS_FLAGS_SKIP_HW; 629 } else if (matches(*argv, "skip_sw") == 0) { 630 flags |= TCA_CLS_FLAGS_SKIP_SW; 631 } else if (matches(*argv, "indev") == 0) { 632 NEXT_ARG(); 633 if (check_ifname(*argv)) 634 invarg("\"indev\" not a valid ifname", *argv); 635 addattrstrz(n, MAX_MSG, TCA_FLOWER_INDEV, *argv); 636 } else if (matches(*argv, "vlan_id") == 0) { 637 __u16 vid; 638 639 NEXT_ARG(); 640 if (eth_type != htons(ETH_P_8021Q)) { 641 fprintf(stderr, 642 "Can't set \"vlan_id\" if ethertype isn't 802.1Q\n"); 643 return -1; 644 } 645 ret = get_u16(&vid, *argv, 10); 646 if (ret < 0 || vid & ~0xfff) { 647 fprintf(stderr, "Illegal \"vlan_id\"\n"); 648 return -1; 649 } 650 addattr16(n, MAX_MSG, TCA_FLOWER_KEY_VLAN_ID, vid); 651 } else if (matches(*argv, "vlan_prio") == 0) { 652 __u8 vlan_prio; 653 654 NEXT_ARG(); 655 if (eth_type != htons(ETH_P_8021Q)) { 656 fprintf(stderr, 657 "Can't set \"vlan_prio\" if ethertype isn't 802.1Q\n"); 658 return -1; 659 } 660 ret = get_u8(&vlan_prio, *argv, 10); 661 if (ret < 0 || vlan_prio & ~0x7) { 662 fprintf(stderr, "Illegal \"vlan_prio\"\n"); 663 return -1; 664 } 665 addattr8(n, MAX_MSG, 666 TCA_FLOWER_KEY_VLAN_PRIO, vlan_prio); 667 } else if (matches(*argv, "vlan_ethtype") == 0) { 668 NEXT_ARG(); 669 ret = flower_parse_vlan_eth_type(*argv, eth_type, 670 TCA_FLOWER_KEY_VLAN_ETH_TYPE, 671 &vlan_ethtype, n); 672 if (ret < 0) 673 return -1; 674 } else if (matches(*argv, "dst_mac") == 0) { 675 NEXT_ARG(); 676 ret = flower_parse_eth_addr(*argv, 677 TCA_FLOWER_KEY_ETH_DST, 678 TCA_FLOWER_KEY_ETH_DST_MASK, 679 n); 680 if (ret < 0) { 681 fprintf(stderr, "Illegal \"dst_mac\"\n"); 682 return -1; 683 } 684 } else if (matches(*argv, "src_mac") == 0) { 685 NEXT_ARG(); 686 ret = flower_parse_eth_addr(*argv, 687 TCA_FLOWER_KEY_ETH_SRC, 688 TCA_FLOWER_KEY_ETH_SRC_MASK, 689 n); 690 if (ret < 0) { 691 fprintf(stderr, "Illegal \"src_mac\"\n"); 692 return -1; 693 } 694 } else if (matches(*argv, "ip_proto") == 0) { 695 NEXT_ARG(); 696 ret = flower_parse_ip_proto(*argv, vlan_ethtype ? 697 vlan_ethtype : eth_type, 698 TCA_FLOWER_KEY_IP_PROTO, 699 &ip_proto, n); 700 if (ret < 0) { 701 fprintf(stderr, "Illegal \"ip_proto\"\n"); 702 return -1; 703 } 704 } else if (matches(*argv, "ip_tos") == 0) { 705 NEXT_ARG(); 706 ret = flower_parse_ip_tos_ttl(*argv, 707 TCA_FLOWER_KEY_IP_TOS, 708 TCA_FLOWER_KEY_IP_TOS_MASK, 709 n); 710 if (ret < 0) { 711 fprintf(stderr, "Illegal \"ip_tos\"\n"); 712 return -1; 713 } 714 } else if (matches(*argv, "ip_ttl") == 0) { 715 NEXT_ARG(); 716 ret = flower_parse_ip_tos_ttl(*argv, 717 TCA_FLOWER_KEY_IP_TTL, 718 TCA_FLOWER_KEY_IP_TTL_MASK, 719 n); 720 if (ret < 0) { 721 fprintf(stderr, "Illegal \"ip_ttl\"\n"); 722 return -1; 723 } 724 } else if (matches(*argv, "dst_ip") == 0) { 725 NEXT_ARG(); 726 ret = flower_parse_ip_addr(*argv, vlan_ethtype ? 727 vlan_ethtype : eth_type, 728 TCA_FLOWER_KEY_IPV4_DST, 729 TCA_FLOWER_KEY_IPV4_DST_MASK, 730 TCA_FLOWER_KEY_IPV6_DST, 731 TCA_FLOWER_KEY_IPV6_DST_MASK, 732 n); 733 if (ret < 0) { 734 fprintf(stderr, "Illegal \"dst_ip\"\n"); 735 return -1; 736 } 737 } else if (matches(*argv, "src_ip") == 0) { 738 NEXT_ARG(); 739 ret = flower_parse_ip_addr(*argv, vlan_ethtype ? 740 vlan_ethtype : eth_type, 741 TCA_FLOWER_KEY_IPV4_SRC, 742 TCA_FLOWER_KEY_IPV4_SRC_MASK, 743 TCA_FLOWER_KEY_IPV6_SRC, 744 TCA_FLOWER_KEY_IPV6_SRC_MASK, 745 n); 746 if (ret < 0) { 747 fprintf(stderr, "Illegal \"src_ip\"\n"); 748 return -1; 749 } 750 } else if (matches(*argv, "dst_port") == 0) { 751 NEXT_ARG(); 752 ret = flower_parse_port(*argv, ip_proto, 753 FLOWER_ENDPOINT_DST, n); 754 if (ret < 0) { 755 fprintf(stderr, "Illegal \"dst_port\"\n"); 756 return -1; 757 } 758 } else if (matches(*argv, "src_port") == 0) { 759 NEXT_ARG(); 760 ret = flower_parse_port(*argv, ip_proto, 761 FLOWER_ENDPOINT_SRC, n); 762 if (ret < 0) { 763 fprintf(stderr, "Illegal \"src_port\"\n"); 764 return -1; 765 } 766 } else if (matches(*argv, "tcp_flags") == 0) { 767 NEXT_ARG(); 768 ret = flower_parse_tcp_flags(*argv, 769 TCA_FLOWER_KEY_TCP_FLAGS, 770 TCA_FLOWER_KEY_TCP_FLAGS_MASK, 771 n); 772 if (ret < 0) { 773 fprintf(stderr, "Illegal \"tcp_flags\"\n"); 774 return -1; 775 } 776 } else if (matches(*argv, "type") == 0) { 777 NEXT_ARG(); 778 ret = flower_parse_icmp(*argv, eth_type, ip_proto, 779 FLOWER_ICMP_FIELD_TYPE, n); 780 if (ret < 0) { 781 fprintf(stderr, "Illegal \"icmp type\"\n"); 782 return -1; 783 } 784 } else if (matches(*argv, "code") == 0) { 785 NEXT_ARG(); 786 ret = flower_parse_icmp(*argv, eth_type, ip_proto, 787 FLOWER_ICMP_FIELD_CODE, n); 788 if (ret < 0) { 789 fprintf(stderr, "Illegal \"icmp code\"\n"); 790 return -1; 791 } 792 } else if (matches(*argv, "arp_tip") == 0) { 793 NEXT_ARG(); 794 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ? 795 vlan_ethtype : eth_type, 796 TCA_FLOWER_KEY_ARP_TIP, 797 TCA_FLOWER_KEY_ARP_TIP_MASK, 798 n); 799 if (ret < 0) { 800 fprintf(stderr, "Illegal \"arp_tip\"\n"); 801 return -1; 802 } 803 } else if (matches(*argv, "arp_sip") == 0) { 804 NEXT_ARG(); 805 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ? 806 vlan_ethtype : eth_type, 807 TCA_FLOWER_KEY_ARP_SIP, 808 TCA_FLOWER_KEY_ARP_SIP_MASK, 809 n); 810 if (ret < 0) { 811 fprintf(stderr, "Illegal \"arp_sip\"\n"); 812 return -1; 813 } 814 } else if (matches(*argv, "arp_op") == 0) { 815 NEXT_ARG(); 816 ret = flower_parse_arp_op(*argv, vlan_ethtype ? 817 vlan_ethtype : eth_type, 818 TCA_FLOWER_KEY_ARP_OP, 819 TCA_FLOWER_KEY_ARP_OP_MASK, 820 n); 821 if (ret < 0) { 822 fprintf(stderr, "Illegal \"arp_op\"\n"); 823 return -1; 824 } 825 } else if (matches(*argv, "arp_tha") == 0) { 826 NEXT_ARG(); 827 ret = flower_parse_eth_addr(*argv, 828 TCA_FLOWER_KEY_ARP_THA, 829 TCA_FLOWER_KEY_ARP_THA_MASK, 830 n); 831 if (ret < 0) { 832 fprintf(stderr, "Illegal \"arp_tha\"\n"); 833 return -1; 834 } 835 } else if (matches(*argv, "arp_sha") == 0) { 836 NEXT_ARG(); 837 ret = flower_parse_eth_addr(*argv, 838 TCA_FLOWER_KEY_ARP_SHA, 839 TCA_FLOWER_KEY_ARP_SHA_MASK, 840 n); 841 if (ret < 0) { 842 fprintf(stderr, "Illegal \"arp_sha\"\n"); 843 return -1; 844 } 845 } else if (matches(*argv, "enc_dst_ip") == 0) { 846 NEXT_ARG(); 847 ret = flower_parse_ip_addr(*argv, 0, 848 TCA_FLOWER_KEY_ENC_IPV4_DST, 849 TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, 850 TCA_FLOWER_KEY_ENC_IPV6_DST, 851 TCA_FLOWER_KEY_ENC_IPV6_DST_MASK, 852 n); 853 if (ret < 0) { 854 fprintf(stderr, "Illegal \"enc_dst_ip\"\n"); 855 return -1; 856 } 857 } else if (matches(*argv, "enc_src_ip") == 0) { 858 NEXT_ARG(); 859 ret = flower_parse_ip_addr(*argv, 0, 860 TCA_FLOWER_KEY_ENC_IPV4_SRC, 861 TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, 862 TCA_FLOWER_KEY_ENC_IPV6_SRC, 863 TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK, 864 n); 865 if (ret < 0) { 866 fprintf(stderr, "Illegal \"enc_src_ip\"\n"); 867 return -1; 868 } 869 } else if (matches(*argv, "enc_key_id") == 0) { 870 NEXT_ARG(); 871 ret = flower_parse_key_id(*argv, 872 TCA_FLOWER_KEY_ENC_KEY_ID, n); 873 if (ret < 0) { 874 fprintf(stderr, "Illegal \"enc_key_id\"\n"); 875 return -1; 876 } 877 } else if (matches(*argv, "enc_dst_port") == 0) { 878 NEXT_ARG(); 879 ret = flower_parse_enc_port(*argv, 880 TCA_FLOWER_KEY_ENC_UDP_DST_PORT, n); 881 if (ret < 0) { 882 fprintf(stderr, "Illegal \"enc_dst_port\"\n"); 883 return -1; 884 } 885 } else if (matches(*argv, "action") == 0) { 886 NEXT_ARG(); 887 ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n); 888 if (ret) { 889 fprintf(stderr, "Illegal \"action\"\n"); 890 return -1; 891 } 892 continue; 893 } else if (strcmp(*argv, "help") == 0) { 894 explain(); 895 return -1; 896 } else { 897 fprintf(stderr, "What is \"%s\"?\n", *argv); 898 explain(); 899 return -1; 900 } 901 argc--; argv++; 902 } 903 904 parse_done: 905 ret = addattr32(n, MAX_MSG, TCA_FLOWER_FLAGS, flags); 906 if (ret) 907 return ret; 908 909 if (mtf_mask) { 910 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS, htonl(mtf)); 911 if (ret) 912 return ret; 913 914 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS_MASK, htonl(mtf_mask)); 915 if (ret) 916 return ret; 917 } 918 919 if (eth_type != htons(ETH_P_ALL)) { 920 ret = addattr16(n, MAX_MSG, TCA_FLOWER_KEY_ETH_TYPE, eth_type); 921 if (ret) 922 return ret; 923 } 924 925 tail->rta_len = (((void *)n)+n->nlmsg_len) - (void *)tail; 926 927 return 0; 928 } 929 930 static int __mask_bits(char *addr, size_t len) 931 { 932 int bits = 0; 933 bool hole = false; 934 int i; 935 int j; 936 937 for (i = 0; i < len; i++, addr++) { 938 for (j = 7; j >= 0; j--) { 939 if (((*addr) >> j) & 0x1) { 940 if (hole) 941 return -1; 942 bits++; 943 } else if (bits) { 944 hole = true; 945 } else{ 946 return -1; 947 } 948 } 949 } 950 return bits; 951 } 952 953 static void flower_print_eth_addr(FILE *f, char *name, 954 struct rtattr *addr_attr, 955 struct rtattr *mask_attr) 956 { 957 SPRINT_BUF(b1); 958 int bits; 959 960 if (!addr_attr || RTA_PAYLOAD(addr_attr) != ETH_ALEN) 961 return; 962 fprintf(f, "\n %s %s", name, ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN, 963 0, b1, sizeof(b1))); 964 if (!mask_attr || RTA_PAYLOAD(mask_attr) != ETH_ALEN) 965 return; 966 bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN); 967 if (bits < 0) 968 fprintf(f, "/%s", ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN, 969 0, b1, sizeof(b1))); 970 else if (bits < ETH_ALEN * 8) 971 fprintf(f, "/%d", bits); 972 } 973 974 static void flower_print_eth_type(FILE *f, __be16 *p_eth_type, 975 struct rtattr *eth_type_attr) 976 { 977 __be16 eth_type; 978 979 if (!eth_type_attr) 980 return; 981 982 eth_type = rta_getattr_u16(eth_type_attr); 983 fprintf(f, "\n eth_type "); 984 if (eth_type == htons(ETH_P_IP)) 985 fprintf(f, "ipv4"); 986 else if (eth_type == htons(ETH_P_IPV6)) 987 fprintf(f, "ipv6"); 988 else if (eth_type == htons(ETH_P_ARP)) 989 fprintf(f, "arp"); 990 else if (eth_type == htons(ETH_P_RARP)) 991 fprintf(f, "rarp"); 992 else 993 fprintf(f, "%04x", ntohs(eth_type)); 994 *p_eth_type = eth_type; 995 } 996 997 static void flower_print_ip_proto(FILE *f, __u8 *p_ip_proto, 998 struct rtattr *ip_proto_attr) 999 { 1000 __u8 ip_proto; 1001 1002 if (!ip_proto_attr) 1003 return; 1004 1005 ip_proto = rta_getattr_u8(ip_proto_attr); 1006 fprintf(f, "\n ip_proto "); 1007 if (ip_proto == IPPROTO_TCP) 1008 fprintf(f, "tcp"); 1009 else if (ip_proto == IPPROTO_UDP) 1010 fprintf(f, "udp"); 1011 else if (ip_proto == IPPROTO_SCTP) 1012 fprintf(f, "sctp"); 1013 else if (ip_proto == IPPROTO_ICMP) 1014 fprintf(f, "icmp"); 1015 else if (ip_proto == IPPROTO_ICMPV6) 1016 fprintf(f, "icmpv6"); 1017 else 1018 fprintf(f, "%02x", ip_proto); 1019 *p_ip_proto = ip_proto; 1020 } 1021 1022 static void flower_print_ip_attr(FILE *f, char *name, 1023 struct rtattr *key_attr, 1024 struct rtattr *mask_attr) 1025 { 1026 if (!key_attr) 1027 return; 1028 1029 fprintf(f, "\n %s %x", name, rta_getattr_u8(key_attr)); 1030 if (!mask_attr) 1031 return; 1032 fprintf(f, "/%x", rta_getattr_u8(mask_attr)); 1033 } 1034 1035 static void flower_print_matching_flags(FILE *f, char *name, 1036 enum flower_matching_flags type, 1037 struct rtattr *attr, 1038 struct rtattr *mask_attr) 1039 { 1040 int i; 1041 int count = 0; 1042 __u32 mtf; 1043 __u32 mtf_mask; 1044 1045 if (!mask_attr || RTA_PAYLOAD(mask_attr) != 4) 1046 return; 1047 1048 mtf = ntohl(rta_getattr_u32(attr)); 1049 mtf_mask = ntohl(rta_getattr_u32(mask_attr)); 1050 1051 for (i = 0; i < ARRAY_SIZE(flags_str); i++) { 1052 if (type != flags_str[i].type) 1053 continue; 1054 if (mtf_mask & flags_str[i].flag) { 1055 if (++count == 1) 1056 fprintf(f, "\n %s ", name); 1057 else 1058 fprintf(f, "/"); 1059 1060 if (mtf & flags_str[i].flag) 1061 fprintf(f, "%s", flags_str[i].string); 1062 else 1063 fprintf(f, "no%s", flags_str[i].string); 1064 } 1065 } 1066 } 1067 1068 static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type, 1069 struct rtattr *addr4_attr, 1070 struct rtattr *mask4_attr, 1071 struct rtattr *addr6_attr, 1072 struct rtattr *mask6_attr) 1073 { 1074 struct rtattr *addr_attr; 1075 struct rtattr *mask_attr; 1076 int family; 1077 size_t len; 1078 int bits; 1079 1080 if (eth_type == htons(ETH_P_IP)) { 1081 family = AF_INET; 1082 addr_attr = addr4_attr; 1083 mask_attr = mask4_attr; 1084 len = 4; 1085 } else if (eth_type == htons(ETH_P_IPV6)) { 1086 family = AF_INET6; 1087 addr_attr = addr6_attr; 1088 mask_attr = mask6_attr; 1089 len = 16; 1090 } else { 1091 return; 1092 } 1093 if (!addr_attr || RTA_PAYLOAD(addr_attr) != len) 1094 return; 1095 fprintf(f, "\n %s %s", name, rt_addr_n2a_rta(family, addr_attr)); 1096 if (!mask_attr || RTA_PAYLOAD(mask_attr) != len) 1097 return; 1098 bits = __mask_bits(RTA_DATA(mask_attr), len); 1099 if (bits < 0) 1100 fprintf(f, "/%s", rt_addr_n2a_rta(family, mask_attr)); 1101 else if (bits < len * 8) 1102 fprintf(f, "/%d", bits); 1103 } 1104 static void flower_print_ip4_addr(FILE *f, char *name, 1105 struct rtattr *addr_attr, 1106 struct rtattr *mask_attr) 1107 { 1108 return flower_print_ip_addr(f, name, htons(ETH_P_IP), 1109 addr_attr, mask_attr, 0, 0); 1110 } 1111 1112 static void flower_print_port(FILE *f, char *name, struct rtattr *attr) 1113 { 1114 if (attr) 1115 fprintf(f, "\n %s %d", name, rta_getattr_be16(attr)); 1116 } 1117 1118 static void flower_print_tcp_flags(FILE *f, char *name, 1119 struct rtattr *flags_attr, 1120 struct rtattr *mask_attr) 1121 { 1122 if (!flags_attr) 1123 return; 1124 fprintf(f, "\n %s %x", name, rta_getattr_be16(flags_attr)); 1125 if (!mask_attr) 1126 return; 1127 fprintf(f, "/%x", rta_getattr_be16(mask_attr)); 1128 } 1129 1130 1131 static void flower_print_key_id(FILE *f, const char *name, 1132 struct rtattr *attr) 1133 { 1134 if (attr) 1135 fprintf(f, "\n %s %d", name, rta_getattr_be32(attr)); 1136 } 1137 1138 static void flower_print_masked_u8(FILE *f, const char *name, 1139 struct rtattr *attr, 1140 struct rtattr *mask_attr, 1141 const char *(*value_to_str)(__u8 value)) 1142 { 1143 const char *value_str = NULL; 1144 __u8 value, mask; 1145 1146 if (!attr) 1147 return; 1148 1149 value = rta_getattr_u8(attr); 1150 mask = mask_attr ? rta_getattr_u8(mask_attr) : UINT8_MAX; 1151 if (mask == UINT8_MAX && value_to_str) 1152 value_str = value_to_str(value); 1153 1154 fprintf(f, "\n %s ", name); 1155 1156 if (value_str) 1157 fputs(value_str, f); 1158 else 1159 fprintf(f, "%d", value); 1160 1161 if (mask != UINT8_MAX) 1162 fprintf(f, "/%d", mask); 1163 } 1164 1165 static void flower_print_arp_op(FILE *f, const char *name, 1166 struct rtattr *op_attr, 1167 struct rtattr *mask_attr) 1168 { 1169 flower_print_masked_u8(f, name, op_attr, mask_attr, 1170 flower_print_arp_op_to_name); 1171 } 1172 1173 static int flower_print_opt(struct filter_util *qu, FILE *f, 1174 struct rtattr *opt, __u32 handle) 1175 { 1176 struct rtattr *tb[TCA_FLOWER_MAX + 1]; 1177 int nl_type, nl_mask_type; 1178 __be16 eth_type = 0; 1179 __u8 ip_proto = 0xff; 1180 1181 if (!opt) 1182 return 0; 1183 1184 parse_rtattr_nested(tb, TCA_FLOWER_MAX, opt); 1185 1186 if (handle) 1187 fprintf(f, "handle 0x%x ", handle); 1188 1189 if (tb[TCA_FLOWER_CLASSID]) { 1190 SPRINT_BUF(b1); 1191 fprintf(f, "classid %s ", 1192 sprint_tc_classid(rta_getattr_u32(tb[TCA_FLOWER_CLASSID]), 1193 b1)); 1194 } 1195 1196 if (tb[TCA_FLOWER_INDEV]) { 1197 struct rtattr *attr = tb[TCA_FLOWER_INDEV]; 1198 1199 fprintf(f, "\n indev %s", rta_getattr_str(attr)); 1200 } 1201 1202 if (tb[TCA_FLOWER_KEY_VLAN_ID]) { 1203 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ID]; 1204 1205 fprintf(f, "\n vlan_id %d", rta_getattr_u16(attr)); 1206 } 1207 1208 if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) { 1209 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_PRIO]; 1210 1211 fprintf(f, "\n vlan_prio %d", rta_getattr_u8(attr)); 1212 } 1213 1214 flower_print_eth_addr(f, "dst_mac", tb[TCA_FLOWER_KEY_ETH_DST], 1215 tb[TCA_FLOWER_KEY_ETH_DST_MASK]); 1216 flower_print_eth_addr(f, "src_mac", tb[TCA_FLOWER_KEY_ETH_SRC], 1217 tb[TCA_FLOWER_KEY_ETH_SRC_MASK]); 1218 1219 flower_print_eth_type(f, ð_type, tb[TCA_FLOWER_KEY_ETH_TYPE]); 1220 flower_print_ip_proto(f, &ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]); 1221 1222 flower_print_ip_attr(f, "ip_tos", tb[TCA_FLOWER_KEY_IP_TOS], 1223 tb[TCA_FLOWER_KEY_IP_TOS_MASK]); 1224 flower_print_ip_attr(f, "ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL], 1225 tb[TCA_FLOWER_KEY_IP_TTL_MASK]); 1226 1227 flower_print_ip_addr(f, "dst_ip", eth_type, 1228 tb[TCA_FLOWER_KEY_IPV4_DST], 1229 tb[TCA_FLOWER_KEY_IPV4_DST_MASK], 1230 tb[TCA_FLOWER_KEY_IPV6_DST], 1231 tb[TCA_FLOWER_KEY_IPV6_DST_MASK]); 1232 1233 flower_print_ip_addr(f, "src_ip", eth_type, 1234 tb[TCA_FLOWER_KEY_IPV4_SRC], 1235 tb[TCA_FLOWER_KEY_IPV4_SRC_MASK], 1236 tb[TCA_FLOWER_KEY_IPV6_SRC], 1237 tb[TCA_FLOWER_KEY_IPV6_SRC_MASK]); 1238 1239 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_DST); 1240 if (nl_type >= 0) 1241 flower_print_port(f, "dst_port", tb[nl_type]); 1242 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_SRC); 1243 if (nl_type >= 0) 1244 flower_print_port(f, "src_port", tb[nl_type]); 1245 1246 flower_print_tcp_flags(f, "tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS], 1247 tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]); 1248 1249 nl_type = flower_icmp_attr_type(eth_type, ip_proto, 1250 FLOWER_ICMP_FIELD_TYPE); 1251 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto, 1252 FLOWER_ICMP_FIELD_TYPE); 1253 if (nl_type >= 0 && nl_mask_type >= 0) 1254 flower_print_masked_u8(f, "icmp_type", tb[nl_type], 1255 tb[nl_mask_type], NULL); 1256 1257 nl_type = flower_icmp_attr_type(eth_type, ip_proto, 1258 FLOWER_ICMP_FIELD_CODE); 1259 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto, 1260 FLOWER_ICMP_FIELD_CODE); 1261 if (nl_type >= 0 && nl_mask_type >= 0) 1262 flower_print_masked_u8(f, "icmp_code", tb[nl_type], 1263 tb[nl_mask_type], NULL); 1264 1265 flower_print_ip4_addr(f, "arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP], 1266 tb[TCA_FLOWER_KEY_ARP_SIP_MASK]); 1267 flower_print_ip4_addr(f, "arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP], 1268 tb[TCA_FLOWER_KEY_ARP_TIP_MASK]); 1269 flower_print_arp_op(f, "arp_op", tb[TCA_FLOWER_KEY_ARP_OP], 1270 tb[TCA_FLOWER_KEY_ARP_OP_MASK]); 1271 flower_print_eth_addr(f, "arp_sha", tb[TCA_FLOWER_KEY_ARP_SHA], 1272 tb[TCA_FLOWER_KEY_ARP_SHA_MASK]); 1273 flower_print_eth_addr(f, "arp_tha", tb[TCA_FLOWER_KEY_ARP_THA], 1274 tb[TCA_FLOWER_KEY_ARP_THA_MASK]); 1275 1276 flower_print_ip_addr(f, "enc_dst_ip", 1277 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] ? 1278 htons(ETH_P_IP) : htons(ETH_P_IPV6), 1279 tb[TCA_FLOWER_KEY_ENC_IPV4_DST], 1280 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK], 1281 tb[TCA_FLOWER_KEY_ENC_IPV6_DST], 1282 tb[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]); 1283 1284 flower_print_ip_addr(f, "enc_src_ip", 1285 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] ? 1286 htons(ETH_P_IP) : htons(ETH_P_IPV6), 1287 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC], 1288 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK], 1289 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC], 1290 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]); 1291 1292 flower_print_key_id(f, "enc_key_id", 1293 tb[TCA_FLOWER_KEY_ENC_KEY_ID]); 1294 1295 flower_print_port(f, "enc_dst_port", 1296 tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]); 1297 1298 flower_print_matching_flags(f, "ip_flags", 1299 FLOWER_IP_FLAGS, 1300 tb[TCA_FLOWER_KEY_FLAGS], 1301 tb[TCA_FLOWER_KEY_FLAGS_MASK]); 1302 1303 if (tb[TCA_FLOWER_FLAGS]) { 1304 __u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]); 1305 1306 if (flags & TCA_CLS_FLAGS_SKIP_HW) 1307 fprintf(f, "\n skip_hw"); 1308 if (flags & TCA_CLS_FLAGS_SKIP_SW) 1309 fprintf(f, "\n skip_sw"); 1310 1311 if (flags & TCA_CLS_FLAGS_IN_HW) 1312 fprintf(f, "\n in_hw"); 1313 else if (flags & TCA_CLS_FLAGS_NOT_IN_HW) 1314 fprintf(f, "\n not_in_hw"); 1315 } 1316 1317 if (tb[TCA_FLOWER_ACT]) 1318 tc_print_action(f, tb[TCA_FLOWER_ACT], 0); 1319 1320 return 0; 1321 } 1322 1323 struct filter_util flower_filter_util = { 1324 .id = "flower", 1325 .parse_fopt = flower_parse_opt, 1326 .print_fopt = flower_print_opt, 1327 }; 1328