]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/f_flower.c
ipneigh: update man page and help for router
[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>
30eb304e
JP
15#include <string.h>
16#include <net/if.h>
f888f4e2 17#include <linux/if_arp.h>
30eb304e
JP
18#include <linux/if_ether.h>
19#include <linux/ip.h>
745d9172 20#include <linux/tc_act/tc_vlan.h>
7638ee13 21#include <linux/mpls.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 43 fprintf(stderr,
ac6a4c22 44 "Usage: ... flower [ MATCH-LIST ] [ verbose ]\n"
512caeb2
SH
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"
1f0a5dfd
JL
53 " cvlan_id VID |\n"
54 " cvlan_prio PRIORITY |\n"
55 " cvlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
c2078f8d
SH
56 " dst_mac MASKED-LLADDR |\n"
57 " src_mac MASKED-LLADDR |\n"
eb3b5696 58 " ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n"
6ea2c2b1
OG
59 " ip_tos MASKED-IP_TOS |\n"
60 " ip_ttl MASKED-IP_TTL |\n"
7638ee13
BL
61 " mpls_label LABEL |\n"
62 " mpls_tc TC |\n"
63 " mpls_bos BOS |\n"
64 " mpls_ttl TTL |\n"
b2a1f740
SH
65 " dst_ip PREFIX |\n"
66 " src_ip PREFIX |\n"
512caeb2 67 " dst_port PORT-NUMBER |\n"
bb9b63b1 68 " src_port PORT-NUMBER |\n"
0c30d14d 69 " tcp_flags MASKED-TCP_FLAGS |\n"
6374961a
SH
70 " type MASKED-ICMP-TYPE |\n"
71 " code MASKED-ICMP-CODE |\n"
c7ec052b
SH
72 " arp_tip IPV4-PREFIX |\n"
73 " arp_sip IPV4-PREFIX |\n"
f888f4e2
SH
74 " arp_op [ request | reply | OP ] |\n"
75 " arp_tha MASKED-LLADDR |\n"
76 " arp_sha MASKED-LLADDR |\n"
10da5528
SH
77 " enc_dst_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
78 " enc_src_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
bf73c650 79 " enc_key_id [ KEY-ID ] |\n"
761ec9e2
OG
80 " enc_tos MASKED-IP_TOS |\n"
81 " enc_ttl MASKED-IP_TTL |\n"
08f66c80 82 " ip_flags IP-FLAGS | \n"
a5ae170e 83 " enc_dst_port [ port_number ] }\n"
512caeb2 84 " FILTERID := X:Y:Z\n"
c2078f8d 85 " MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n"
512caeb2
SH
86 " ACTION-SPEC := ... look at individual actions\n"
87 "\n"
328374dc 88 "NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n"
512caeb2
SH
89 "NOTE: There can be only used one mask per one prio. If user needs\n"
90 " to specify different mask, he has to use different prio.\n");
30eb304e
JP
91}
92
93static int flower_parse_eth_addr(char *str, int addr_type, int mask_type,
94 struct nlmsghdr *n)
95{
c2078f8d
SH
96 int ret, err = -1;
97 char addr[ETH_ALEN], *slash;
98
99 slash = strchr(str, '/');
100 if (slash)
101 *slash = '\0';
30eb304e
JP
102
103 ret = ll_addr_a2n(addr, sizeof(addr), str);
104 if (ret < 0)
c2078f8d 105 goto err;
30eb304e 106 addattr_l(n, MAX_MSG, addr_type, addr, sizeof(addr));
c2078f8d
SH
107
108 if (slash) {
109 unsigned bits;
110
111 if (!get_unsigned(&bits, slash + 1, 10)) {
112 uint64_t mask;
113
114 /* Extra 16 bit shift to push mac address into
115 * high bits of uint64_t
116 */
117 mask = htonll(0xffffffffffffULL << (16 + 48 - bits));
118 memcpy(addr, &mask, ETH_ALEN);
119 } else {
120 ret = ll_addr_a2n(addr, sizeof(addr), slash + 1);
121 if (ret < 0)
122 goto err;
123 }
124 } else {
125 memset(addr, 0xff, ETH_ALEN);
126 }
30eb304e 127 addattr_l(n, MAX_MSG, mask_type, addr, sizeof(addr));
c2078f8d
SH
128
129 err = 0;
130err:
131 if (slash)
132 *slash = '/';
133 return err;
30eb304e
JP
134}
135
1f0a5dfd
JL
136static bool eth_type_vlan(__be16 ethertype)
137{
138 return ethertype == htons(ETH_P_8021Q) ||
139 ethertype == htons(ETH_P_8021AD);
140}
141
745d9172 142static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type,
512caeb2
SH
143 __be16 *p_vlan_eth_type,
144 struct nlmsghdr *n)
745d9172
HHZ
145{
146 __be16 vlan_eth_type;
147
1f0a5dfd
JL
148 if (!eth_type_vlan(eth_type)) {
149 fprintf(stderr, "Can't set \"%s\" if ethertype isn't 802.1Q or 802.1AD\n",
150 type == TCA_FLOWER_KEY_VLAN_ETH_TYPE ? "vlan_ethtype" : "cvlan_ethtype");
745d9172
HHZ
151 return -1;
152 }
153
154 if (ll_proto_a2n(&vlan_eth_type, str))
155 invarg("invalid vlan_ethtype", str);
156 addattr16(n, MAX_MSG, type, vlan_eth_type);
157 *p_vlan_eth_type = vlan_eth_type;
158 return 0;
159}
160
08f66c80
PB
161struct flag_to_string {
162 int flag;
163 enum flower_matching_flags type;
164 char *string;
165};
22a8f019 166
08f66c80
PB
167static struct flag_to_string flags_str[] = {
168 { TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOWER_IP_FLAGS, "frag" },
fb4e6abf 169 { TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST, FLOWER_IP_FLAGS, "firstfrag" },
08f66c80 170};
22a8f019 171
08f66c80
PB
172static int flower_parse_matching_flags(char *str,
173 enum flower_matching_flags type,
174 __u32 *mtf, __u32 *mtf_mask)
175{
176 char *token;
177 bool no;
178 bool found;
179 int i;
22a8f019 180
08f66c80
PB
181 token = strtok(str, "/");
182
183 while (token) {
184 if (!strncmp(token, "no", 2)) {
185 no = true;
186 token += 2;
187 } else
188 no = false;
189
190 found = false;
191 for (i = 0; i < ARRAY_SIZE(flags_str); i++) {
192 if (type != flags_str[i].type)
193 continue;
194
195 if (!strcmp(token, flags_str[i].string)) {
196 if (no)
197 *mtf &= ~flags_str[i].flag;
198 else
199 *mtf |= flags_str[i].flag;
200
201 *mtf_mask |= flags_str[i].flag;
202 found = true;
203 break;
204 }
205 }
206 if (!found)
22a8f019 207 return -1;
08f66c80
PB
208
209 token = strtok(NULL, "/");
22a8f019
PB
210 }
211
22a8f019
PB
212 return 0;
213}
214
30eb304e
JP
215static int flower_parse_ip_proto(char *str, __be16 eth_type, int type,
216 __u8 *p_ip_proto, struct nlmsghdr *n)
217{
218 int ret;
219 __u8 ip_proto;
220
eb3b5696
SH
221 if (eth_type != htons(ETH_P_IP) && eth_type != htons(ETH_P_IPV6))
222 goto err;
223
30eb304e
JP
224 if (matches(str, "tcp") == 0) {
225 ip_proto = IPPROTO_TCP;
226 } else if (matches(str, "udp") == 0) {
227 ip_proto = IPPROTO_UDP;
a1fb0d48
SH
228 } else if (matches(str, "sctp") == 0) {
229 ip_proto = IPPROTO_SCTP;
eb3b5696
SH
230 } else if (matches(str, "icmp") == 0) {
231 if (eth_type != htons(ETH_P_IP))
232 goto err;
233 ip_proto = IPPROTO_ICMP;
234 } else if (matches(str, "icmpv6") == 0) {
235 if (eth_type != htons(ETH_P_IPV6))
236 goto err;
237 ip_proto = IPPROTO_ICMPV6;
30eb304e
JP
238 } else {
239 ret = get_u8(&ip_proto, str, 16);
240 if (ret)
241 return -1;
242 }
243 addattr8(n, MAX_MSG, type, ip_proto);
244 *p_ip_proto = ip_proto;
245 return 0;
eb3b5696
SH
246
247err:
248 fprintf(stderr, "Illegal \"eth_type\" for ip proto\n");
249 return -1;
30eb304e
JP
250}
251
f888f4e2
SH
252static int __flower_parse_ip_addr(char *str, int family,
253 int addr4_type, int mask4_type,
254 int addr6_type, int mask6_type,
255 struct nlmsghdr *n)
30eb304e
JP
256{
257 int ret;
258 inet_prefix addr;
30eb304e
JP
259 int bits;
260 int i;
261
30eb304e
JP
262 ret = get_prefix(&addr, str, family);
263 if (ret)
264 return -1;
265
bb9b63b1
AV
266 if (family && (addr.family != family)) {
267 fprintf(stderr, "Illegal \"eth_type\" for ip address\n");
30eb304e 268 return -1;
bb9b63b1 269 }
30eb304e
JP
270
271 addattr_l(n, MAX_MSG, addr.family == AF_INET ? addr4_type : addr6_type,
272 addr.data, addr.bytelen);
273
274 memset(addr.data, 0xff, addr.bytelen);
275 bits = addr.bitlen;
276 for (i = 0; i < addr.bytelen / 4; i++) {
277 if (!bits) {
278 addr.data[i] = 0;
279 } else if (bits / 32 >= 1) {
280 bits -= 32;
281 } else {
282 addr.data[i] <<= 32 - bits;
283 addr.data[i] = htonl(addr.data[i]);
284 bits = 0;
285 }
286 }
287
288 addattr_l(n, MAX_MSG, addr.family == AF_INET ? mask4_type : mask6_type,
289 addr.data, addr.bytelen);
290
291 return 0;
292}
293
f888f4e2
SH
294static int flower_parse_ip_addr(char *str, __be16 eth_type,
295 int addr4_type, int mask4_type,
296 int addr6_type, int mask6_type,
297 struct nlmsghdr *n)
298{
299 int family;
300
301 if (eth_type == htons(ETH_P_IP)) {
302 family = AF_INET;
303 } else if (eth_type == htons(ETH_P_IPV6)) {
304 family = AF_INET6;
305 } else if (!eth_type) {
306 family = AF_UNSPEC;
307 } else {
308 return -1;
309 }
310
164a9ff4
RD
311 return __flower_parse_ip_addr(str, family, addr4_type, mask4_type,
312 addr6_type, mask6_type, n);
f888f4e2
SH
313}
314
315static bool flower_eth_type_arp(__be16 eth_type)
316{
317 return eth_type == htons(ETH_P_ARP) || eth_type == htons(ETH_P_RARP);
318}
319
320static int flower_parse_arp_ip_addr(char *str, __be16 eth_type,
321 int addr_type, int mask_type,
322 struct nlmsghdr *n)
323{
324 if (!flower_eth_type_arp(eth_type))
325 return -1;
326
327 return __flower_parse_ip_addr(str, AF_INET, addr_type, mask_type,
328 TCA_FLOWER_UNSPEC, TCA_FLOWER_UNSPEC, n);
329}
330
180136e5
SH
331static int flower_parse_u8(char *str, int value_type, int mask_type,
332 int (*value_from_name)(const char *str,
333 __u8 *value),
334 bool (*value_validate)(__u8 value),
335 struct nlmsghdr *n)
f888f4e2
SH
336{
337 char *slash;
338 int ret, err = -1;
180136e5 339 __u8 value, mask;
f888f4e2
SH
340
341 slash = strchr(str, '/');
342 if (slash)
343 *slash = '\0';
344
180136e5
SH
345 ret = value_from_name ? value_from_name(str, &value) : -1;
346 if (ret < 0) {
f888f4e2
SH
347 ret = get_u8(&value, str, 10);
348 if (ret)
349 goto err;
f888f4e2
SH
350 }
351
180136e5
SH
352 if (value_validate && !value_validate(value))
353 goto err;
354
f888f4e2
SH
355 if (slash) {
356 ret = get_u8(&mask, slash + 1, 10);
357 if (ret)
358 goto err;
359 }
360 else {
361 mask = UINT8_MAX;
362 }
363
180136e5 364 addattr8(n, MAX_MSG, value_type, value);
f888f4e2
SH
365 addattr8(n, MAX_MSG, mask_type, mask);
366
367 err = 0;
368err:
369 if (slash)
370 *slash = '/';
371 return err;
372}
373
9d36e54f
SH
374static const char *flower_print_arp_op_to_name(__u8 op)
375{
376 switch (op) {
377 case ARPOP_REQUEST:
378 return "request";
379 case ARPOP_REPLY:
380 return "reply";
381 default:
382 return NULL;
383 }
384}
385
180136e5
SH
386static int flower_arp_op_from_name(const char *name, __u8 *op)
387{
388 if (!strcmp(name, "request"))
389 *op = ARPOP_REQUEST;
390 else if (!strcmp(name, "reply"))
391 *op = ARPOP_REPLY;
392 else
393 return -1;
394
395 return 0;
396}
397
398static bool flow_arp_op_validate(__u8 op)
399{
400 return !op || op == ARPOP_REQUEST || op == ARPOP_REPLY;
401}
402
403static int flower_parse_arp_op(char *str, __be16 eth_type,
404 int op_type, int mask_type,
405 struct nlmsghdr *n)
406{
407 if (!flower_eth_type_arp(eth_type))
408 return -1;
409
410 return flower_parse_u8(str, op_type, mask_type, flower_arp_op_from_name,
411 flow_arp_op_validate, n);
412}
413
eb3b5696
SH
414static int flower_icmp_attr_type(__be16 eth_type, __u8 ip_proto,
415 enum flower_icmp_field field)
416{
417 if (eth_type == htons(ETH_P_IP) && ip_proto == IPPROTO_ICMP)
418 return field == FLOWER_ICMP_FIELD_CODE ?
419 TCA_FLOWER_KEY_ICMPV4_CODE :
420 TCA_FLOWER_KEY_ICMPV4_TYPE;
421 else if (eth_type == htons(ETH_P_IPV6) && ip_proto == IPPROTO_ICMPV6)
422 return field == FLOWER_ICMP_FIELD_CODE ?
423 TCA_FLOWER_KEY_ICMPV6_CODE :
424 TCA_FLOWER_KEY_ICMPV6_TYPE;
425
426 return -1;
427}
428
6374961a
SH
429static int flower_icmp_attr_mask_type(__be16 eth_type, __u8 ip_proto,
430 enum flower_icmp_field field)
431{
432 if (eth_type == htons(ETH_P_IP) && ip_proto == IPPROTO_ICMP)
433 return field == FLOWER_ICMP_FIELD_CODE ?
434 TCA_FLOWER_KEY_ICMPV4_CODE_MASK :
435 TCA_FLOWER_KEY_ICMPV4_TYPE_MASK;
436 else if (eth_type == htons(ETH_P_IPV6) && ip_proto == IPPROTO_ICMPV6)
437 return field == FLOWER_ICMP_FIELD_CODE ?
438 TCA_FLOWER_KEY_ICMPV6_CODE_MASK :
439 TCA_FLOWER_KEY_ICMPV6_TYPE_MASK;
440
441 return -1;
442}
443
eb3b5696
SH
444static int flower_parse_icmp(char *str, __u16 eth_type, __u8 ip_proto,
445 enum flower_icmp_field field, struct nlmsghdr *n)
446{
6374961a 447 int value_type, mask_type;
eb3b5696 448
6374961a
SH
449 value_type = flower_icmp_attr_type(eth_type, ip_proto, field);
450 mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto, field);
451 if (value_type < 0 || mask_type < 0)
eb3b5696
SH
452 return -1;
453
6374961a 454 return flower_parse_u8(str, value_type, mask_type, NULL, NULL, n);
eb3b5696
SH
455}
456
6910d656 457static int flower_port_attr_type(__u8 ip_proto, enum flower_endpoint endpoint)
30eb304e 458{
6bd5b80c 459 if (ip_proto == IPPROTO_TCP)
6910d656
SH
460 return endpoint == FLOWER_ENDPOINT_SRC ?
461 TCA_FLOWER_KEY_TCP_SRC :
a1fb0d48 462 TCA_FLOWER_KEY_TCP_DST;
6bd5b80c 463 else if (ip_proto == IPPROTO_UDP)
6910d656
SH
464 return endpoint == FLOWER_ENDPOINT_SRC ?
465 TCA_FLOWER_KEY_UDP_SRC :
a1fb0d48 466 TCA_FLOWER_KEY_UDP_DST;
6bd5b80c 467 else if (ip_proto == IPPROTO_SCTP)
6910d656
SH
468 return endpoint == FLOWER_ENDPOINT_SRC ?
469 TCA_FLOWER_KEY_SCTP_SRC :
a1fb0d48 470 TCA_FLOWER_KEY_SCTP_DST;
6bd5b80c 471 else
30eb304e 472 return -1;
a1fb0d48
SH
473}
474
6910d656
SH
475static int flower_parse_port(char *str, __u8 ip_proto,
476 enum flower_endpoint endpoint,
a1fb0d48
SH
477 struct nlmsghdr *n)
478{
479 int ret;
480 int type;
481 __be16 port;
482
6910d656 483 type = flower_port_attr_type(ip_proto, endpoint);
a1fb0d48
SH
484 if (type < 0)
485 return -1;
30eb304e 486
9f7401fa 487 ret = get_be16(&port, str, 10);
30eb304e
JP
488 if (ret)
489 return -1;
490
9f7401fa 491 addattr16(n, MAX_MSG, type, port);
30eb304e
JP
492
493 return 0;
494}
495
0c30d14d
JP
496#define TCP_FLAGS_MAX_MASK 0xfff
497
498static int flower_parse_tcp_flags(char *str, int flags_type, int mask_type,
499 struct nlmsghdr *n)
500{
501 char *slash;
502 int ret, err = -1;
503 __u16 flags;
504
505 slash = strchr(str, '/');
506 if (slash)
507 *slash = '\0';
508
509 ret = get_u16(&flags, str, 16);
510 if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK)
511 goto err;
512
513 addattr16(n, MAX_MSG, flags_type, htons(flags));
514
515 if (slash) {
516 ret = get_u16(&flags, slash + 1, 16);
517 if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK)
518 goto err;
519 } else {
520 flags = TCP_FLAGS_MAX_MASK;
521 }
522 addattr16(n, MAX_MSG, mask_type, htons(flags));
523
524 err = 0;
525err:
526 if (slash)
527 *slash = '/';
528 return err;
529}
530
6ea2c2b1
OG
531static int flower_parse_ip_tos_ttl(char *str, int key_type, int mask_type,
532 struct nlmsghdr *n)
533{
534 char *slash;
535 int ret, err = -1;
536 __u8 tos_ttl;
537
538 slash = strchr(str, '/');
539 if (slash)
540 *slash = '\0';
541
542 ret = get_u8(&tos_ttl, str, 10);
543 if (ret < 0)
544 ret = get_u8(&tos_ttl, str, 16);
545 if (ret < 0)
546 goto err;
547
548 addattr8(n, MAX_MSG, key_type, tos_ttl);
549
550 if (slash) {
551 ret = get_u8(&tos_ttl, slash + 1, 16);
552 if (ret < 0)
553 goto err;
554 } else {
555 tos_ttl = 0xff;
556 }
557 addattr8(n, MAX_MSG, mask_type, tos_ttl);
558
559 err = 0;
560err:
561 if (slash)
562 *slash = '/';
563 return err;
564}
565
bb9b63b1
AV
566static int flower_parse_key_id(const char *str, int type, struct nlmsghdr *n)
567{
568 int ret;
569 __be32 key_id;
570
571 ret = get_be32(&key_id, str, 10);
572 if (!ret)
573 addattr32(n, MAX_MSG, type, key_id);
574
575 return ret;
576}
577
41aa17ff
HHZ
578static int flower_parse_enc_port(char *str, int type, struct nlmsghdr *n)
579{
580 int ret;
581 __be16 port;
582
583 ret = get_be16(&port, str, 10);
584 if (ret)
585 return -1;
586
587 addattr16(n, MAX_MSG, type, port);
588
589 return 0;
590}
591
30eb304e
JP
592static int flower_parse_opt(struct filter_util *qu, char *handle,
593 int argc, char **argv, struct nlmsghdr *n)
594{
595 int ret;
596 struct tcmsg *t = NLMSG_DATA(n);
597 struct rtattr *tail;
488b41d0 598 __be16 eth_type = TC_H_MIN(t->tcm_info);
745d9172 599 __be16 vlan_ethtype = 0;
1f0a5dfd 600 __be16 cvlan_ethtype = 0;
30eb304e 601 __u8 ip_proto = 0xff;
cfcabf18 602 __u32 flags = 0;
08f66c80
PB
603 __u32 mtf = 0;
604 __u32 mtf_mask = 0;
30eb304e 605
30eb304e
JP
606 if (handle) {
607 ret = get_u32(&t->tcm_handle, handle, 0);
608 if (ret) {
609 fprintf(stderr, "Illegal \"handle\"\n");
610 return -1;
611 }
612 }
613
614 tail = (struct rtattr *) (((void *) n) + NLMSG_ALIGN(n->nlmsg_len));
615 addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
616
488b41d0
JHS
617 if (argc == 0) {
618 /*at minimal we will match all ethertype packets */
619 goto parse_done;
620 }
621
30eb304e
JP
622 while (argc > 0) {
623 if (matches(*argv, "classid") == 0 ||
624 matches(*argv, "flowid") == 0) {
32a121cb 625 unsigned int handle;
30eb304e
JP
626
627 NEXT_ARG();
628 ret = get_tc_classid(&handle, *argv);
629 if (ret) {
630 fprintf(stderr, "Illegal \"classid\"\n");
631 return -1;
632 }
633 addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle, 4);
0d575c4d
AN
634 } else if (matches(*argv, "hw_tc") == 0) {
635 unsigned int handle;
636 __u32 tc;
637 char *end;
638
639 NEXT_ARG();
640 tc = strtoul(*argv, &end, 0);
641 if (*end) {
642 fprintf(stderr, "Illegal TC index\n");
643 return -1;
644 }
645 if (tc >= TC_QOPT_MAX_QUEUE) {
646 fprintf(stderr, "TC index exceeds max range\n");
647 return -1;
648 }
649 handle = TC_H_MAKE(TC_H_MAJ(t->tcm_parent),
650 TC_H_MIN(tc + TC_H_MIN_PRIORITY));
651 addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle,
652 sizeof(handle));
08f66c80 653 } else if (matches(*argv, "ip_flags") == 0) {
22a8f019
PB
654 NEXT_ARG();
655 ret = flower_parse_matching_flags(*argv,
08f66c80
PB
656 FLOWER_IP_FLAGS,
657 &mtf,
658 &mtf_mask);
22a8f019 659 if (ret < 0) {
08f66c80 660 fprintf(stderr, "Illegal \"ip_flags\"\n");
22a8f019
PB
661 return -1;
662 }
ac6a4c22
MRL
663 } else if (matches(*argv, "verbose") == 0) {
664 flags |= TCA_CLS_FLAGS_VERBOSE;
cfcabf18
AV
665 } else if (matches(*argv, "skip_hw") == 0) {
666 flags |= TCA_CLS_FLAGS_SKIP_HW;
667 } else if (matches(*argv, "skip_sw") == 0) {
668 flags |= TCA_CLS_FLAGS_SKIP_SW;
30eb304e 669 } else if (matches(*argv, "indev") == 0) {
30eb304e 670 NEXT_ARG();
625df645
PS
671 if (check_ifname(*argv))
672 invarg("\"indev\" not a valid ifname", *argv);
ee474849 673 addattrstrz(n, MAX_MSG, TCA_FLOWER_INDEV, *argv);
745d9172
HHZ
674 } else if (matches(*argv, "vlan_id") == 0) {
675 __u16 vid;
676
677 NEXT_ARG();
1f0a5dfd
JL
678 if (!eth_type_vlan(eth_type)) {
679 fprintf(stderr, "Can't set \"vlan_id\" if ethertype isn't 802.1Q or 802.1AD\n");
745d9172
HHZ
680 return -1;
681 }
682 ret = get_u16(&vid, *argv, 10);
683 if (ret < 0 || vid & ~0xfff) {
684 fprintf(stderr, "Illegal \"vlan_id\"\n");
685 return -1;
686 }
687 addattr16(n, MAX_MSG, TCA_FLOWER_KEY_VLAN_ID, vid);
688 } else if (matches(*argv, "vlan_prio") == 0) {
689 __u8 vlan_prio;
690
691 NEXT_ARG();
1f0a5dfd
JL
692 if (!eth_type_vlan(eth_type)) {
693 fprintf(stderr, "Can't set \"vlan_prio\" if ethertype isn't 802.1Q or 802.1AD\n");
745d9172
HHZ
694 return -1;
695 }
696 ret = get_u8(&vlan_prio, *argv, 10);
697 if (ret < 0 || vlan_prio & ~0x7) {
698 fprintf(stderr, "Illegal \"vlan_prio\"\n");
699 return -1;
700 }
512caeb2
SH
701 addattr8(n, MAX_MSG,
702 TCA_FLOWER_KEY_VLAN_PRIO, vlan_prio);
745d9172
HHZ
703 } else if (matches(*argv, "vlan_ethtype") == 0) {
704 NEXT_ARG();
705 ret = flower_parse_vlan_eth_type(*argv, eth_type,
512caeb2
SH
706 TCA_FLOWER_KEY_VLAN_ETH_TYPE,
707 &vlan_ethtype, n);
745d9172
HHZ
708 if (ret < 0)
709 return -1;
1f0a5dfd
JL
710 } else if (matches(*argv, "cvlan_id") == 0) {
711 __u16 vid;
712
713 NEXT_ARG();
714 if (!eth_type_vlan(vlan_ethtype)) {
715 fprintf(stderr, "Can't set \"cvlan_id\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n");
716 return -1;
717 }
718 ret = get_u16(&vid, *argv, 10);
719 if (ret < 0 || vid & ~0xfff) {
720 fprintf(stderr, "Illegal \"cvlan_id\"\n");
721 return -1;
722 }
723 addattr16(n, MAX_MSG, TCA_FLOWER_KEY_CVLAN_ID, vid);
724 } else if (matches(*argv, "cvlan_prio") == 0) {
725 __u8 cvlan_prio;
726
727 NEXT_ARG();
728 if (!eth_type_vlan(vlan_ethtype)) {
729 fprintf(stderr, "Can't set \"cvlan_prio\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n");
730 return -1;
731 }
732 ret = get_u8(&cvlan_prio, *argv, 10);
733 if (ret < 0 || cvlan_prio & ~0x7) {
734 fprintf(stderr, "Illegal \"cvlan_prio\"\n");
735 return -1;
736 }
737 addattr8(n, MAX_MSG,
738 TCA_FLOWER_KEY_CVLAN_PRIO, cvlan_prio);
739 } else if (matches(*argv, "cvlan_ethtype") == 0) {
740 NEXT_ARG();
741 ret = flower_parse_vlan_eth_type(*argv, vlan_ethtype,
742 TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
743 &cvlan_ethtype, n);
744 if (ret < 0)
745 return -1;
7638ee13
BL
746 } else if (matches(*argv, "mpls_label") == 0) {
747 __u32 label;
748
749 NEXT_ARG();
750 if (eth_type != htons(ETH_P_MPLS_UC) &&
751 eth_type != htons(ETH_P_MPLS_MC)) {
752 fprintf(stderr,
753 "Can't set \"mpls_label\" if ethertype isn't MPLS\n");
754 return -1;
755 }
756 ret = get_u32(&label, *argv, 10);
757 if (ret < 0 || label & ~(MPLS_LS_LABEL_MASK >> MPLS_LS_LABEL_SHIFT)) {
758 fprintf(stderr, "Illegal \"mpls_label\"\n");
759 return -1;
760 }
761 addattr32(n, MAX_MSG, TCA_FLOWER_KEY_MPLS_LABEL, label);
762 } else if (matches(*argv, "mpls_tc") == 0) {
763 __u8 tc;
764
765 NEXT_ARG();
766 if (eth_type != htons(ETH_P_MPLS_UC) &&
767 eth_type != htons(ETH_P_MPLS_MC)) {
768 fprintf(stderr,
769 "Can't set \"mpls_tc\" if ethertype isn't MPLS\n");
770 return -1;
771 }
772 ret = get_u8(&tc, *argv, 10);
773 if (ret < 0 || tc & ~(MPLS_LS_TC_MASK >> MPLS_LS_TC_SHIFT)) {
774 fprintf(stderr, "Illegal \"mpls_tc\"\n");
775 return -1;
776 }
777 addattr8(n, MAX_MSG, TCA_FLOWER_KEY_MPLS_TC, tc);
778 } else if (matches(*argv, "mpls_bos") == 0) {
779 __u8 bos;
780
781 NEXT_ARG();
782 if (eth_type != htons(ETH_P_MPLS_UC) &&
783 eth_type != htons(ETH_P_MPLS_MC)) {
784 fprintf(stderr,
785 "Can't set \"mpls_bos\" if ethertype isn't MPLS\n");
786 return -1;
787 }
788 ret = get_u8(&bos, *argv, 10);
789 if (ret < 0 || bos & ~(MPLS_LS_S_MASK >> MPLS_LS_S_SHIFT)) {
790 fprintf(stderr, "Illegal \"mpls_bos\"\n");
791 return -1;
792 }
793 addattr8(n, MAX_MSG, TCA_FLOWER_KEY_MPLS_BOS, bos);
794 } else if (matches(*argv, "mpls_ttl") == 0) {
795 __u8 ttl;
796
797 NEXT_ARG();
798 if (eth_type != htons(ETH_P_MPLS_UC) &&
799 eth_type != htons(ETH_P_MPLS_MC)) {
800 fprintf(stderr,
801 "Can't set \"mpls_ttl\" if ethertype isn't MPLS\n");
802 return -1;
803 }
804 ret = get_u8(&ttl, *argv, 10);
805 if (ret < 0 || ttl & ~(MPLS_LS_TTL_MASK >> MPLS_LS_TTL_SHIFT)) {
806 fprintf(stderr, "Illegal \"mpls_ttl\"\n");
807 return -1;
808 }
809 addattr8(n, MAX_MSG, TCA_FLOWER_KEY_MPLS_TTL, ttl);
30eb304e
JP
810 } else if (matches(*argv, "dst_mac") == 0) {
811 NEXT_ARG();
812 ret = flower_parse_eth_addr(*argv,
813 TCA_FLOWER_KEY_ETH_DST,
814 TCA_FLOWER_KEY_ETH_DST_MASK,
815 n);
816 if (ret < 0) {
817 fprintf(stderr, "Illegal \"dst_mac\"\n");
818 return -1;
819 }
820 } else if (matches(*argv, "src_mac") == 0) {
821 NEXT_ARG();
822 ret = flower_parse_eth_addr(*argv,
823 TCA_FLOWER_KEY_ETH_SRC,
824 TCA_FLOWER_KEY_ETH_SRC_MASK,
825 n);
826 if (ret < 0) {
827 fprintf(stderr, "Illegal \"src_mac\"\n");
828 return -1;
829 }
30eb304e
JP
830 } else if (matches(*argv, "ip_proto") == 0) {
831 NEXT_ARG();
1f0a5dfd
JL
832 ret = flower_parse_ip_proto(*argv, cvlan_ethtype ?
833 cvlan_ethtype : vlan_ethtype ?
745d9172 834 vlan_ethtype : eth_type,
30eb304e
JP
835 TCA_FLOWER_KEY_IP_PROTO,
836 &ip_proto, n);
837 if (ret < 0) {
838 fprintf(stderr, "Illegal \"ip_proto\"\n");
839 return -1;
840 }
6ea2c2b1
OG
841 } else if (matches(*argv, "ip_tos") == 0) {
842 NEXT_ARG();
843 ret = flower_parse_ip_tos_ttl(*argv,
844 TCA_FLOWER_KEY_IP_TOS,
845 TCA_FLOWER_KEY_IP_TOS_MASK,
846 n);
847 if (ret < 0) {
848 fprintf(stderr, "Illegal \"ip_tos\"\n");
849 return -1;
850 }
851 } else if (matches(*argv, "ip_ttl") == 0) {
852 NEXT_ARG();
853 ret = flower_parse_ip_tos_ttl(*argv,
854 TCA_FLOWER_KEY_IP_TTL,
855 TCA_FLOWER_KEY_IP_TTL_MASK,
856 n);
857 if (ret < 0) {
858 fprintf(stderr, "Illegal \"ip_ttl\"\n");
859 return -1;
860 }
30eb304e
JP
861 } else if (matches(*argv, "dst_ip") == 0) {
862 NEXT_ARG();
1f0a5dfd
JL
863 ret = flower_parse_ip_addr(*argv, cvlan_ethtype ?
864 cvlan_ethtype : vlan_ethtype ?
745d9172 865 vlan_ethtype : eth_type,
30eb304e
JP
866 TCA_FLOWER_KEY_IPV4_DST,
867 TCA_FLOWER_KEY_IPV4_DST_MASK,
868 TCA_FLOWER_KEY_IPV6_DST,
869 TCA_FLOWER_KEY_IPV6_DST_MASK,
870 n);
871 if (ret < 0) {
872 fprintf(stderr, "Illegal \"dst_ip\"\n");
873 return -1;
874 }
875 } else if (matches(*argv, "src_ip") == 0) {
876 NEXT_ARG();
1f0a5dfd
JL
877 ret = flower_parse_ip_addr(*argv, cvlan_ethtype ?
878 cvlan_ethtype : vlan_ethtype ?
745d9172 879 vlan_ethtype : eth_type,
30eb304e
JP
880 TCA_FLOWER_KEY_IPV4_SRC,
881 TCA_FLOWER_KEY_IPV4_SRC_MASK,
882 TCA_FLOWER_KEY_IPV6_SRC,
883 TCA_FLOWER_KEY_IPV6_SRC_MASK,
884 n);
885 if (ret < 0) {
886 fprintf(stderr, "Illegal \"src_ip\"\n");
887 return -1;
888 }
889 } else if (matches(*argv, "dst_port") == 0) {
890 NEXT_ARG();
6910d656
SH
891 ret = flower_parse_port(*argv, ip_proto,
892 FLOWER_ENDPOINT_DST, n);
30eb304e
JP
893 if (ret < 0) {
894 fprintf(stderr, "Illegal \"dst_port\"\n");
895 return -1;
896 }
897 } else if (matches(*argv, "src_port") == 0) {
898 NEXT_ARG();
6910d656
SH
899 ret = flower_parse_port(*argv, ip_proto,
900 FLOWER_ENDPOINT_SRC, n);
30eb304e
JP
901 if (ret < 0) {
902 fprintf(stderr, "Illegal \"src_port\"\n");
903 return -1;
904 }
0c30d14d
JP
905 } else if (matches(*argv, "tcp_flags") == 0) {
906 NEXT_ARG();
907 ret = flower_parse_tcp_flags(*argv,
908 TCA_FLOWER_KEY_TCP_FLAGS,
909 TCA_FLOWER_KEY_TCP_FLAGS_MASK,
910 n);
911 if (ret < 0) {
912 fprintf(stderr, "Illegal \"tcp_flags\"\n");
913 return -1;
914 }
eb3b5696
SH
915 } else if (matches(*argv, "type") == 0) {
916 NEXT_ARG();
917 ret = flower_parse_icmp(*argv, eth_type, ip_proto,
918 FLOWER_ICMP_FIELD_TYPE, n);
919 if (ret < 0) {
920 fprintf(stderr, "Illegal \"icmp type\"\n");
921 return -1;
922 }
923 } else if (matches(*argv, "code") == 0) {
924 NEXT_ARG();
925 ret = flower_parse_icmp(*argv, eth_type, ip_proto,
926 FLOWER_ICMP_FIELD_CODE, n);
927 if (ret < 0) {
928 fprintf(stderr, "Illegal \"icmp code\"\n");
929 return -1;
930 }
f888f4e2
SH
931 } else if (matches(*argv, "arp_tip") == 0) {
932 NEXT_ARG();
933 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ?
934 vlan_ethtype : eth_type,
935 TCA_FLOWER_KEY_ARP_TIP,
936 TCA_FLOWER_KEY_ARP_TIP_MASK,
937 n);
938 if (ret < 0) {
939 fprintf(stderr, "Illegal \"arp_tip\"\n");
940 return -1;
941 }
942 } else if (matches(*argv, "arp_sip") == 0) {
943 NEXT_ARG();
944 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ?
945 vlan_ethtype : eth_type,
946 TCA_FLOWER_KEY_ARP_SIP,
947 TCA_FLOWER_KEY_ARP_SIP_MASK,
948 n);
949 if (ret < 0) {
950 fprintf(stderr, "Illegal \"arp_sip\"\n");
951 return -1;
952 }
953 } else if (matches(*argv, "arp_op") == 0) {
954 NEXT_ARG();
955 ret = flower_parse_arp_op(*argv, vlan_ethtype ?
956 vlan_ethtype : eth_type,
957 TCA_FLOWER_KEY_ARP_OP,
958 TCA_FLOWER_KEY_ARP_OP_MASK,
959 n);
960 if (ret < 0) {
961 fprintf(stderr, "Illegal \"arp_op\"\n");
962 return -1;
963 }
964 } else if (matches(*argv, "arp_tha") == 0) {
965 NEXT_ARG();
966 ret = flower_parse_eth_addr(*argv,
967 TCA_FLOWER_KEY_ARP_THA,
968 TCA_FLOWER_KEY_ARP_THA_MASK,
969 n);
970 if (ret < 0) {
971 fprintf(stderr, "Illegal \"arp_tha\"\n");
972 return -1;
973 }
974 } else if (matches(*argv, "arp_sha") == 0) {
975 NEXT_ARG();
976 ret = flower_parse_eth_addr(*argv,
977 TCA_FLOWER_KEY_ARP_SHA,
978 TCA_FLOWER_KEY_ARP_SHA_MASK,
979 n);
980 if (ret < 0) {
981 fprintf(stderr, "Illegal \"arp_sha\"\n");
982 return -1;
983 }
bb9b63b1
AV
984 } else if (matches(*argv, "enc_dst_ip") == 0) {
985 NEXT_ARG();
986 ret = flower_parse_ip_addr(*argv, 0,
987 TCA_FLOWER_KEY_ENC_IPV4_DST,
988 TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,
989 TCA_FLOWER_KEY_ENC_IPV6_DST,
990 TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,
991 n);
992 if (ret < 0) {
993 fprintf(stderr, "Illegal \"enc_dst_ip\"\n");
994 return -1;
995 }
996 } else if (matches(*argv, "enc_src_ip") == 0) {
997 NEXT_ARG();
998 ret = flower_parse_ip_addr(*argv, 0,
999 TCA_FLOWER_KEY_ENC_IPV4_SRC,
1000 TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,
1001 TCA_FLOWER_KEY_ENC_IPV6_SRC,
1002 TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,
1003 n);
1004 if (ret < 0) {
1005 fprintf(stderr, "Illegal \"enc_src_ip\"\n");
1006 return -1;
1007 }
1008 } else if (matches(*argv, "enc_key_id") == 0) {
1009 NEXT_ARG();
1010 ret = flower_parse_key_id(*argv,
1011 TCA_FLOWER_KEY_ENC_KEY_ID, n);
1012 if (ret < 0) {
1013 fprintf(stderr, "Illegal \"enc_key_id\"\n");
1014 return -1;
1015 }
41aa17ff
HHZ
1016 } else if (matches(*argv, "enc_dst_port") == 0) {
1017 NEXT_ARG();
1018 ret = flower_parse_enc_port(*argv,
1019 TCA_FLOWER_KEY_ENC_UDP_DST_PORT, n);
1020 if (ret < 0) {
1021 fprintf(stderr, "Illegal \"enc_dst_port\"\n");
1022 return -1;
1023 }
761ec9e2
OG
1024 } else if (matches(*argv, "enc_tos") == 0) {
1025 NEXT_ARG();
1026 ret = flower_parse_ip_tos_ttl(*argv,
1027 TCA_FLOWER_KEY_ENC_IP_TOS,
1028 TCA_FLOWER_KEY_ENC_IP_TOS_MASK,
1029 n);
1030 if (ret < 0) {
1031 fprintf(stderr, "Illegal \"enc_tos\"\n");
1032 return -1;
1033 }
1034 } else if (matches(*argv, "enc_ttl") == 0) {
1035 NEXT_ARG();
1036 ret = flower_parse_ip_tos_ttl(*argv,
1037 TCA_FLOWER_KEY_ENC_IP_TTL,
1038 TCA_FLOWER_KEY_ENC_IP_TTL_MASK,
1039 n);
1040 if (ret < 0) {
1041 fprintf(stderr, "Illegal \"enc_ttl\"\n");
1042 return -1;
1043 }
30eb304e
JP
1044 } else if (matches(*argv, "action") == 0) {
1045 NEXT_ARG();
1046 ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n);
1047 if (ret) {
1048 fprintf(stderr, "Illegal \"action\"\n");
1049 return -1;
1050 }
1051 continue;
1052 } else if (strcmp(*argv, "help") == 0) {
1053 explain();
1054 return -1;
1055 } else {
1056 fprintf(stderr, "What is \"%s\"?\n", *argv);
1057 explain();
1058 return -1;
1059 }
1060 argc--; argv++;
1061 }
1062
488b41d0 1063parse_done:
c85609b2
RD
1064 ret = addattr32(n, MAX_MSG, TCA_FLOWER_FLAGS, flags);
1065 if (ret)
1066 return ret;
cfcabf18 1067
08f66c80
PB
1068 if (mtf_mask) {
1069 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS, htonl(mtf));
1070 if (ret)
1071 return ret;
1072
1073 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS_MASK, htonl(mtf_mask));
1074 if (ret)
1075 return ret;
1076 }
1077
4f7d406f
BL
1078 if (eth_type != htons(ETH_P_ALL)) {
1079 ret = addattr16(n, MAX_MSG, TCA_FLOWER_KEY_ETH_TYPE, eth_type);
1080 if (ret)
1081 return ret;
1082 }
488b41d0 1083
32a121cb 1084 tail->rta_len = (((void *)n)+n->nlmsg_len) - (void *)tail;
30eb304e
JP
1085
1086 return 0;
1087}
1088
1089static int __mask_bits(char *addr, size_t len)
1090{
1091 int bits = 0;
1092 bool hole = false;
1093 int i;
1094 int j;
1095
1096 for (i = 0; i < len; i++, addr++) {
1097 for (j = 7; j >= 0; j--) {
1098 if (((*addr) >> j) & 0x1) {
1099 if (hole)
1100 return -1;
1101 bits++;
1102 } else if (bits) {
1103 hole = true;
1104 } else{
1105 return -1;
1106 }
1107 }
1108 }
1109 return bits;
1110}
1111
e28b88a4 1112static void flower_print_eth_addr(char *name, struct rtattr *addr_attr,
30eb304e
JP
1113 struct rtattr *mask_attr)
1114{
e28b88a4
JP
1115 SPRINT_BUF(namefrm);
1116 SPRINT_BUF(out);
30eb304e 1117 SPRINT_BUF(b1);
e28b88a4 1118 size_t done;
30eb304e
JP
1119 int bits;
1120
1121 if (!addr_attr || RTA_PAYLOAD(addr_attr) != ETH_ALEN)
1122 return;
e28b88a4
JP
1123 done = sprintf(out, "%s",
1124 ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN,
1125 0, b1, sizeof(b1)));
1126 if (mask_attr && RTA_PAYLOAD(mask_attr) == ETH_ALEN) {
1127 bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN);
1128 if (bits < 0)
1129 sprintf(out + done, "/%s",
1130 ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN,
1131 0, b1, sizeof(b1)));
1132 else if (bits < ETH_ALEN * 8)
1133 sprintf(out + done, "/%d", bits);
1134 }
1135
1136 sprintf(namefrm, "\n %s %%s", name);
1137 print_string(PRINT_ANY, name, namefrm, out);
30eb304e
JP
1138}
1139
e28b88a4 1140static void flower_print_eth_type(__be16 *p_eth_type,
30eb304e
JP
1141 struct rtattr *eth_type_attr)
1142{
e28b88a4 1143 SPRINT_BUF(out);
30eb304e
JP
1144 __be16 eth_type;
1145
1146 if (!eth_type_attr)
1147 return;
1148
1149 eth_type = rta_getattr_u16(eth_type_attr);
30eb304e 1150 if (eth_type == htons(ETH_P_IP))
e28b88a4 1151 sprintf(out, "ipv4");
30eb304e 1152 else if (eth_type == htons(ETH_P_IPV6))
e28b88a4 1153 sprintf(out, "ipv6");
f888f4e2 1154 else if (eth_type == htons(ETH_P_ARP))
e28b88a4 1155 sprintf(out, "arp");
f888f4e2 1156 else if (eth_type == htons(ETH_P_RARP))
e28b88a4 1157 sprintf(out, "rarp");
30eb304e 1158 else
e28b88a4
JP
1159 sprintf(out, "%04x", ntohs(eth_type));
1160
1161 print_string(PRINT_ANY, "eth_type", "\n eth_type %s", out);
30eb304e
JP
1162 *p_eth_type = eth_type;
1163}
1164
e28b88a4 1165static void flower_print_ip_proto(__u8 *p_ip_proto,
30eb304e
JP
1166 struct rtattr *ip_proto_attr)
1167{
e28b88a4 1168 SPRINT_BUF(out);
30eb304e
JP
1169 __u8 ip_proto;
1170
1171 if (!ip_proto_attr)
1172 return;
1173
1174 ip_proto = rta_getattr_u8(ip_proto_attr);
30eb304e 1175 if (ip_proto == IPPROTO_TCP)
e28b88a4 1176 sprintf(out, "tcp");
30eb304e 1177 else if (ip_proto == IPPROTO_UDP)
e28b88a4 1178 sprintf(out, "udp");
a1fb0d48 1179 else if (ip_proto == IPPROTO_SCTP)
e28b88a4 1180 sprintf(out, "sctp");
eb3b5696 1181 else if (ip_proto == IPPROTO_ICMP)
e28b88a4 1182 sprintf(out, "icmp");
eb3b5696 1183 else if (ip_proto == IPPROTO_ICMPV6)
e28b88a4 1184 sprintf(out, "icmpv6");
30eb304e 1185 else
e28b88a4
JP
1186 sprintf(out, "%02x", ip_proto);
1187
1188 print_string(PRINT_ANY, "ip_proto", "\n ip_proto %s", out);
30eb304e
JP
1189 *p_ip_proto = ip_proto;
1190}
1191
e8bd3955 1192static void flower_print_ip_attr(const char *name, struct rtattr *key_attr,
6ea2c2b1
OG
1193 struct rtattr *mask_attr)
1194{
e28b88a4
JP
1195 SPRINT_BUF(namefrm);
1196 SPRINT_BUF(out);
1197 size_t done;
1198
6ea2c2b1
OG
1199 if (!key_attr)
1200 return;
1201
e8bd3955 1202 done = sprintf(out, "0x%x", rta_getattr_u8(key_attr));
e28b88a4
JP
1203 if (mask_attr)
1204 sprintf(out + done, "/%x", rta_getattr_u8(mask_attr));
1205
e8bd3955
KL
1206 print_string(PRINT_FP, NULL, "%s ", _SL_);
1207 sprintf(namefrm, "%s %%s", name);
e28b88a4 1208 print_string(PRINT_ANY, name, namefrm, out);
6ea2c2b1
OG
1209}
1210
e28b88a4 1211static void flower_print_matching_flags(char *name,
08f66c80 1212 enum flower_matching_flags type,
22a8f019
PB
1213 struct rtattr *attr,
1214 struct rtattr *mask_attr)
1215{
08f66c80
PB
1216 int i;
1217 int count = 0;
1218 __u32 mtf;
1219 __u32 mtf_mask;
1220
22a8f019
PB
1221 if (!mask_attr || RTA_PAYLOAD(mask_attr) != 4)
1222 return;
1223
08f66c80
PB
1224 mtf = ntohl(rta_getattr_u32(attr));
1225 mtf_mask = ntohl(rta_getattr_u32(mask_attr));
1226
1227 for (i = 0; i < ARRAY_SIZE(flags_str); i++) {
1228 if (type != flags_str[i].type)
1229 continue;
1230 if (mtf_mask & flags_str[i].flag) {
e28b88a4
JP
1231 if (++count == 1) {
1232 print_string(PRINT_FP, NULL, "\n %s ", name);
1233 open_json_object(name);
1234 } else {
1235 print_string(PRINT_FP, NULL, "/", NULL);
1236 }
08f66c80 1237
e28b88a4
JP
1238 print_bool(PRINT_JSON, flags_str[i].string, NULL,
1239 mtf & flags_str[i].flag);
08f66c80 1240 if (mtf & flags_str[i].flag)
e28b88a4
JP
1241 print_string(PRINT_FP, NULL, "%s",
1242 flags_str[i].string);
08f66c80 1243 else
e28b88a4
JP
1244 print_string(PRINT_FP, NULL, "no%s",
1245 flags_str[i].string);
08f66c80
PB
1246 }
1247 }
e28b88a4
JP
1248 if (count)
1249 close_json_object();
22a8f019
PB
1250}
1251
e28b88a4 1252static void flower_print_ip_addr(char *name, __be16 eth_type,
30eb304e
JP
1253 struct rtattr *addr4_attr,
1254 struct rtattr *mask4_attr,
1255 struct rtattr *addr6_attr,
1256 struct rtattr *mask6_attr)
1257{
30eb304e
JP
1258 struct rtattr *addr_attr;
1259 struct rtattr *mask_attr;
e28b88a4
JP
1260 SPRINT_BUF(namefrm);
1261 SPRINT_BUF(out);
1262 size_t done;
30eb304e
JP
1263 int family;
1264 size_t len;
1265 int bits;
1266
1267 if (eth_type == htons(ETH_P_IP)) {
1268 family = AF_INET;
1269 addr_attr = addr4_attr;
1270 mask_attr = mask4_attr;
1271 len = 4;
1272 } else if (eth_type == htons(ETH_P_IPV6)) {
1273 family = AF_INET6;
1274 addr_attr = addr6_attr;
1275 mask_attr = mask6_attr;
1276 len = 16;
1277 } else {
1278 return;
1279 }
1280 if (!addr_attr || RTA_PAYLOAD(addr_attr) != len)
1281 return;
30eb304e
JP
1282 if (!mask_attr || RTA_PAYLOAD(mask_attr) != len)
1283 return;
e28b88a4 1284 done = sprintf(out, "%s", rt_addr_n2a_rta(family, addr_attr));
30eb304e
JP
1285 bits = __mask_bits(RTA_DATA(mask_attr), len);
1286 if (bits < 0)
e28b88a4 1287 sprintf(out + done, "/%s", rt_addr_n2a_rta(family, mask_attr));
30eb304e 1288 else if (bits < len * 8)
e28b88a4
JP
1289 sprintf(out + done, "/%d", bits);
1290
1291 sprintf(namefrm, "\n %s %%s", name);
1292 print_string(PRINT_ANY, name, namefrm, out);
30eb304e 1293}
e28b88a4 1294static void flower_print_ip4_addr(char *name, struct rtattr *addr_attr,
f888f4e2
SH
1295 struct rtattr *mask_attr)
1296{
e28b88a4 1297 return flower_print_ip_addr(name, htons(ETH_P_IP),
f888f4e2
SH
1298 addr_attr, mask_attr, 0, 0);
1299}
30eb304e 1300
e28b88a4 1301static void flower_print_port(char *name, struct rtattr *attr)
30eb304e 1302{
e28b88a4
JP
1303 SPRINT_BUF(namefrm);
1304
1305 if (!attr)
1306 return;
1307
1308 sprintf(namefrm,"\n %s %%u", name);
0b01f088 1309 print_hu(PRINT_ANY, name, namefrm, rta_getattr_be16(attr));
30eb304e
JP
1310}
1311
e8bd3955 1312static void flower_print_tcp_flags(const char *name, struct rtattr *flags_attr,
e28b88a4 1313 struct rtattr *mask_attr)
0c30d14d 1314{
e28b88a4
JP
1315 SPRINT_BUF(namefrm);
1316 SPRINT_BUF(out);
1317 size_t done;
1318
0c30d14d
JP
1319 if (!flags_attr)
1320 return;
e28b88a4 1321
e8bd3955 1322 done = sprintf(out, "0x%x", rta_getattr_be16(flags_attr));
e28b88a4 1323 if (mask_attr)
e8bd3955 1324 sprintf(out + done, "/%x", rta_getattr_be16(mask_attr));
e28b88a4 1325
e8bd3955
KL
1326 print_string(PRINT_FP, NULL, "%s ", _SL_);
1327 sprintf(namefrm, "%s %%s", name);
e28b88a4 1328 print_string(PRINT_ANY, name, namefrm, out);
0c30d14d
JP
1329}
1330
1331
e28b88a4 1332static void flower_print_key_id(const char *name, struct rtattr *attr)
bb9b63b1 1333{
e28b88a4
JP
1334 SPRINT_BUF(namefrm);
1335
1336 if (!attr)
1337 return;
1338
1339 sprintf(namefrm,"\n %s %%u", name);
1340 print_uint(PRINT_ANY, name, namefrm, rta_getattr_be32(attr));
bb9b63b1
AV
1341}
1342
e28b88a4 1343static void flower_print_masked_u8(const char *name, struct rtattr *attr,
9d36e54f
SH
1344 struct rtattr *mask_attr,
1345 const char *(*value_to_str)(__u8 value))
f888f4e2 1346{
9d36e54f
SH
1347 const char *value_str = NULL;
1348 __u8 value, mask;
e28b88a4
JP
1349 SPRINT_BUF(namefrm);
1350 SPRINT_BUF(out);
1351 size_t done;
f888f4e2 1352
9d36e54f 1353 if (!attr)
f888f4e2
SH
1354 return;
1355
9d36e54f 1356 value = rta_getattr_u8(attr);
f888f4e2 1357 mask = mask_attr ? rta_getattr_u8(mask_attr) : UINT8_MAX;
9d36e54f
SH
1358 if (mask == UINT8_MAX && value_to_str)
1359 value_str = value_to_str(value);
f888f4e2 1360
9d36e54f 1361 if (value_str)
e28b88a4 1362 done = sprintf(out, "%s", value_str);
f888f4e2 1363 else
e28b88a4 1364 done = sprintf(out, "%d", value);
f888f4e2
SH
1365
1366 if (mask != UINT8_MAX)
e28b88a4
JP
1367 sprintf(out + done, "/%d", mask);
1368
1369 sprintf(namefrm,"\n %s %%s", name);
1370 print_string(PRINT_ANY, name, namefrm, out);
f888f4e2
SH
1371}
1372
e28b88a4 1373static void flower_print_u8(const char *name, struct rtattr *attr)
7638ee13 1374{
e28b88a4 1375 flower_print_masked_u8(name, attr, NULL, NULL);
7638ee13
BL
1376}
1377
e28b88a4 1378static void flower_print_u32(const char *name, struct rtattr *attr)
7638ee13 1379{
e28b88a4 1380 SPRINT_BUF(namefrm);
7638ee13
BL
1381
1382 if (!attr)
1383 return;
1384
e28b88a4
JP
1385 sprintf(namefrm,"\n %s %%u", name);
1386 print_uint(PRINT_ANY, name, namefrm, rta_getattr_u32(attr));
7638ee13
BL
1387}
1388
e28b88a4 1389static void flower_print_arp_op(const char *name,
9d36e54f
SH
1390 struct rtattr *op_attr,
1391 struct rtattr *mask_attr)
1392{
e28b88a4 1393 flower_print_masked_u8(name, op_attr, mask_attr,
9d36e54f
SH
1394 flower_print_arp_op_to_name);
1395}
1396
30eb304e
JP
1397static int flower_print_opt(struct filter_util *qu, FILE *f,
1398 struct rtattr *opt, __u32 handle)
1399{
1400 struct rtattr *tb[TCA_FLOWER_MAX + 1];
6374961a 1401 int nl_type, nl_mask_type;
30eb304e
JP
1402 __be16 eth_type = 0;
1403 __u8 ip_proto = 0xff;
1404
1405 if (!opt)
1406 return 0;
1407
1408 parse_rtattr_nested(tb, TCA_FLOWER_MAX, opt);
1409
1410 if (handle)
e28b88a4 1411 print_uint(PRINT_ANY, "handle", "handle 0x%x ", handle);
30eb304e
JP
1412
1413 if (tb[TCA_FLOWER_CLASSID]) {
0d575c4d
AN
1414 __u32 h = rta_getattr_u32(tb[TCA_FLOWER_CLASSID]);
1415
1416 if (TC_H_MIN(h) < TC_H_MIN_PRIORITY ||
1417 TC_H_MIN(h) > (TC_H_MIN_PRIORITY + TC_QOPT_MAX_QUEUE - 1)) {
1418 SPRINT_BUF(b1);
e28b88a4
JP
1419 print_string(PRINT_ANY, "classid", "classid %s ",
1420 sprint_tc_classid(h, b1));
0d575c4d 1421 } else {
e28b88a4
JP
1422 print_uint(PRINT_ANY, "hw_tc", "hw_tc %u ",
1423 TC_H_MIN(h) - TC_H_MIN_PRIORITY);
0d575c4d 1424 }
30eb304e
JP
1425 }
1426
1427 if (tb[TCA_FLOWER_INDEV]) {
1428 struct rtattr *attr = tb[TCA_FLOWER_INDEV];
1429
e28b88a4
JP
1430 print_string(PRINT_ANY, "indev", "\n indev %s",
1431 rta_getattr_str(attr));
30eb304e
JP
1432 }
1433
e28b88a4
JP
1434 open_json_object("keys");
1435
745d9172
HHZ
1436 if (tb[TCA_FLOWER_KEY_VLAN_ID]) {
1437 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ID];
1438
e28b88a4
JP
1439 print_uint(PRINT_ANY, "vlan_id", "\n vlan_id %u",
1440 rta_getattr_u16(attr));
745d9172
HHZ
1441 }
1442
1443 if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) {
1444 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_PRIO];
1445
e28b88a4
JP
1446 print_uint(PRINT_ANY, "vlan_prio", "\n vlan_prio %d",
1447 rta_getattr_u8(attr));
745d9172
HHZ
1448 }
1449
1f0a5dfd
JL
1450 if (tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) {
1451 SPRINT_BUF(buf);
1452 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE];
1453
1454 print_string(PRINT_ANY, "vlan_ethtype", "\n vlan_ethtype %s",
1455 ll_proto_n2a(rta_getattr_u16(attr),
1456 buf, sizeof(buf)));
1457 }
1458
1459 if (tb[TCA_FLOWER_KEY_CVLAN_ID]) {
1460 struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_ID];
1461
1462 print_uint(PRINT_ANY, "cvlan_id", "\n cvlan_id %u",
1463 rta_getattr_u16(attr));
1464 }
1465
1466 if (tb[TCA_FLOWER_KEY_CVLAN_PRIO]) {
1467 struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_PRIO];
1468
1469 print_uint(PRINT_ANY, "cvlan_prio", "\n cvlan_prio %d",
1470 rta_getattr_u8(attr));
1471 }
1472
1473 if (tb[TCA_FLOWER_KEY_CVLAN_ETH_TYPE]) {
1474 SPRINT_BUF(buf);
1475 struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_ETH_TYPE];
1476
1477 print_string(PRINT_ANY, "cvlan_ethtype", "\n cvlan_ethtype %s",
1478 ll_proto_n2a(rta_getattr_u16(attr),
1479 buf, sizeof(buf)));
1480 }
1481
e28b88a4 1482 flower_print_eth_addr("dst_mac", tb[TCA_FLOWER_KEY_ETH_DST],
30eb304e 1483 tb[TCA_FLOWER_KEY_ETH_DST_MASK]);
e28b88a4 1484 flower_print_eth_addr("src_mac", tb[TCA_FLOWER_KEY_ETH_SRC],
30eb304e
JP
1485 tb[TCA_FLOWER_KEY_ETH_SRC_MASK]);
1486
e28b88a4
JP
1487 flower_print_eth_type(&eth_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
1488 flower_print_ip_proto(&ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]);
30eb304e 1489
e28b88a4 1490 flower_print_ip_attr("ip_tos", tb[TCA_FLOWER_KEY_IP_TOS],
6ea2c2b1 1491 tb[TCA_FLOWER_KEY_IP_TOS_MASK]);
e28b88a4 1492 flower_print_ip_attr("ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL],
6ea2c2b1
OG
1493 tb[TCA_FLOWER_KEY_IP_TTL_MASK]);
1494
e28b88a4
JP
1495 flower_print_u32("mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]);
1496 flower_print_u8("mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]);
1497 flower_print_u8("mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]);
1498 flower_print_u8("mpls_ttl", tb[TCA_FLOWER_KEY_MPLS_TTL]);
7638ee13 1499
e28b88a4 1500 flower_print_ip_addr("dst_ip", eth_type,
30eb304e
JP
1501 tb[TCA_FLOWER_KEY_IPV4_DST],
1502 tb[TCA_FLOWER_KEY_IPV4_DST_MASK],
1503 tb[TCA_FLOWER_KEY_IPV6_DST],
1504 tb[TCA_FLOWER_KEY_IPV6_DST_MASK]);
1505
e28b88a4 1506 flower_print_ip_addr("src_ip", eth_type,
30eb304e
JP
1507 tb[TCA_FLOWER_KEY_IPV4_SRC],
1508 tb[TCA_FLOWER_KEY_IPV4_SRC_MASK],
1509 tb[TCA_FLOWER_KEY_IPV6_SRC],
1510 tb[TCA_FLOWER_KEY_IPV6_SRC_MASK]);
1511
b2141de1 1512 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_DST);
6bd5b80c 1513 if (nl_type >= 0)
e28b88a4 1514 flower_print_port("dst_port", tb[nl_type]);
b2141de1 1515 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_SRC);
6bd5b80c 1516 if (nl_type >= 0)
e28b88a4 1517 flower_print_port("src_port", tb[nl_type]);
30eb304e 1518
e28b88a4 1519 flower_print_tcp_flags("tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS],
0c30d14d
JP
1520 tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]);
1521
81f6e5a7
SH
1522 nl_type = flower_icmp_attr_type(eth_type, ip_proto,
1523 FLOWER_ICMP_FIELD_TYPE);
6374961a
SH
1524 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
1525 FLOWER_ICMP_FIELD_TYPE);
1526 if (nl_type >= 0 && nl_mask_type >= 0)
e28b88a4 1527 flower_print_masked_u8("icmp_type", tb[nl_type],
6374961a
SH
1528 tb[nl_mask_type], NULL);
1529
81f6e5a7
SH
1530 nl_type = flower_icmp_attr_type(eth_type, ip_proto,
1531 FLOWER_ICMP_FIELD_CODE);
6374961a
SH
1532 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
1533 FLOWER_ICMP_FIELD_CODE);
1534 if (nl_type >= 0 && nl_mask_type >= 0)
e28b88a4 1535 flower_print_masked_u8("icmp_code", tb[nl_type],
6374961a 1536 tb[nl_mask_type], NULL);
eb3b5696 1537
e28b88a4 1538 flower_print_ip4_addr("arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP],
f888f4e2 1539 tb[TCA_FLOWER_KEY_ARP_SIP_MASK]);
e28b88a4 1540 flower_print_ip4_addr("arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP],
f888f4e2 1541 tb[TCA_FLOWER_KEY_ARP_TIP_MASK]);
e28b88a4 1542 flower_print_arp_op("arp_op", tb[TCA_FLOWER_KEY_ARP_OP],
f888f4e2 1543 tb[TCA_FLOWER_KEY_ARP_OP_MASK]);
e28b88a4 1544 flower_print_eth_addr("arp_sha", tb[TCA_FLOWER_KEY_ARP_SHA],
f888f4e2 1545 tb[TCA_FLOWER_KEY_ARP_SHA_MASK]);
e28b88a4 1546 flower_print_eth_addr("arp_tha", tb[TCA_FLOWER_KEY_ARP_THA],
f888f4e2
SH
1547 tb[TCA_FLOWER_KEY_ARP_THA_MASK]);
1548
e28b88a4 1549 flower_print_ip_addr("enc_dst_ip",
bb9b63b1
AV
1550 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] ?
1551 htons(ETH_P_IP) : htons(ETH_P_IPV6),
1552 tb[TCA_FLOWER_KEY_ENC_IPV4_DST],
1553 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK],
1554 tb[TCA_FLOWER_KEY_ENC_IPV6_DST],
1555 tb[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]);
1556
e28b88a4 1557 flower_print_ip_addr("enc_src_ip",
bb9b63b1
AV
1558 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] ?
1559 htons(ETH_P_IP) : htons(ETH_P_IPV6),
1560 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC],
1561 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK],
1562 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC],
1563 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]);
1564
e28b88a4 1565 flower_print_key_id("enc_key_id", tb[TCA_FLOWER_KEY_ENC_KEY_ID]);
bb9b63b1 1566
e28b88a4 1567 flower_print_port("enc_dst_port", tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
41aa17ff 1568
761ec9e2
OG
1569 flower_print_ip_attr("enc_tos", tb[TCA_FLOWER_KEY_ENC_IP_TOS],
1570 tb[TCA_FLOWER_KEY_ENC_IP_TOS_MASK]);
1571 flower_print_ip_attr("enc_ttl", tb[TCA_FLOWER_KEY_ENC_IP_TTL],
1572 tb[TCA_FLOWER_KEY_ENC_IP_TTL_MASK]);
1573
e28b88a4 1574 flower_print_matching_flags("ip_flags", FLOWER_IP_FLAGS,
22a8f019
PB
1575 tb[TCA_FLOWER_KEY_FLAGS],
1576 tb[TCA_FLOWER_KEY_FLAGS_MASK]);
1577
e28b88a4
JP
1578 close_json_object();
1579
512caeb2 1580 if (tb[TCA_FLOWER_FLAGS]) {
cfcabf18
AV
1581 __u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]);
1582
1583 if (flags & TCA_CLS_FLAGS_SKIP_HW)
e28b88a4 1584 print_bool(PRINT_ANY, "skip_hw", "\n skip_hw", true);
cfcabf18 1585 if (flags & TCA_CLS_FLAGS_SKIP_SW)
e28b88a4 1586 print_bool(PRINT_ANY, "skip_sw", "\n skip_sw", true);
e57285b8
OG
1587
1588 if (flags & TCA_CLS_FLAGS_IN_HW)
e28b88a4 1589 print_bool(PRINT_ANY, "in_hw", "\n in_hw", true);
e57285b8 1590 else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
e28b88a4 1591 print_bool(PRINT_ANY, "not_in_hw", "\n not_in_hw", true);
cfcabf18
AV
1592 }
1593
512caeb2 1594 if (tb[TCA_FLOWER_ACT])
9e713525 1595 tc_print_action(f, tb[TCA_FLOWER_ACT], 0);
30eb304e
JP
1596
1597 return 0;
1598}
1599
1600struct filter_util flower_filter_util = {
1601 .id = "flower",
1602 .parse_fopt = flower_parse_opt,
1603 .print_fopt = flower_print_opt,
1604};