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>
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
explain(void)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
flower_parse_eth_addr(char * str,int addr_type,int mask_type,struct nlmsghdr * n)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
flower_parse_vlan_eth_type(char * str,__be16 eth_type,int type,__be16 * p_vlan_eth_type,struct nlmsghdr * n)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
flower_parse_matching_flags(char * str,enum flower_matching_flags type,__u32 * mtf,__u32 * mtf_mask)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
flower_parse_ip_proto(char * str,__be16 eth_type,int type,__u8 * p_ip_proto,struct nlmsghdr * n)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
__flower_parse_ip_addr(char * str,int family,int addr4_type,int mask4_type,int addr6_type,int mask6_type,struct nlmsghdr * n)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
flower_parse_ip_addr(char * str,__be16 eth_type,int addr4_type,int mask4_type,int addr6_type,int mask6_type,struct nlmsghdr * n)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
flower_eth_type_arp(__be16 eth_type)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
flower_parse_arp_ip_addr(char * str,__be16 eth_type,int addr_type,int mask_type,struct nlmsghdr * n)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
flower_parse_u8(char * str,int value_type,int mask_type,int (* value_from_name)(const char * str,__u8 * value),bool (* value_validate)(__u8 value),struct nlmsghdr * n)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
flower_print_arp_op_to_name(__u8 op)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
flower_arp_op_from_name(const char * name,__u8 * op)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
flow_arp_op_validate(__u8 op)382 static bool flow_arp_op_validate(__u8 op)
383 {
384 return !op || op == ARPOP_REQUEST || op == ARPOP_REPLY;
385 }
386
flower_parse_arp_op(char * str,__be16 eth_type,int op_type,int mask_type,struct nlmsghdr * n)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
flower_icmp_attr_type(__be16 eth_type,__u8 ip_proto,enum flower_icmp_field field)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
flower_icmp_attr_mask_type(__be16 eth_type,__u8 ip_proto,enum flower_icmp_field field)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
flower_parse_icmp(char * str,__u16 eth_type,__u8 ip_proto,enum flower_icmp_field field,struct nlmsghdr * n)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
flower_port_attr_type(__u8 ip_proto,enum flower_endpoint endpoint)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
flower_parse_port(char * str,__u8 ip_proto,enum flower_endpoint endpoint,struct nlmsghdr * n)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
flower_parse_tcp_flags(char * str,int flags_type,int mask_type,struct nlmsghdr * n)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
flower_parse_ip_tos_ttl(char * str,int key_type,int mask_type,struct nlmsghdr * n)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
flower_parse_key_id(const char * str,int type,struct nlmsghdr * n)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
flower_parse_enc_port(char * str,int type,struct nlmsghdr * n)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
flower_parse_opt(struct filter_util * qu,char * handle,int argc,char ** argv,struct nlmsghdr * n)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
__mask_bits(char * addr,size_t len)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
flower_print_eth_addr(FILE * f,char * name,struct rtattr * addr_attr,struct rtattr * mask_attr)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
flower_print_eth_type(FILE * f,__be16 * p_eth_type,struct rtattr * eth_type_attr)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
flower_print_ip_proto(FILE * f,__u8 * p_ip_proto,struct rtattr * ip_proto_attr)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
flower_print_ip_attr(FILE * f,char * name,struct rtattr * key_attr,struct rtattr * mask_attr)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
flower_print_matching_flags(FILE * f,char * name,enum flower_matching_flags type,struct rtattr * attr,struct rtattr * mask_attr)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
flower_print_ip_addr(FILE * f,char * name,__be16 eth_type,struct rtattr * addr4_attr,struct rtattr * mask4_attr,struct rtattr * addr6_attr,struct rtattr * mask6_attr)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 }
flower_print_ip4_addr(FILE * f,char * name,struct rtattr * addr_attr,struct rtattr * mask_attr)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
flower_print_port(FILE * f,char * name,struct rtattr * attr)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
flower_print_tcp_flags(FILE * f,char * name,struct rtattr * flags_attr,struct rtattr * mask_attr)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
flower_print_key_id(FILE * f,const char * name,struct rtattr * attr)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
flower_print_masked_u8(FILE * f,const char * name,struct rtattr * attr,struct rtattr * mask_attr,const char * (* value_to_str)(__u8 value))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
flower_print_arp_op(FILE * f,const char * name,struct rtattr * op_attr,struct rtattr * mask_attr)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
flower_print_opt(struct filter_util * qu,FILE * f,struct rtattr * opt,__u32 handle)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