]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/f_flower.c
Merge branch 'master' into net-next
[mirror_iproute2.git] / tc / f_flower.c
CommitLineData
30eb304e
JP
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@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>
f888f4e2 18#include <linux/if_arp.h>
30eb304e
JP
19#include <linux/if_ether.h>
20#include <linux/ip.h>
745d9172 21#include <linux/tc_act/tc_vlan.h>
30eb304e
JP
22
23#include "utils.h"
24#include "tc_util.h"
25#include "rt_names.h"
26
08f66c80
PB
27enum flower_matching_flags {
28 FLOWER_IP_FLAGS,
29};
30
6910d656
SH
31enum flower_endpoint {
32 FLOWER_ENDPOINT_SRC,
33 FLOWER_ENDPOINT_DST
34};
35
eb3b5696
SH
36enum flower_icmp_field {
37 FLOWER_ICMP_FIELD_TYPE,
38 FLOWER_ICMP_FIELD_CODE
39};
40
30eb304e
JP
41static void explain(void)
42{
512caeb2
SH
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"
c2078f8d
SH
53 " dst_mac MASKED-LLADDR |\n"
54 " src_mac MASKED-LLADDR |\n"
eb3b5696 55 " ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n"
6ea2c2b1
OG
56 " ip_tos MASKED-IP_TOS |\n"
57 " ip_ttl MASKED-IP_TTL |\n"
b2a1f740
SH
58 " dst_ip PREFIX |\n"
59 " src_ip PREFIX |\n"
512caeb2 60 " dst_port PORT-NUMBER |\n"
bb9b63b1 61 " src_port PORT-NUMBER |\n"
0c30d14d 62 " tcp_flags MASKED-TCP_FLAGS |\n"
6374961a
SH
63 " type MASKED-ICMP-TYPE |\n"
64 " code MASKED-ICMP-CODE |\n"
c7ec052b
SH
65 " arp_tip IPV4-PREFIX |\n"
66 " arp_sip IPV4-PREFIX |\n"
f888f4e2
SH
67 " arp_op [ request | reply | OP ] |\n"
68 " arp_tha MASKED-LLADDR |\n"
69 " arp_sha MASKED-LLADDR |\n"
10da5528
SH
70 " enc_dst_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
71 " enc_src_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
bf73c650 72 " enc_key_id [ KEY-ID ] |\n"
08f66c80 73 " ip_flags IP-FLAGS | \n"
a5ae170e 74 " enc_dst_port [ port_number ] }\n"
512caeb2 75 " FILTERID := X:Y:Z\n"
c2078f8d 76 " MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n"
512caeb2
SH
77 " ACTION-SPEC := ... look at individual actions\n"
78 "\n"
328374dc 79 "NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n"
512caeb2
SH
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");
30eb304e
JP
82}
83
84static int flower_parse_eth_addr(char *str, int addr_type, int mask_type,
85 struct nlmsghdr *n)
86{
c2078f8d
SH
87 int ret, err = -1;
88 char addr[ETH_ALEN], *slash;
89
90 slash = strchr(str, '/');
91 if (slash)
92 *slash = '\0';
30eb304e
JP
93
94 ret = ll_addr_a2n(addr, sizeof(addr), str);
95 if (ret < 0)
c2078f8d 96 goto err;
30eb304e 97 addattr_l(n, MAX_MSG, addr_type, addr, sizeof(addr));
c2078f8d
SH
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 }
30eb304e 118 addattr_l(n, MAX_MSG, mask_type, addr, sizeof(addr));
c2078f8d
SH
119
120 err = 0;
121err:
122 if (slash)
123 *slash = '/';
124 return err;
30eb304e
JP
125}
126
745d9172 127static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type,
512caeb2
SH
128 __be16 *p_vlan_eth_type,
129 struct nlmsghdr *n)
745d9172
HHZ
130{
131 __be16 vlan_eth_type;
132
133 if (eth_type != htons(ETH_P_8021Q)) {
512caeb2
SH
134 fprintf(stderr,
135 "Can't set \"vlan_ethtype\" if ethertype isn't 802.1Q\n");
745d9172
HHZ
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
08f66c80
PB
146struct flag_to_string {
147 int flag;
148 enum flower_matching_flags type;
149 char *string;
150};
22a8f019 151
08f66c80
PB
152static struct flag_to_string flags_str[] = {
153 { TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOWER_IP_FLAGS, "frag" },
154};
22a8f019 155
08f66c80
PB
156static 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;
22a8f019 164
08f66c80
PB
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)
22a8f019 191 return -1;
08f66c80
PB
192
193 token = strtok(NULL, "/");
22a8f019
PB
194 }
195
22a8f019
PB
196 return 0;
197}
198
30eb304e
JP
199static 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
eb3b5696
SH
205 if (eth_type != htons(ETH_P_IP) && eth_type != htons(ETH_P_IPV6))
206 goto err;
207
30eb304e
JP
208 if (matches(str, "tcp") == 0) {
209 ip_proto = IPPROTO_TCP;
210 } else if (matches(str, "udp") == 0) {
211 ip_proto = IPPROTO_UDP;
a1fb0d48
SH
212 } else if (matches(str, "sctp") == 0) {
213 ip_proto = IPPROTO_SCTP;
eb3b5696
SH
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;
30eb304e
JP
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;
eb3b5696
SH
230
231err:
232 fprintf(stderr, "Illegal \"eth_type\" for ip proto\n");
233 return -1;
30eb304e
JP
234}
235
f888f4e2
SH
236static 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)
30eb304e
JP
240{
241 int ret;
242 inet_prefix addr;
30eb304e
JP
243 int bits;
244 int i;
245
30eb304e
JP
246 ret = get_prefix(&addr, str, family);
247 if (ret)
248 return -1;
249
bb9b63b1
AV
250 if (family && (addr.family != family)) {
251 fprintf(stderr, "Illegal \"eth_type\" for ip address\n");
30eb304e 252 return -1;
bb9b63b1 253 }
30eb304e
JP
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
f888f4e2
SH
278static 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
164a9ff4
RD
295 return __flower_parse_ip_addr(str, family, addr4_type, mask4_type,
296 addr6_type, mask6_type, n);
f888f4e2
SH
297}
298
299static 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
304static 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
180136e5
SH
315static 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)
f888f4e2
SH
320{
321 char *slash;
322 int ret, err = -1;
180136e5 323 __u8 value, mask;
f888f4e2
SH
324
325 slash = strchr(str, '/');
326 if (slash)
327 *slash = '\0';
328
180136e5
SH
329 ret = value_from_name ? value_from_name(str, &value) : -1;
330 if (ret < 0) {
f888f4e2
SH
331 ret = get_u8(&value, str, 10);
332 if (ret)
333 goto err;
f888f4e2
SH
334 }
335
180136e5
SH
336 if (value_validate && !value_validate(value))
337 goto err;
338
f888f4e2
SH
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
180136e5 348 addattr8(n, MAX_MSG, value_type, value);
f888f4e2
SH
349 addattr8(n, MAX_MSG, mask_type, mask);
350
351 err = 0;
352err:
353 if (slash)
354 *slash = '/';
355 return err;
356}
357
9d36e54f
SH
358static 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
180136e5
SH
370static 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
382static bool flow_arp_op_validate(__u8 op)
383{
384 return !op || op == ARPOP_REQUEST || op == ARPOP_REPLY;
385}
386
387static 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
eb3b5696
SH
398static 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
6374961a
SH
413static 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
eb3b5696
SH
428static int flower_parse_icmp(char *str, __u16 eth_type, __u8 ip_proto,
429 enum flower_icmp_field field, struct nlmsghdr *n)
430{
6374961a 431 int value_type, mask_type;
eb3b5696 432
6374961a
SH
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)
eb3b5696
SH
436 return -1;
437
6374961a 438 return flower_parse_u8(str, value_type, mask_type, NULL, NULL, n);
eb3b5696
SH
439}
440
6910d656 441static int flower_port_attr_type(__u8 ip_proto, enum flower_endpoint endpoint)
30eb304e 442{
6bd5b80c 443 if (ip_proto == IPPROTO_TCP)
6910d656
SH
444 return endpoint == FLOWER_ENDPOINT_SRC ?
445 TCA_FLOWER_KEY_TCP_SRC :
a1fb0d48 446 TCA_FLOWER_KEY_TCP_DST;
6bd5b80c 447 else if (ip_proto == IPPROTO_UDP)
6910d656
SH
448 return endpoint == FLOWER_ENDPOINT_SRC ?
449 TCA_FLOWER_KEY_UDP_SRC :
a1fb0d48 450 TCA_FLOWER_KEY_UDP_DST;
6bd5b80c 451 else if (ip_proto == IPPROTO_SCTP)
6910d656
SH
452 return endpoint == FLOWER_ENDPOINT_SRC ?
453 TCA_FLOWER_KEY_SCTP_SRC :
a1fb0d48 454 TCA_FLOWER_KEY_SCTP_DST;
6bd5b80c 455 else
30eb304e 456 return -1;
a1fb0d48
SH
457}
458
6910d656
SH
459static int flower_parse_port(char *str, __u8 ip_proto,
460 enum flower_endpoint endpoint,
a1fb0d48
SH
461 struct nlmsghdr *n)
462{
463 int ret;
464 int type;
465 __be16 port;
466
6910d656 467 type = flower_port_attr_type(ip_proto, endpoint);
a1fb0d48
SH
468 if (type < 0)
469 return -1;
30eb304e 470
9f7401fa 471 ret = get_be16(&port, str, 10);
30eb304e
JP
472 if (ret)
473 return -1;
474
9f7401fa 475 addattr16(n, MAX_MSG, type, port);
30eb304e
JP
476
477 return 0;
478}
479
0c30d14d
JP
480#define TCP_FLAGS_MAX_MASK 0xfff
481
482static 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;
509err:
510 if (slash)
511 *slash = '/';
512 return err;
513}
514
6ea2c2b1
OG
515static 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;
544err:
545 if (slash)
546 *slash = '/';
547 return err;
548}
549
bb9b63b1
AV
550static 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
41aa17ff
HHZ
562static 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
30eb304e
JP
576static 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;
488b41d0 582 __be16 eth_type = TC_H_MIN(t->tcm_info);
745d9172 583 __be16 vlan_ethtype = 0;
30eb304e 584 __u8 ip_proto = 0xff;
cfcabf18 585 __u32 flags = 0;
08f66c80
PB
586 __u32 mtf = 0;
587 __u32 mtf_mask = 0;
30eb304e 588
30eb304e
JP
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
488b41d0
JHS
600 if (argc == 0) {
601 /*at minimal we will match all ethertype packets */
602 goto parse_done;
603 }
604
30eb304e
JP
605 while (argc > 0) {
606 if (matches(*argv, "classid") == 0 ||
607 matches(*argv, "flowid") == 0) {
32a121cb 608 unsigned int handle;
30eb304e
JP
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);
08f66c80 617 } else if (matches(*argv, "ip_flags") == 0) {
22a8f019
PB
618 NEXT_ARG();
619 ret = flower_parse_matching_flags(*argv,
08f66c80
PB
620 FLOWER_IP_FLAGS,
621 &mtf,
622 &mtf_mask);
22a8f019 623 if (ret < 0) {
08f66c80 624 fprintf(stderr, "Illegal \"ip_flags\"\n");
22a8f019
PB
625 return -1;
626 }
cfcabf18
AV
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;
30eb304e 631 } else if (matches(*argv, "indev") == 0) {
d17b136f 632 char ifname[IFNAMSIZ] = {};
30eb304e
JP
633
634 NEXT_ARG();
30eb304e
JP
635 strncpy(ifname, *argv, sizeof(ifname) - 1);
636 addattrstrz(n, MAX_MSG, TCA_FLOWER_INDEV, ifname);
745d9172
HHZ
637 } else if (matches(*argv, "vlan_id") == 0) {
638 __u16 vid;
639
640 NEXT_ARG();
641 if (eth_type != htons(ETH_P_8021Q)) {
512caeb2
SH
642 fprintf(stderr,
643 "Can't set \"vlan_id\" if ethertype isn't 802.1Q\n");
745d9172
HHZ
644 return -1;
645 }
646 ret = get_u16(&vid, *argv, 10);
647 if (ret < 0 || vid & ~0xfff) {
648 fprintf(stderr, "Illegal \"vlan_id\"\n");
649 return -1;
650 }
651 addattr16(n, MAX_MSG, TCA_FLOWER_KEY_VLAN_ID, vid);
652 } else if (matches(*argv, "vlan_prio") == 0) {
653 __u8 vlan_prio;
654
655 NEXT_ARG();
656 if (eth_type != htons(ETH_P_8021Q)) {
512caeb2
SH
657 fprintf(stderr,
658 "Can't set \"vlan_prio\" if ethertype isn't 802.1Q\n");
745d9172
HHZ
659 return -1;
660 }
661 ret = get_u8(&vlan_prio, *argv, 10);
662 if (ret < 0 || vlan_prio & ~0x7) {
663 fprintf(stderr, "Illegal \"vlan_prio\"\n");
664 return -1;
665 }
512caeb2
SH
666 addattr8(n, MAX_MSG,
667 TCA_FLOWER_KEY_VLAN_PRIO, vlan_prio);
745d9172
HHZ
668 } else if (matches(*argv, "vlan_ethtype") == 0) {
669 NEXT_ARG();
670 ret = flower_parse_vlan_eth_type(*argv, eth_type,
512caeb2
SH
671 TCA_FLOWER_KEY_VLAN_ETH_TYPE,
672 &vlan_ethtype, n);
745d9172
HHZ
673 if (ret < 0)
674 return -1;
30eb304e
JP
675 } else if (matches(*argv, "dst_mac") == 0) {
676 NEXT_ARG();
677 ret = flower_parse_eth_addr(*argv,
678 TCA_FLOWER_KEY_ETH_DST,
679 TCA_FLOWER_KEY_ETH_DST_MASK,
680 n);
681 if (ret < 0) {
682 fprintf(stderr, "Illegal \"dst_mac\"\n");
683 return -1;
684 }
685 } else if (matches(*argv, "src_mac") == 0) {
686 NEXT_ARG();
687 ret = flower_parse_eth_addr(*argv,
688 TCA_FLOWER_KEY_ETH_SRC,
689 TCA_FLOWER_KEY_ETH_SRC_MASK,
690 n);
691 if (ret < 0) {
692 fprintf(stderr, "Illegal \"src_mac\"\n");
693 return -1;
694 }
30eb304e
JP
695 } else if (matches(*argv, "ip_proto") == 0) {
696 NEXT_ARG();
745d9172
HHZ
697 ret = flower_parse_ip_proto(*argv, vlan_ethtype ?
698 vlan_ethtype : eth_type,
30eb304e
JP
699 TCA_FLOWER_KEY_IP_PROTO,
700 &ip_proto, n);
701 if (ret < 0) {
702 fprintf(stderr, "Illegal \"ip_proto\"\n");
703 return -1;
704 }
6ea2c2b1
OG
705 } else if (matches(*argv, "ip_tos") == 0) {
706 NEXT_ARG();
707 ret = flower_parse_ip_tos_ttl(*argv,
708 TCA_FLOWER_KEY_IP_TOS,
709 TCA_FLOWER_KEY_IP_TOS_MASK,
710 n);
711 if (ret < 0) {
712 fprintf(stderr, "Illegal \"ip_tos\"\n");
713 return -1;
714 }
715 } else if (matches(*argv, "ip_ttl") == 0) {
716 NEXT_ARG();
717 ret = flower_parse_ip_tos_ttl(*argv,
718 TCA_FLOWER_KEY_IP_TTL,
719 TCA_FLOWER_KEY_IP_TTL_MASK,
720 n);
721 if (ret < 0) {
722 fprintf(stderr, "Illegal \"ip_ttl\"\n");
723 return -1;
724 }
30eb304e
JP
725 } else if (matches(*argv, "dst_ip") == 0) {
726 NEXT_ARG();
745d9172
HHZ
727 ret = flower_parse_ip_addr(*argv, vlan_ethtype ?
728 vlan_ethtype : eth_type,
30eb304e
JP
729 TCA_FLOWER_KEY_IPV4_DST,
730 TCA_FLOWER_KEY_IPV4_DST_MASK,
731 TCA_FLOWER_KEY_IPV6_DST,
732 TCA_FLOWER_KEY_IPV6_DST_MASK,
733 n);
734 if (ret < 0) {
735 fprintf(stderr, "Illegal \"dst_ip\"\n");
736 return -1;
737 }
738 } else if (matches(*argv, "src_ip") == 0) {
739 NEXT_ARG();
745d9172
HHZ
740 ret = flower_parse_ip_addr(*argv, vlan_ethtype ?
741 vlan_ethtype : eth_type,
30eb304e
JP
742 TCA_FLOWER_KEY_IPV4_SRC,
743 TCA_FLOWER_KEY_IPV4_SRC_MASK,
744 TCA_FLOWER_KEY_IPV6_SRC,
745 TCA_FLOWER_KEY_IPV6_SRC_MASK,
746 n);
747 if (ret < 0) {
748 fprintf(stderr, "Illegal \"src_ip\"\n");
749 return -1;
750 }
751 } else if (matches(*argv, "dst_port") == 0) {
752 NEXT_ARG();
6910d656
SH
753 ret = flower_parse_port(*argv, ip_proto,
754 FLOWER_ENDPOINT_DST, n);
30eb304e
JP
755 if (ret < 0) {
756 fprintf(stderr, "Illegal \"dst_port\"\n");
757 return -1;
758 }
759 } else if (matches(*argv, "src_port") == 0) {
760 NEXT_ARG();
6910d656
SH
761 ret = flower_parse_port(*argv, ip_proto,
762 FLOWER_ENDPOINT_SRC, n);
30eb304e
JP
763 if (ret < 0) {
764 fprintf(stderr, "Illegal \"src_port\"\n");
765 return -1;
766 }
0c30d14d
JP
767 } else if (matches(*argv, "tcp_flags") == 0) {
768 NEXT_ARG();
769 ret = flower_parse_tcp_flags(*argv,
770 TCA_FLOWER_KEY_TCP_FLAGS,
771 TCA_FLOWER_KEY_TCP_FLAGS_MASK,
772 n);
773 if (ret < 0) {
774 fprintf(stderr, "Illegal \"tcp_flags\"\n");
775 return -1;
776 }
eb3b5696
SH
777 } else if (matches(*argv, "type") == 0) {
778 NEXT_ARG();
779 ret = flower_parse_icmp(*argv, eth_type, ip_proto,
780 FLOWER_ICMP_FIELD_TYPE, n);
781 if (ret < 0) {
782 fprintf(stderr, "Illegal \"icmp type\"\n");
783 return -1;
784 }
785 } else if (matches(*argv, "code") == 0) {
786 NEXT_ARG();
787 ret = flower_parse_icmp(*argv, eth_type, ip_proto,
788 FLOWER_ICMP_FIELD_CODE, n);
789 if (ret < 0) {
790 fprintf(stderr, "Illegal \"icmp code\"\n");
791 return -1;
792 }
f888f4e2
SH
793 } else if (matches(*argv, "arp_tip") == 0) {
794 NEXT_ARG();
795 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ?
796 vlan_ethtype : eth_type,
797 TCA_FLOWER_KEY_ARP_TIP,
798 TCA_FLOWER_KEY_ARP_TIP_MASK,
799 n);
800 if (ret < 0) {
801 fprintf(stderr, "Illegal \"arp_tip\"\n");
802 return -1;
803 }
804 } else if (matches(*argv, "arp_sip") == 0) {
805 NEXT_ARG();
806 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ?
807 vlan_ethtype : eth_type,
808 TCA_FLOWER_KEY_ARP_SIP,
809 TCA_FLOWER_KEY_ARP_SIP_MASK,
810 n);
811 if (ret < 0) {
812 fprintf(stderr, "Illegal \"arp_sip\"\n");
813 return -1;
814 }
815 } else if (matches(*argv, "arp_op") == 0) {
816 NEXT_ARG();
817 ret = flower_parse_arp_op(*argv, vlan_ethtype ?
818 vlan_ethtype : eth_type,
819 TCA_FLOWER_KEY_ARP_OP,
820 TCA_FLOWER_KEY_ARP_OP_MASK,
821 n);
822 if (ret < 0) {
823 fprintf(stderr, "Illegal \"arp_op\"\n");
824 return -1;
825 }
826 } else if (matches(*argv, "arp_tha") == 0) {
827 NEXT_ARG();
828 ret = flower_parse_eth_addr(*argv,
829 TCA_FLOWER_KEY_ARP_THA,
830 TCA_FLOWER_KEY_ARP_THA_MASK,
831 n);
832 if (ret < 0) {
833 fprintf(stderr, "Illegal \"arp_tha\"\n");
834 return -1;
835 }
836 } else if (matches(*argv, "arp_sha") == 0) {
837 NEXT_ARG();
838 ret = flower_parse_eth_addr(*argv,
839 TCA_FLOWER_KEY_ARP_SHA,
840 TCA_FLOWER_KEY_ARP_SHA_MASK,
841 n);
842 if (ret < 0) {
843 fprintf(stderr, "Illegal \"arp_sha\"\n");
844 return -1;
845 }
bb9b63b1
AV
846 } else if (matches(*argv, "enc_dst_ip") == 0) {
847 NEXT_ARG();
848 ret = flower_parse_ip_addr(*argv, 0,
849 TCA_FLOWER_KEY_ENC_IPV4_DST,
850 TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,
851 TCA_FLOWER_KEY_ENC_IPV6_DST,
852 TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,
853 n);
854 if (ret < 0) {
855 fprintf(stderr, "Illegal \"enc_dst_ip\"\n");
856 return -1;
857 }
858 } else if (matches(*argv, "enc_src_ip") == 0) {
859 NEXT_ARG();
860 ret = flower_parse_ip_addr(*argv, 0,
861 TCA_FLOWER_KEY_ENC_IPV4_SRC,
862 TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,
863 TCA_FLOWER_KEY_ENC_IPV6_SRC,
864 TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,
865 n);
866 if (ret < 0) {
867 fprintf(stderr, "Illegal \"enc_src_ip\"\n");
868 return -1;
869 }
870 } else if (matches(*argv, "enc_key_id") == 0) {
871 NEXT_ARG();
872 ret = flower_parse_key_id(*argv,
873 TCA_FLOWER_KEY_ENC_KEY_ID, n);
874 if (ret < 0) {
875 fprintf(stderr, "Illegal \"enc_key_id\"\n");
876 return -1;
877 }
41aa17ff
HHZ
878 } else if (matches(*argv, "enc_dst_port") == 0) {
879 NEXT_ARG();
880 ret = flower_parse_enc_port(*argv,
881 TCA_FLOWER_KEY_ENC_UDP_DST_PORT, n);
882 if (ret < 0) {
883 fprintf(stderr, "Illegal \"enc_dst_port\"\n");
884 return -1;
885 }
30eb304e
JP
886 } else if (matches(*argv, "action") == 0) {
887 NEXT_ARG();
888 ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n);
889 if (ret) {
890 fprintf(stderr, "Illegal \"action\"\n");
891 return -1;
892 }
893 continue;
894 } else if (strcmp(*argv, "help") == 0) {
895 explain();
896 return -1;
897 } else {
898 fprintf(stderr, "What is \"%s\"?\n", *argv);
899 explain();
900 return -1;
901 }
902 argc--; argv++;
903 }
904
488b41d0 905parse_done:
c85609b2
RD
906 ret = addattr32(n, MAX_MSG, TCA_FLOWER_FLAGS, flags);
907 if (ret)
908 return ret;
cfcabf18 909
08f66c80
PB
910 if (mtf_mask) {
911 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS, htonl(mtf));
912 if (ret)
913 return ret;
914
915 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS_MASK, htonl(mtf_mask));
916 if (ret)
917 return ret;
918 }
919
4f7d406f
BL
920 if (eth_type != htons(ETH_P_ALL)) {
921 ret = addattr16(n, MAX_MSG, TCA_FLOWER_KEY_ETH_TYPE, eth_type);
922 if (ret)
923 return ret;
924 }
488b41d0 925
32a121cb 926 tail->rta_len = (((void *)n)+n->nlmsg_len) - (void *)tail;
30eb304e
JP
927
928 return 0;
929}
930
931static int __mask_bits(char *addr, size_t len)
932{
933 int bits = 0;
934 bool hole = false;
935 int i;
936 int j;
937
938 for (i = 0; i < len; i++, addr++) {
939 for (j = 7; j >= 0; j--) {
940 if (((*addr) >> j) & 0x1) {
941 if (hole)
942 return -1;
943 bits++;
944 } else if (bits) {
945 hole = true;
946 } else{
947 return -1;
948 }
949 }
950 }
951 return bits;
952}
953
954static void flower_print_eth_addr(FILE *f, char *name,
955 struct rtattr *addr_attr,
956 struct rtattr *mask_attr)
957{
958 SPRINT_BUF(b1);
959 int bits;
960
961 if (!addr_attr || RTA_PAYLOAD(addr_attr) != ETH_ALEN)
962 return;
963 fprintf(f, "\n %s %s", name, ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN,
964 0, b1, sizeof(b1)));
965 if (!mask_attr || RTA_PAYLOAD(mask_attr) != ETH_ALEN)
966 return;
967 bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN);
968 if (bits < 0)
969 fprintf(f, "/%s", ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN,
970 0, b1, sizeof(b1)));
971 else if (bits < ETH_ALEN * 8)
972 fprintf(f, "/%d", bits);
973}
974
975static void flower_print_eth_type(FILE *f, __be16 *p_eth_type,
976 struct rtattr *eth_type_attr)
977{
978 __be16 eth_type;
979
980 if (!eth_type_attr)
981 return;
982
983 eth_type = rta_getattr_u16(eth_type_attr);
984 fprintf(f, "\n eth_type ");
985 if (eth_type == htons(ETH_P_IP))
986 fprintf(f, "ipv4");
987 else if (eth_type == htons(ETH_P_IPV6))
988 fprintf(f, "ipv6");
f888f4e2
SH
989 else if (eth_type == htons(ETH_P_ARP))
990 fprintf(f, "arp");
991 else if (eth_type == htons(ETH_P_RARP))
992 fprintf(f, "rarp");
30eb304e
JP
993 else
994 fprintf(f, "%04x", ntohs(eth_type));
995 *p_eth_type = eth_type;
996}
997
998static void flower_print_ip_proto(FILE *f, __u8 *p_ip_proto,
999 struct rtattr *ip_proto_attr)
1000{
1001 __u8 ip_proto;
1002
1003 if (!ip_proto_attr)
1004 return;
1005
1006 ip_proto = rta_getattr_u8(ip_proto_attr);
1007 fprintf(f, "\n ip_proto ");
1008 if (ip_proto == IPPROTO_TCP)
1009 fprintf(f, "tcp");
1010 else if (ip_proto == IPPROTO_UDP)
1011 fprintf(f, "udp");
a1fb0d48
SH
1012 else if (ip_proto == IPPROTO_SCTP)
1013 fprintf(f, "sctp");
eb3b5696
SH
1014 else if (ip_proto == IPPROTO_ICMP)
1015 fprintf(f, "icmp");
1016 else if (ip_proto == IPPROTO_ICMPV6)
1017 fprintf(f, "icmpv6");
30eb304e
JP
1018 else
1019 fprintf(f, "%02x", ip_proto);
1020 *p_ip_proto = ip_proto;
1021}
1022
6ea2c2b1
OG
1023static void flower_print_ip_attr(FILE *f, char *name,
1024 struct rtattr *key_attr,
1025 struct rtattr *mask_attr)
1026{
1027 if (!key_attr)
1028 return;
1029
1030 fprintf(f, "\n %s %x", name, rta_getattr_u8(key_attr));
1031 if (!mask_attr)
1032 return;
1033 fprintf(f, "/%x", rta_getattr_u8(mask_attr));
1034}
1035
22a8f019 1036static void flower_print_matching_flags(FILE *f, char *name,
08f66c80 1037 enum flower_matching_flags type,
22a8f019
PB
1038 struct rtattr *attr,
1039 struct rtattr *mask_attr)
1040{
08f66c80
PB
1041 int i;
1042 int count = 0;
1043 __u32 mtf;
1044 __u32 mtf_mask;
1045
22a8f019
PB
1046 if (!mask_attr || RTA_PAYLOAD(mask_attr) != 4)
1047 return;
1048
08f66c80
PB
1049 mtf = ntohl(rta_getattr_u32(attr));
1050 mtf_mask = ntohl(rta_getattr_u32(mask_attr));
1051
1052 for (i = 0; i < ARRAY_SIZE(flags_str); i++) {
1053 if (type != flags_str[i].type)
1054 continue;
1055 if (mtf_mask & flags_str[i].flag) {
1056 if (++count == 1)
1057 fprintf(f, "\n %s ", name);
1058 else
1059 fprintf(f, "/");
1060
1061 if (mtf & flags_str[i].flag)
1062 fprintf(f, "%s", flags_str[i].string);
1063 else
1064 fprintf(f, "no%s", flags_str[i].string);
1065 }
1066 }
22a8f019
PB
1067}
1068
30eb304e
JP
1069static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type,
1070 struct rtattr *addr4_attr,
1071 struct rtattr *mask4_attr,
1072 struct rtattr *addr6_attr,
1073 struct rtattr *mask6_attr)
1074{
30eb304e
JP
1075 struct rtattr *addr_attr;
1076 struct rtattr *mask_attr;
1077 int family;
1078 size_t len;
1079 int bits;
1080
1081 if (eth_type == htons(ETH_P_IP)) {
1082 family = AF_INET;
1083 addr_attr = addr4_attr;
1084 mask_attr = mask4_attr;
1085 len = 4;
1086 } else if (eth_type == htons(ETH_P_IPV6)) {
1087 family = AF_INET6;
1088 addr_attr = addr6_attr;
1089 mask_attr = mask6_attr;
1090 len = 16;
1091 } else {
1092 return;
1093 }
1094 if (!addr_attr || RTA_PAYLOAD(addr_attr) != len)
1095 return;
7faf1588 1096 fprintf(f, "\n %s %s", name, rt_addr_n2a_rta(family, addr_attr));
30eb304e
JP
1097 if (!mask_attr || RTA_PAYLOAD(mask_attr) != len)
1098 return;
1099 bits = __mask_bits(RTA_DATA(mask_attr), len);
1100 if (bits < 0)
7faf1588 1101 fprintf(f, "/%s", rt_addr_n2a_rta(family, mask_attr));
30eb304e
JP
1102 else if (bits < len * 8)
1103 fprintf(f, "/%d", bits);
1104}
f888f4e2
SH
1105static void flower_print_ip4_addr(FILE *f, char *name,
1106 struct rtattr *addr_attr,
1107 struct rtattr *mask_attr)
1108{
1109 return flower_print_ip_addr(f, name, htons(ETH_P_IP),
1110 addr_attr, mask_attr, 0, 0);
1111}
30eb304e 1112
a1fb0d48 1113static void flower_print_port(FILE *f, char *name, struct rtattr *attr)
30eb304e 1114{
6bd5b80c
SH
1115 if (attr)
1116 fprintf(f, "\n %s %d", name, rta_getattr_be16(attr));
30eb304e
JP
1117}
1118
0c30d14d
JP
1119static void flower_print_tcp_flags(FILE *f, char *name,
1120 struct rtattr *flags_attr,
1121 struct rtattr *mask_attr)
1122{
1123 if (!flags_attr)
1124 return;
1125 fprintf(f, "\n %s %x", name, rta_getattr_be16(flags_attr));
1126 if (!mask_attr)
1127 return;
1128 fprintf(f, "/%x", rta_getattr_be16(mask_attr));
1129}
1130
1131
bb9b63b1
AV
1132static void flower_print_key_id(FILE *f, const char *name,
1133 struct rtattr *attr)
1134{
1135 if (attr)
1136 fprintf(f, "\n %s %d", name, rta_getattr_be32(attr));
1137}
1138
9d36e54f
SH
1139static void flower_print_masked_u8(FILE *f, const char *name,
1140 struct rtattr *attr,
1141 struct rtattr *mask_attr,
1142 const char *(*value_to_str)(__u8 value))
f888f4e2 1143{
9d36e54f
SH
1144 const char *value_str = NULL;
1145 __u8 value, mask;
f888f4e2 1146
9d36e54f 1147 if (!attr)
f888f4e2
SH
1148 return;
1149
9d36e54f 1150 value = rta_getattr_u8(attr);
f888f4e2 1151 mask = mask_attr ? rta_getattr_u8(mask_attr) : UINT8_MAX;
9d36e54f
SH
1152 if (mask == UINT8_MAX && value_to_str)
1153 value_str = value_to_str(value);
f888f4e2
SH
1154
1155 fprintf(f, "\n %s ", name);
1156
9d36e54f
SH
1157 if (value_str)
1158 fputs(value_str, f);
f888f4e2 1159 else
9d36e54f 1160 fprintf(f, "%d", value);
f888f4e2
SH
1161
1162 if (mask != UINT8_MAX)
1163 fprintf(f, "/%d", mask);
1164}
1165
9d36e54f
SH
1166static void flower_print_arp_op(FILE *f, const char *name,
1167 struct rtattr *op_attr,
1168 struct rtattr *mask_attr)
1169{
1170 flower_print_masked_u8(f, name, op_attr, mask_attr,
1171 flower_print_arp_op_to_name);
1172}
1173
30eb304e
JP
1174static int flower_print_opt(struct filter_util *qu, FILE *f,
1175 struct rtattr *opt, __u32 handle)
1176{
1177 struct rtattr *tb[TCA_FLOWER_MAX + 1];
6374961a 1178 int nl_type, nl_mask_type;
30eb304e
JP
1179 __be16 eth_type = 0;
1180 __u8 ip_proto = 0xff;
1181
1182 if (!opt)
1183 return 0;
1184
1185 parse_rtattr_nested(tb, TCA_FLOWER_MAX, opt);
1186
1187 if (handle)
1188 fprintf(f, "handle 0x%x ", handle);
1189
1190 if (tb[TCA_FLOWER_CLASSID]) {
1191 SPRINT_BUF(b1);
1192 fprintf(f, "classid %s ",
488b41d0
JHS
1193 sprint_tc_classid(rta_getattr_u32(tb[TCA_FLOWER_CLASSID]),
1194 b1));
30eb304e
JP
1195 }
1196
1197 if (tb[TCA_FLOWER_INDEV]) {
1198 struct rtattr *attr = tb[TCA_FLOWER_INDEV];
1199
1200 fprintf(f, "\n indev %s", rta_getattr_str(attr));
1201 }
1202
745d9172
HHZ
1203 if (tb[TCA_FLOWER_KEY_VLAN_ID]) {
1204 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ID];
1205
1206 fprintf(f, "\n vlan_id %d", rta_getattr_u16(attr));
1207 }
1208
1209 if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) {
1210 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_PRIO];
1211
1212 fprintf(f, "\n vlan_prio %d", rta_getattr_u8(attr));
1213 }
1214
30eb304e
JP
1215 flower_print_eth_addr(f, "dst_mac", tb[TCA_FLOWER_KEY_ETH_DST],
1216 tb[TCA_FLOWER_KEY_ETH_DST_MASK]);
1217 flower_print_eth_addr(f, "src_mac", tb[TCA_FLOWER_KEY_ETH_SRC],
1218 tb[TCA_FLOWER_KEY_ETH_SRC_MASK]);
1219
1220 flower_print_eth_type(f, &eth_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
1221 flower_print_ip_proto(f, &ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]);
1222
6ea2c2b1
OG
1223 flower_print_ip_attr(f, "ip_tos", tb[TCA_FLOWER_KEY_IP_TOS],
1224 tb[TCA_FLOWER_KEY_IP_TOS_MASK]);
1225 flower_print_ip_attr(f, "ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL],
1226 tb[TCA_FLOWER_KEY_IP_TTL_MASK]);
1227
30eb304e
JP
1228 flower_print_ip_addr(f, "dst_ip", eth_type,
1229 tb[TCA_FLOWER_KEY_IPV4_DST],
1230 tb[TCA_FLOWER_KEY_IPV4_DST_MASK],
1231 tb[TCA_FLOWER_KEY_IPV6_DST],
1232 tb[TCA_FLOWER_KEY_IPV6_DST_MASK]);
1233
1234 flower_print_ip_addr(f, "src_ip", eth_type,
1235 tb[TCA_FLOWER_KEY_IPV4_SRC],
1236 tb[TCA_FLOWER_KEY_IPV4_SRC_MASK],
1237 tb[TCA_FLOWER_KEY_IPV6_SRC],
1238 tb[TCA_FLOWER_KEY_IPV6_SRC_MASK]);
1239
b2141de1 1240 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_DST);
6bd5b80c
SH
1241 if (nl_type >= 0)
1242 flower_print_port(f, "dst_port", tb[nl_type]);
b2141de1 1243 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_SRC);
6bd5b80c
SH
1244 if (nl_type >= 0)
1245 flower_print_port(f, "src_port", tb[nl_type]);
30eb304e 1246
0c30d14d
JP
1247 flower_print_tcp_flags(f, "tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS],
1248 tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]);
1249
81f6e5a7
SH
1250 nl_type = flower_icmp_attr_type(eth_type, ip_proto,
1251 FLOWER_ICMP_FIELD_TYPE);
6374961a
SH
1252 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
1253 FLOWER_ICMP_FIELD_TYPE);
1254 if (nl_type >= 0 && nl_mask_type >= 0)
1255 flower_print_masked_u8(f, "icmp_type", tb[nl_type],
1256 tb[nl_mask_type], NULL);
1257
81f6e5a7
SH
1258 nl_type = flower_icmp_attr_type(eth_type, ip_proto,
1259 FLOWER_ICMP_FIELD_CODE);
6374961a
SH
1260 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
1261 FLOWER_ICMP_FIELD_CODE);
1262 if (nl_type >= 0 && nl_mask_type >= 0)
1263 flower_print_masked_u8(f, "icmp_code", tb[nl_type],
1264 tb[nl_mask_type], NULL);
eb3b5696 1265
f888f4e2
SH
1266 flower_print_ip4_addr(f, "arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP],
1267 tb[TCA_FLOWER_KEY_ARP_SIP_MASK]);
1268 flower_print_ip4_addr(f, "arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP],
1269 tb[TCA_FLOWER_KEY_ARP_TIP_MASK]);
1270 flower_print_arp_op(f, "arp_op", tb[TCA_FLOWER_KEY_ARP_OP],
1271 tb[TCA_FLOWER_KEY_ARP_OP_MASK]);
1272 flower_print_eth_addr(f, "arp_sha", tb[TCA_FLOWER_KEY_ARP_SHA],
1273 tb[TCA_FLOWER_KEY_ARP_SHA_MASK]);
1274 flower_print_eth_addr(f, "arp_tha", tb[TCA_FLOWER_KEY_ARP_THA],
1275 tb[TCA_FLOWER_KEY_ARP_THA_MASK]);
1276
bb9b63b1
AV
1277 flower_print_ip_addr(f, "enc_dst_ip",
1278 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] ?
1279 htons(ETH_P_IP) : htons(ETH_P_IPV6),
1280 tb[TCA_FLOWER_KEY_ENC_IPV4_DST],
1281 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK],
1282 tb[TCA_FLOWER_KEY_ENC_IPV6_DST],
1283 tb[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]);
1284
1285 flower_print_ip_addr(f, "enc_src_ip",
1286 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] ?
1287 htons(ETH_P_IP) : htons(ETH_P_IPV6),
1288 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC],
1289 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK],
1290 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC],
1291 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]);
1292
1293 flower_print_key_id(f, "enc_key_id",
1294 tb[TCA_FLOWER_KEY_ENC_KEY_ID]);
1295
41aa17ff
HHZ
1296 flower_print_port(f, "enc_dst_port",
1297 tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
1298
08f66c80
PB
1299 flower_print_matching_flags(f, "ip_flags",
1300 FLOWER_IP_FLAGS,
22a8f019
PB
1301 tb[TCA_FLOWER_KEY_FLAGS],
1302 tb[TCA_FLOWER_KEY_FLAGS_MASK]);
1303
512caeb2 1304 if (tb[TCA_FLOWER_FLAGS]) {
cfcabf18
AV
1305 __u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]);
1306
1307 if (flags & TCA_CLS_FLAGS_SKIP_HW)
1308 fprintf(f, "\n skip_hw");
1309 if (flags & TCA_CLS_FLAGS_SKIP_SW)
1310 fprintf(f, "\n skip_sw");
e57285b8
OG
1311
1312 if (flags & TCA_CLS_FLAGS_IN_HW)
1313 fprintf(f, "\n in_hw");
1314 else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
1315 fprintf(f, "\n not_in_hw");
cfcabf18
AV
1316 }
1317
512caeb2 1318 if (tb[TCA_FLOWER_ACT])
30eb304e 1319 tc_print_action(f, tb[TCA_FLOWER_ACT]);
30eb304e
JP
1320
1321 return 0;
1322}
1323
1324struct filter_util flower_filter_util = {
1325 .id = "flower",
1326 .parse_fopt = flower_parse_opt,
1327 .print_fopt = flower_print_opt,
1328};