Home | History | Annotate | Download | only in tc
      1 /*
      2  * q_u32.c		U32 filter.
      3  *
      4  *		This program is free software; you can u32istribute it and/or
      5  *		modify it under the terms of the GNU General Public License
      6  *		as published by the Free Software Foundation; either version
      7  *		2 of the License, or (at your option) any later version.
      8  *
      9  * Authors:	Alexey Kuznetsov, <kuznet (at) ms2.inr.ac.ru>
     10  *		Match mark added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro> [5 nov 2004]
     11  *
     12  */
     13 
     14 #include <stdio.h>
     15 #include <stdlib.h>
     16 #include <unistd.h>
     17 #include <syslog.h>
     18 #include <fcntl.h>
     19 #include <sys/socket.h>
     20 #include <netinet/in.h>
     21 #include <arpa/inet.h>
     22 #include <string.h>
     23 #include <linux/if.h>
     24 #include <linux/if_ether.h>
     25 
     26 #include "utils.h"
     27 #include "tc_util.h"
     28 
     29 extern int show_pretty;
     30 
     31 static void explain(void)
     32 {
     33 	fprintf(stderr,
     34 		"Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]\n"
     35 		"               [ action ACTION_SPEC ] [ offset OFFSET_SPEC ]\n"
     36 		"               [ ht HTID ] [ hashkey HASHKEY_SPEC ]\n"
     37 		"               [ sample SAMPLE ] [skip_hw | skip_sw]\n"
     38 		"or         u32 divisor DIVISOR\n"
     39 		"\n"
     40 		"Where: SELECTOR := SAMPLE SAMPLE ...\n"
     41 		"       SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark }\n"
     42 		"                 SAMPLE_ARGS [ divisor DIVISOR ]\n"
     43 		"       FILTERID := X:Y:Z\n"
     44 		"\nNOTE: CLASSID is parsed at hexadecimal input.\n");
     45 }
     46 
     47 static int get_u32_handle(__u32 *handle, const char *str)
     48 {
     49 	__u32 htid = 0, hash = 0, nodeid = 0;
     50 	char *tmp = strchr(str, ':');
     51 
     52 	if (tmp == NULL) {
     53 		if (memcmp("0x", str, 2) == 0)
     54 			return get_u32(handle, str, 16);
     55 		return -1;
     56 	}
     57 	htid = strtoul(str, &tmp, 16);
     58 	if (tmp == str && *str != ':' && *str != 0)
     59 		return -1;
     60 	if (htid >= 0x1000)
     61 		return -1;
     62 	if (*tmp) {
     63 		str = tmp + 1;
     64 		hash = strtoul(str, &tmp, 16);
     65 		if (tmp == str && *str != ':' && *str != 0)
     66 			return -1;
     67 		if (hash >= 0x100)
     68 			return -1;
     69 		if (*tmp) {
     70 			str = tmp + 1;
     71 			nodeid = strtoul(str, &tmp, 16);
     72 			if (tmp == str && *str != 0)
     73 				return -1;
     74 			if (nodeid >= 0x1000)
     75 				return -1;
     76 		}
     77 	}
     78 	*handle = (htid<<20)|(hash<<12)|nodeid;
     79 	return 0;
     80 }
     81 
     82 static char *sprint_u32_handle(__u32 handle, char *buf)
     83 {
     84 	int bsize = SPRINT_BSIZE-1;
     85 	__u32 htid = TC_U32_HTID(handle);
     86 	__u32 hash = TC_U32_HASH(handle);
     87 	__u32 nodeid = TC_U32_NODE(handle);
     88 	char *b = buf;
     89 
     90 	if (handle == 0) {
     91 		snprintf(b, bsize, "none");
     92 		return b;
     93 	}
     94 	if (htid) {
     95 		int l = snprintf(b, bsize, "%x:", htid>>20);
     96 
     97 		bsize -= l;
     98 		b += l;
     99 	}
    100 	if (nodeid|hash) {
    101 		if (hash) {
    102 			int l = snprintf(b, bsize, "%x", hash);
    103 
    104 			bsize -= l;
    105 			b += l;
    106 		}
    107 		if (nodeid) {
    108 			int l = snprintf(b, bsize, ":%x", nodeid);
    109 
    110 			bsize -= l;
    111 			b += l;
    112 		}
    113 	}
    114 	if (show_raw)
    115 		snprintf(b, bsize, "[%08x] ", handle);
    116 	return buf;
    117 }
    118 
    119 static int pack_key(struct tc_u32_sel *sel, __u32 key, __u32 mask,
    120 		    int off, int offmask)
    121 {
    122 	int i;
    123 	int hwm = sel->nkeys;
    124 
    125 	key &= mask;
    126 
    127 	for (i = 0; i < hwm; i++) {
    128 		if (sel->keys[i].off == off && sel->keys[i].offmask == offmask) {
    129 			__u32 intersect = mask & sel->keys[i].mask;
    130 
    131 			if ((key ^ sel->keys[i].val) & intersect)
    132 				return -1;
    133 			sel->keys[i].val |= key;
    134 			sel->keys[i].mask |= mask;
    135 			return 0;
    136 		}
    137 	}
    138 
    139 	if (hwm >= 128)
    140 		return -1;
    141 	if (off % 4)
    142 		return -1;
    143 	sel->keys[hwm].val = key;
    144 	sel->keys[hwm].mask = mask;
    145 	sel->keys[hwm].off = off;
    146 	sel->keys[hwm].offmask = offmask;
    147 	sel->nkeys++;
    148 	return 0;
    149 }
    150 
    151 static int pack_key32(struct tc_u32_sel *sel, __u32 key, __u32 mask,
    152 		      int off, int offmask)
    153 {
    154 	key = htonl(key);
    155 	mask = htonl(mask);
    156 	return pack_key(sel, key, mask, off, offmask);
    157 }
    158 
    159 static int pack_key16(struct tc_u32_sel *sel, __u32 key, __u32 mask,
    160 		      int off, int offmask)
    161 {
    162 	if (key > 0xFFFF || mask > 0xFFFF)
    163 		return -1;
    164 
    165 	if ((off & 3) == 0) {
    166 		key <<= 16;
    167 		mask <<= 16;
    168 	}
    169 	off &= ~3;
    170 	key = htonl(key);
    171 	mask = htonl(mask);
    172 
    173 	return pack_key(sel, key, mask, off, offmask);
    174 }
    175 
    176 static int pack_key8(struct tc_u32_sel *sel, __u32 key, __u32 mask, int off,
    177 		     int offmask)
    178 {
    179 	if (key > 0xFF || mask > 0xFF)
    180 		return -1;
    181 
    182 	if ((off & 3) == 0) {
    183 		key <<= 24;
    184 		mask <<= 24;
    185 	} else if ((off & 3) == 1) {
    186 		key <<= 16;
    187 		mask <<= 16;
    188 	} else if ((off & 3) == 2) {
    189 		key <<= 8;
    190 		mask <<= 8;
    191 	}
    192 	off &= ~3;
    193 	key = htonl(key);
    194 	mask = htonl(mask);
    195 
    196 	return pack_key(sel, key, mask, off, offmask);
    197 }
    198 
    199 
    200 static int parse_at(int *argc_p, char ***argv_p, int *off, int *offmask)
    201 {
    202 	int argc = *argc_p;
    203 	char **argv = *argv_p;
    204 	char *p = *argv;
    205 
    206 	if (argc <= 0)
    207 		return -1;
    208 
    209 	if (strlen(p) > strlen("nexthdr+") &&
    210 	    memcmp(p, "nexthdr+", strlen("nexthdr+")) == 0) {
    211 		*offmask = -1;
    212 		p += strlen("nexthdr+");
    213 	} else if (matches(*argv, "nexthdr+") == 0) {
    214 		NEXT_ARG();
    215 		*offmask = -1;
    216 		p = *argv;
    217 	}
    218 
    219 	if (get_integer(off, p, 0))
    220 		return -1;
    221 	argc--; argv++;
    222 
    223 	*argc_p = argc;
    224 	*argv_p = argv;
    225 	return 0;
    226 }
    227 
    228 
    229 static int parse_u32(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
    230 		     int off, int offmask)
    231 {
    232 	int res = -1;
    233 	int argc = *argc_p;
    234 	char **argv = *argv_p;
    235 	__u32 key;
    236 	__u32 mask;
    237 
    238 	if (argc < 2)
    239 		return -1;
    240 
    241 	if (get_u32(&key, *argv, 0))
    242 		return -1;
    243 	argc--; argv++;
    244 
    245 	if (get_u32(&mask, *argv, 16))
    246 		return -1;
    247 	argc--; argv++;
    248 
    249 	if (argc > 0 && strcmp(argv[0], "at") == 0) {
    250 		NEXT_ARG();
    251 		if (parse_at(&argc, &argv, &off, &offmask))
    252 			return -1;
    253 	}
    254 
    255 	res = pack_key32(sel, key, mask, off, offmask);
    256 	*argc_p = argc;
    257 	*argv_p = argv;
    258 	return res;
    259 }
    260 
    261 static int parse_u16(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
    262 		     int off, int offmask)
    263 {
    264 	int res = -1;
    265 	int argc = *argc_p;
    266 	char **argv = *argv_p;
    267 	__u32 key;
    268 	__u32 mask;
    269 
    270 	if (argc < 2)
    271 		return -1;
    272 
    273 	if (get_u32(&key, *argv, 0))
    274 		return -1;
    275 	argc--; argv++;
    276 
    277 	if (get_u32(&mask, *argv, 16))
    278 		return -1;
    279 	argc--; argv++;
    280 
    281 	if (argc > 0 && strcmp(argv[0], "at") == 0) {
    282 		NEXT_ARG();
    283 		if (parse_at(&argc, &argv, &off, &offmask))
    284 			return -1;
    285 	}
    286 	res = pack_key16(sel, key, mask, off, offmask);
    287 	*argc_p = argc;
    288 	*argv_p = argv;
    289 	return res;
    290 }
    291 
    292 static int parse_u8(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
    293 		    int off, int offmask)
    294 {
    295 	int res = -1;
    296 	int argc = *argc_p;
    297 	char **argv = *argv_p;
    298 	__u32 key;
    299 	__u32 mask;
    300 
    301 	if (argc < 2)
    302 		return -1;
    303 
    304 	if (get_u32(&key, *argv, 0))
    305 		return -1;
    306 	argc--; argv++;
    307 
    308 	if (get_u32(&mask, *argv, 16))
    309 		return -1;
    310 	argc--; argv++;
    311 
    312 	if (key > 0xFF || mask > 0xFF)
    313 		return -1;
    314 
    315 	if (argc > 0 && strcmp(argv[0], "at") == 0) {
    316 		NEXT_ARG();
    317 		if (parse_at(&argc, &argv, &off, &offmask))
    318 			return -1;
    319 	}
    320 
    321 	res = pack_key8(sel, key, mask, off, offmask);
    322 	*argc_p = argc;
    323 	*argv_p = argv;
    324 	return res;
    325 }
    326 
    327 static int parse_ip_addr(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
    328 			 int off)
    329 {
    330 	int res = -1;
    331 	int argc = *argc_p;
    332 	char **argv = *argv_p;
    333 	inet_prefix addr;
    334 	__u32 mask;
    335 	int offmask = 0;
    336 
    337 	if (argc < 1)
    338 		return -1;
    339 
    340 	if (get_prefix_1(&addr, *argv, AF_INET))
    341 		return -1;
    342 	argc--; argv++;
    343 
    344 	if (argc > 0 && strcmp(argv[0], "at") == 0) {
    345 		NEXT_ARG();
    346 		if (parse_at(&argc, &argv, &off, &offmask))
    347 			return -1;
    348 	}
    349 
    350 	mask = 0;
    351 	if (addr.bitlen)
    352 		mask = htonl(0xFFFFFFFF << (32 - addr.bitlen));
    353 	if (pack_key(sel, addr.data[0], mask, off, offmask) < 0)
    354 		return -1;
    355 	res = 0;
    356 
    357 	*argc_p = argc;
    358 	*argv_p = argv;
    359 	return res;
    360 }
    361 
    362 static int parse_ip6_addr(int *argc_p, char ***argv_p,
    363 			  struct tc_u32_sel *sel, int off)
    364 {
    365 	int res = -1;
    366 	int argc = *argc_p;
    367 	char **argv = *argv_p;
    368 	int plen = 128;
    369 	int i;
    370 	inet_prefix addr;
    371 	int offmask = 0;
    372 
    373 	if (argc < 1)
    374 		return -1;
    375 
    376 	if (get_prefix_1(&addr, *argv, AF_INET6))
    377 		return -1;
    378 	argc--; argv++;
    379 
    380 	if (argc > 0 && strcmp(argv[0], "at") == 0) {
    381 		NEXT_ARG();
    382 		if (parse_at(&argc, &argv, &off, &offmask))
    383 			return -1;
    384 	}
    385 
    386 	plen = addr.bitlen;
    387 	for (i = 0; i < plen; i += 32) {
    388 		if (i + 31 < plen) {
    389 			res = pack_key(sel, addr.data[i / 32],
    390 				       0xFFFFFFFF, off + 4 * (i / 32), offmask);
    391 			if (res < 0)
    392 				return -1;
    393 		} else if (i < plen) {
    394 			__u32 mask = htonl(0xFFFFFFFF << (32 - (plen - i)));
    395 
    396 			res = pack_key(sel, addr.data[i / 32],
    397 				       mask, off + 4 * (i / 32), offmask);
    398 			if (res < 0)
    399 				return -1;
    400 		}
    401 	}
    402 	res = 0;
    403 
    404 	*argc_p = argc;
    405 	*argv_p = argv;
    406 	return res;
    407 }
    408 
    409 static int parse_ip6_class(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
    410 {
    411 	int res = -1;
    412 	int argc = *argc_p;
    413 	char **argv = *argv_p;
    414 	__u32 key;
    415 	__u32 mask;
    416 	int off = 0;
    417 	int offmask = 0;
    418 
    419 	if (argc < 2)
    420 		return -1;
    421 
    422 	if (get_u32(&key, *argv, 0))
    423 		return -1;
    424 	argc--; argv++;
    425 
    426 	if (get_u32(&mask, *argv, 16))
    427 		return -1;
    428 	argc--; argv++;
    429 
    430 	if (key > 0xFF || mask > 0xFF)
    431 		return -1;
    432 
    433 	key <<= 20;
    434 	mask <<= 20;
    435 	key = htonl(key);
    436 	mask = htonl(mask);
    437 
    438 	res = pack_key(sel, key, mask, off, offmask);
    439 	if (res < 0)
    440 		return -1;
    441 
    442 	*argc_p = argc;
    443 	*argv_p = argv;
    444 	return 0;
    445 }
    446 
    447 static int parse_ether_addr(int *argc_p, char ***argv_p,
    448 			    struct tc_u32_sel *sel, int off)
    449 {
    450 	int res = -1;
    451 	int argc = *argc_p;
    452 	char **argv = *argv_p;
    453 	__u8 addr[6];
    454 	int offmask = 0;
    455 	int i;
    456 
    457 	if (argc < 1)
    458 		return -1;
    459 
    460 	if (sscanf(*argv, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
    461 		   addr + 0, addr + 1, addr + 2,
    462 		   addr + 3, addr + 4, addr + 5) != 6) {
    463 		fprintf(stderr, "parse_ether_addr: improperly formed address '%s'\n",
    464 			*argv);
    465 		return -1;
    466 	}
    467 
    468 	argc--; argv++;
    469 	if (argc > 0 && strcmp(argv[0], "at") == 0) {
    470 		NEXT_ARG();
    471 		if (parse_at(&argc, &argv, &off, &offmask))
    472 			return -1;
    473 	}
    474 
    475 	for (i = 0; i < 6; i++) {
    476 		res = pack_key8(sel, addr[i], 0xFF, off + i, offmask);
    477 		if (res < 0)
    478 			return -1;
    479 	}
    480 
    481 	*argc_p = argc;
    482 	*argv_p = argv;
    483 	return res;
    484 }
    485 
    486 static int parse_ip(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
    487 {
    488 	int res = -1;
    489 	int argc = *argc_p;
    490 	char **argv = *argv_p;
    491 
    492 	if (argc < 2)
    493 		return -1;
    494 
    495 	if (strcmp(*argv, "src") == 0) {
    496 		NEXT_ARG();
    497 		res = parse_ip_addr(&argc, &argv, sel, 12);
    498 	} else if (strcmp(*argv, "dst") == 0) {
    499 		NEXT_ARG();
    500 		res = parse_ip_addr(&argc, &argv, sel, 16);
    501 	} else if (strcmp(*argv, "tos") == 0 ||
    502 	    matches(*argv, "dsfield") == 0 ||
    503 	    matches(*argv, "precedence") == 0) {
    504 		NEXT_ARG();
    505 		res = parse_u8(&argc, &argv, sel, 1, 0);
    506 	} else if (strcmp(*argv, "ihl") == 0) {
    507 		NEXT_ARG();
    508 		res = parse_u8(&argc, &argv, sel, 0, 0);
    509 	} else if (strcmp(*argv, "protocol") == 0) {
    510 		NEXT_ARG();
    511 		res = parse_u8(&argc, &argv, sel, 9, 0);
    512 	} else if (strcmp(*argv, "nofrag") == 0) {
    513 		argc--; argv++;
    514 		res = pack_key16(sel, 0, 0x3FFF, 6, 0);
    515 	} else if (strcmp(*argv, "firstfrag") == 0) {
    516 		argc--; argv++;
    517 		res = pack_key16(sel, 0x2000, 0x3FFF, 6, 0);
    518 	} else if (strcmp(*argv, "df") == 0) {
    519 		argc--; argv++;
    520 		res = pack_key16(sel, 0x4000, 0x4000, 6, 0);
    521 	} else if (strcmp(*argv, "mf") == 0) {
    522 		argc--; argv++;
    523 		res = pack_key16(sel, 0x2000, 0x2000, 6, 0);
    524 	} else if (strcmp(*argv, "dport") == 0) {
    525 		NEXT_ARG();
    526 		res = parse_u16(&argc, &argv, sel, 22, 0);
    527 	} else if (strcmp(*argv, "sport") == 0) {
    528 		NEXT_ARG();
    529 		res = parse_u16(&argc, &argv, sel, 20, 0);
    530 	} else if (strcmp(*argv, "icmp_type") == 0) {
    531 		NEXT_ARG();
    532 		res = parse_u8(&argc, &argv, sel, 20, 0);
    533 	} else if (strcmp(*argv, "icmp_code") == 0) {
    534 		NEXT_ARG();
    535 		res = parse_u8(&argc, &argv, sel, 21, 0);
    536 	} else
    537 		return -1;
    538 
    539 	*argc_p = argc;
    540 	*argv_p = argv;
    541 	return res;
    542 }
    543 
    544 static int parse_ip6(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
    545 {
    546 	int res = -1;
    547 	int argc = *argc_p;
    548 	char **argv = *argv_p;
    549 
    550 	if (argc < 2)
    551 		return -1;
    552 
    553 	if (strcmp(*argv, "src") == 0) {
    554 		NEXT_ARG();
    555 		res = parse_ip6_addr(&argc, &argv, sel, 8);
    556 	} else if (strcmp(*argv, "dst") == 0) {
    557 		NEXT_ARG();
    558 		res = parse_ip6_addr(&argc, &argv, sel, 24);
    559 	} else if (strcmp(*argv, "priority") == 0) {
    560 		NEXT_ARG();
    561 		res = parse_ip6_class(&argc, &argv, sel);
    562 	} else if (strcmp(*argv, "protocol") == 0) {
    563 		NEXT_ARG();
    564 		res = parse_u8(&argc, &argv, sel, 6, 0);
    565 	} else if (strcmp(*argv, "flowlabel") == 0) {
    566 		NEXT_ARG();
    567 		res = parse_u32(&argc, &argv, sel, 0, 0);
    568 	} else if (strcmp(*argv, "dport") == 0) {
    569 		NEXT_ARG();
    570 		res = parse_u16(&argc, &argv, sel, 42, 0);
    571 	} else if (strcmp(*argv, "sport") == 0) {
    572 		NEXT_ARG();
    573 		res = parse_u16(&argc, &argv, sel, 40, 0);
    574 	} else if (strcmp(*argv, "icmp_type") == 0) {
    575 		NEXT_ARG();
    576 		res = parse_u8(&argc, &argv, sel, 40, 0);
    577 	} else if (strcmp(*argv, "icmp_code") == 0) {
    578 		NEXT_ARG();
    579 		res = parse_u8(&argc, &argv, sel, 41, 1);
    580 	} else
    581 		return -1;
    582 
    583 	*argc_p = argc;
    584 	*argv_p = argv;
    585 	return res;
    586 }
    587 
    588 static int parse_ether(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
    589 {
    590 	int res = -1;
    591 	int argc = *argc_p;
    592 	char **argv = *argv_p;
    593 
    594 	if (argc < 2)
    595 		return -1;
    596 
    597 	if (strcmp(*argv, "src") == 0) {
    598 		NEXT_ARG();
    599 		res = parse_ether_addr(&argc, &argv, sel, -8);
    600 	} else if (strcmp(*argv, "dst") == 0) {
    601 		NEXT_ARG();
    602 		res = parse_ether_addr(&argc, &argv, sel, -14);
    603 	} else {
    604 		fprintf(stderr, "Unknown match: ether %s\n", *argv);
    605 		return -1;
    606 	}
    607 
    608 	*argc_p = argc;
    609 	*argv_p = argv;
    610 	return res;
    611 }
    612 
    613 #define parse_tcp parse_udp
    614 static int parse_udp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
    615 {
    616 	int res = -1;
    617 	int argc = *argc_p;
    618 	char **argv = *argv_p;
    619 
    620 	if (argc < 2)
    621 		return -1;
    622 
    623 	if (strcmp(*argv, "src") == 0) {
    624 		NEXT_ARG();
    625 		res = parse_u16(&argc, &argv, sel, 0, -1);
    626 	} else if (strcmp(*argv, "dst") == 0) {
    627 		NEXT_ARG();
    628 		res = parse_u16(&argc, &argv, sel, 2, -1);
    629 	} else
    630 		return -1;
    631 
    632 	*argc_p = argc;
    633 	*argv_p = argv;
    634 	return res;
    635 }
    636 
    637 
    638 static int parse_icmp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
    639 {
    640 	int res = -1;
    641 	int argc = *argc_p;
    642 	char **argv = *argv_p;
    643 
    644 	if (argc < 2)
    645 		return -1;
    646 
    647 	if (strcmp(*argv, "type") == 0) {
    648 		NEXT_ARG();
    649 		res = parse_u8(&argc, &argv, sel, 0, -1);
    650 	} else if (strcmp(*argv, "code") == 0) {
    651 		NEXT_ARG();
    652 		res = parse_u8(&argc, &argv, sel, 1, -1);
    653 	} else
    654 		return -1;
    655 
    656 	*argc_p = argc;
    657 	*argv_p = argv;
    658 	return res;
    659 }
    660 
    661 static int parse_mark(int *argc_p, char ***argv_p, struct nlmsghdr *n)
    662 {
    663 	int res = -1;
    664 	int argc = *argc_p;
    665 	char **argv = *argv_p;
    666 	struct tc_u32_mark mark;
    667 
    668 	if (argc <= 1)
    669 		return -1;
    670 
    671 	if (get_u32(&mark.val, *argv, 0)) {
    672 		fprintf(stderr, "Illegal \"mark\" value\n");
    673 		return -1;
    674 	}
    675 	NEXT_ARG();
    676 
    677 	if (get_u32(&mark.mask, *argv, 0)) {
    678 		fprintf(stderr, "Illegal \"mark\" mask\n");
    679 		return -1;
    680 	}
    681 	NEXT_ARG();
    682 
    683 	if ((mark.val & mark.mask) != mark.val) {
    684 		fprintf(stderr, "Illegal \"mark\" (impossible combination)\n");
    685 		return -1;
    686 	}
    687 
    688 	addattr_l(n, MAX_MSG, TCA_U32_MARK, &mark, sizeof(mark));
    689 	res = 0;
    690 
    691 	*argc_p = argc;
    692 	*argv_p = argv;
    693 	return res;
    694 }
    695 
    696 static int parse_selector(int *argc_p, char ***argv_p,
    697 			  struct tc_u32_sel *sel, struct nlmsghdr *n)
    698 {
    699 	int argc = *argc_p;
    700 	char **argv = *argv_p;
    701 	int res = -1;
    702 
    703 	if (argc <= 0)
    704 		return -1;
    705 
    706 	if (matches(*argv, "u32") == 0) {
    707 		NEXT_ARG();
    708 		res = parse_u32(&argc, &argv, sel, 0, 0);
    709 	} else if (matches(*argv, "u16") == 0) {
    710 		NEXT_ARG();
    711 		res = parse_u16(&argc, &argv, sel, 0, 0);
    712 	} else if (matches(*argv, "u8") == 0) {
    713 		NEXT_ARG();
    714 		res = parse_u8(&argc, &argv, sel, 0, 0);
    715 	} else if (matches(*argv, "ip") == 0) {
    716 		NEXT_ARG();
    717 		res = parse_ip(&argc, &argv, sel);
    718 	} else	if (matches(*argv, "ip6") == 0) {
    719 		NEXT_ARG();
    720 		res = parse_ip6(&argc, &argv, sel);
    721 	} else if (matches(*argv, "udp") == 0) {
    722 		NEXT_ARG();
    723 		res = parse_udp(&argc, &argv, sel);
    724 	} else if (matches(*argv, "tcp") == 0) {
    725 		NEXT_ARG();
    726 		res = parse_tcp(&argc, &argv, sel);
    727 	} else if (matches(*argv, "icmp") == 0) {
    728 		NEXT_ARG();
    729 		res = parse_icmp(&argc, &argv, sel);
    730 	} else if (matches(*argv, "mark") == 0) {
    731 		NEXT_ARG();
    732 		res = parse_mark(&argc, &argv, n);
    733 	} else if (matches(*argv, "ether") == 0) {
    734 		NEXT_ARG();
    735 		res = parse_ether(&argc, &argv, sel);
    736 	} else
    737 		return -1;
    738 
    739 	*argc_p = argc;
    740 	*argv_p = argv;
    741 	return res;
    742 }
    743 
    744 static int parse_offset(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
    745 {
    746 	int argc = *argc_p;
    747 	char **argv = *argv_p;
    748 
    749 	while (argc > 0) {
    750 		if (matches(*argv, "plus") == 0) {
    751 			int off;
    752 
    753 			NEXT_ARG();
    754 			if (get_integer(&off, *argv, 0))
    755 				return -1;
    756 			sel->off = off;
    757 			sel->flags |= TC_U32_OFFSET;
    758 		} else if (matches(*argv, "at") == 0) {
    759 			int off;
    760 
    761 			NEXT_ARG();
    762 			if (get_integer(&off, *argv, 0))
    763 				return -1;
    764 			sel->offoff = off;
    765 			if (off%2) {
    766 				fprintf(stderr, "offset \"at\" must be even\n");
    767 				return -1;
    768 			}
    769 			sel->flags |= TC_U32_VAROFFSET;
    770 		} else if (matches(*argv, "mask") == 0) {
    771 			NEXT_ARG();
    772 			if (get_be16(&sel->offmask, *argv, 16))
    773 				return -1;
    774 			sel->flags |= TC_U32_VAROFFSET;
    775 		} else if (matches(*argv, "shift") == 0) {
    776 			int shift;
    777 
    778 			NEXT_ARG();
    779 			if (get_integer(&shift, *argv, 0))
    780 				return -1;
    781 			sel->offshift = shift;
    782 			sel->flags |= TC_U32_VAROFFSET;
    783 		} else if (matches(*argv, "eat") == 0) {
    784 			sel->flags |= TC_U32_EAT;
    785 		} else {
    786 			break;
    787 		}
    788 		argc--; argv++;
    789 	}
    790 
    791 	*argc_p = argc;
    792 	*argv_p = argv;
    793 	return 0;
    794 }
    795 
    796 static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
    797 {
    798 	int argc = *argc_p;
    799 	char **argv = *argv_p;
    800 
    801 	while (argc > 0) {
    802 		if (matches(*argv, "mask") == 0) {
    803 			NEXT_ARG();
    804 			if (get_be32(&sel->hmask, *argv, 16))
    805 				return -1;
    806 		} else if (matches(*argv, "at") == 0) {
    807 			int num;
    808 
    809 			NEXT_ARG();
    810 			if (get_integer(&num, *argv, 0))
    811 				return -1;
    812 			if (num%4)
    813 				return -1;
    814 			sel->hoff = num;
    815 		} else {
    816 			break;
    817 		}
    818 		argc--; argv++;
    819 	}
    820 
    821 	*argc_p = argc;
    822 	*argv_p = argv;
    823 	return 0;
    824 }
    825 
    826 static void print_ipv4(FILE *f, const struct tc_u32_key *key)
    827 {
    828 	char abuf[256];
    829 
    830 	switch (key->off) {
    831 	case 0:
    832 		switch (ntohl(key->mask)) {
    833 		case 0x0f000000:
    834 			fprintf(f, "\n  match IP ihl %u",
    835 				ntohl(key->val) >> 24);
    836 			return;
    837 		case 0x00ff0000:
    838 			fprintf(f, "\n  match IP dsfield %#x",
    839 				ntohl(key->val) >> 16);
    840 			return;
    841 		}
    842 		break;
    843 	case 8:
    844 		if (ntohl(key->mask) == 0x00ff0000) {
    845 			fprintf(f, "\n  match IP protocol %d",
    846 				ntohl(key->val) >> 16);
    847 			return;
    848 		}
    849 		break;
    850 	case 12:
    851 	case 16: {
    852 			int bits = mask2bits(key->mask);
    853 
    854 			if (bits >= 0) {
    855 				fprintf(f, "\n  %s %s/%d",
    856 					key->off == 12 ? "match IP src" : "match IP dst",
    857 					inet_ntop(AF_INET, &key->val,
    858 						  abuf, sizeof(abuf)),
    859 					bits);
    860 				return;
    861 			}
    862 		}
    863 		break;
    864 
    865 	case 20:
    866 		switch (ntohl(key->mask)) {
    867 		case 0x0000ffff:
    868 			fprintf(f, "\n  match dport %u",
    869 				ntohl(key->val) & 0xffff);
    870 			return;
    871 		case 0xffff0000:
    872 			fprintf(f, "\n  match sport %u",
    873 				ntohl(key->val) >> 16);
    874 			return;
    875 		case 0xffffffff:
    876 			fprintf(f, "\n  match dport %u, match sport %u",
    877 				ntohl(key->val) & 0xffff,
    878 				ntohl(key->val) >> 16);
    879 
    880 			return;
    881 		}
    882 		/* XXX: Default print_raw */
    883 	}
    884 }
    885 
    886 static void print_ipv6(FILE *f, const struct tc_u32_key *key)
    887 {
    888 	char abuf[256];
    889 
    890 	switch (key->off) {
    891 	case 0:
    892 		switch (ntohl(key->mask)) {
    893 		case 0x0f000000:
    894 			fprintf(f, "\n  match IP ihl %u",
    895 				ntohl(key->val) >> 24);
    896 			return;
    897 		case 0x00ff0000:
    898 			fprintf(f, "\n  match IP dsfield %#x",
    899 				ntohl(key->val) >> 16);
    900 			return;
    901 		}
    902 		break;
    903 	case 8:
    904 		if (ntohl(key->mask) == 0x00ff0000) {
    905 			fprintf(f, "\n  match IP protocol %d",
    906 				ntohl(key->val) >> 16);
    907 			return;
    908 		}
    909 		break;
    910 	case 12:
    911 	case 16: {
    912 			int bits = mask2bits(key->mask);
    913 
    914 			if (bits >= 0) {
    915 				fprintf(f, "\n  %s %s/%d",
    916 					key->off == 12 ? "match IP src" : "match IP dst",
    917 					inet_ntop(AF_INET, &key->val,
    918 						  abuf, sizeof(abuf)),
    919 					bits);
    920 				return;
    921 			}
    922 		}
    923 		break;
    924 
    925 	case 20:
    926 		switch (ntohl(key->mask)) {
    927 		case 0x0000ffff:
    928 			fprintf(f, "\n  match sport %u",
    929 				ntohl(key->val) & 0xffff);
    930 			return;
    931 		case 0xffff0000:
    932 			fprintf(f, "\n  match dport %u",
    933 				ntohl(key->val) >> 16);
    934 			return;
    935 		case 0xffffffff:
    936 			fprintf(f, "\n  match sport %u, match dport %u",
    937 				ntohl(key->val) & 0xffff,
    938 				ntohl(key->val) >> 16);
    939 
    940 			return;
    941 		}
    942 		/* XXX: Default print_raw */
    943 	}
    944 }
    945 
    946 static void print_raw(FILE *f, const struct tc_u32_key *key)
    947 {
    948 	fprintf(f, "\n  match %08x/%08x at %s%d",
    949 		(unsigned int)ntohl(key->val),
    950 		(unsigned int)ntohl(key->mask),
    951 		key->offmask ? "nexthdr+" : "",
    952 		key->off);
    953 }
    954 
    955 static const struct {
    956 	__u16 proto;
    957 	__u16 pad;
    958 	void (*pprinter)(FILE *f, const struct tc_u32_key *key);
    959 } u32_pprinters[] = {
    960 	{0,	   0, print_raw},
    961 	{ETH_P_IP, 0, print_ipv4},
    962 	{ETH_P_IPV6, 0, print_ipv6},
    963 };
    964 
    965 static void show_keys(FILE *f, const struct tc_u32_key *key)
    966 {
    967 	int i = 0;
    968 
    969 	if (!show_pretty)
    970 		goto show_k;
    971 
    972 	for (i = 0; i < ARRAY_SIZE(u32_pprinters); i++) {
    973 		if (u32_pprinters[i].proto == ntohs(f_proto)) {
    974 show_k:
    975 			u32_pprinters[i].pprinter(f, key);
    976 			return;
    977 		}
    978 	}
    979 
    980 	i = 0;
    981 	goto show_k;
    982 }
    983 
    984 static int u32_parse_opt(struct filter_util *qu, char *handle,
    985 			 int argc, char **argv, struct nlmsghdr *n)
    986 {
    987 	struct {
    988 		struct tc_u32_sel sel;
    989 		struct tc_u32_key keys[128];
    990 	} sel = {};
    991 	struct tcmsg *t = NLMSG_DATA(n);
    992 	struct rtattr *tail;
    993 	int sel_ok = 0, terminal_ok = 0;
    994 	int sample_ok = 0;
    995 	__u32 htid = 0;
    996 	__u32 order = 0;
    997 	__u32 flags = 0;
    998 
    999 	if (handle && get_u32_handle(&t->tcm_handle, handle)) {
   1000 		fprintf(stderr, "Illegal filter ID\n");
   1001 		return -1;
   1002 	}
   1003 
   1004 	if (argc == 0)
   1005 		return 0;
   1006 
   1007 	tail = NLMSG_TAIL(n);
   1008 	addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
   1009 
   1010 	while (argc > 0) {
   1011 		if (matches(*argv, "match") == 0) {
   1012 			NEXT_ARG();
   1013 			if (parse_selector(&argc, &argv, &sel.sel, n)) {
   1014 				fprintf(stderr, "Illegal \"match\"\n");
   1015 				return -1;
   1016 			}
   1017 			sel_ok++;
   1018 			continue;
   1019 		} else if (matches(*argv, "offset") == 0) {
   1020 			NEXT_ARG();
   1021 			if (parse_offset(&argc, &argv, &sel.sel)) {
   1022 				fprintf(stderr, "Illegal \"offset\"\n");
   1023 				return -1;
   1024 			}
   1025 			continue;
   1026 		} else if (matches(*argv, "hashkey") == 0) {
   1027 			NEXT_ARG();
   1028 			if (parse_hashkey(&argc, &argv, &sel.sel)) {
   1029 				fprintf(stderr, "Illegal \"hashkey\"\n");
   1030 				return -1;
   1031 			}
   1032 			continue;
   1033 		} else if (matches(*argv, "classid") == 0 ||
   1034 			   strcmp(*argv, "flowid") == 0) {
   1035 			unsigned int flowid;
   1036 
   1037 			NEXT_ARG();
   1038 			if (get_tc_classid(&flowid, *argv)) {
   1039 				fprintf(stderr, "Illegal \"classid\"\n");
   1040 				return -1;
   1041 			}
   1042 			addattr_l(n, MAX_MSG, TCA_U32_CLASSID, &flowid, 4);
   1043 			sel.sel.flags |= TC_U32_TERMINAL;
   1044 		} else if (matches(*argv, "divisor") == 0) {
   1045 			unsigned int divisor;
   1046 
   1047 			NEXT_ARG();
   1048 			if (get_unsigned(&divisor, *argv, 0) ||
   1049 			    divisor == 0 ||
   1050 			    divisor > 0x100 || ((divisor - 1) & divisor)) {
   1051 				fprintf(stderr, "Illegal \"divisor\"\n");
   1052 				return -1;
   1053 			}
   1054 			addattr_l(n, MAX_MSG, TCA_U32_DIVISOR, &divisor, 4);
   1055 		} else if (matches(*argv, "order") == 0) {
   1056 			NEXT_ARG();
   1057 			if (get_u32(&order, *argv, 0)) {
   1058 				fprintf(stderr, "Illegal \"order\"\n");
   1059 				return -1;
   1060 			}
   1061 		} else if (strcmp(*argv, "link") == 0) {
   1062 			unsigned int linkid;
   1063 
   1064 			NEXT_ARG();
   1065 			if (get_u32_handle(&linkid, *argv)) {
   1066 				fprintf(stderr, "Illegal \"link\"\n");
   1067 				return -1;
   1068 			}
   1069 			if (linkid && TC_U32_NODE(linkid)) {
   1070 				fprintf(stderr, "\"link\" must be a hash table.\n");
   1071 				return -1;
   1072 			}
   1073 			addattr_l(n, MAX_MSG, TCA_U32_LINK, &linkid, 4);
   1074 		} else if (strcmp(*argv, "ht") == 0) {
   1075 			unsigned int ht;
   1076 
   1077 			NEXT_ARG();
   1078 			if (get_u32_handle(&ht, *argv)) {
   1079 				fprintf(stderr, "Illegal \"ht\"\n");
   1080 				return -1;
   1081 			}
   1082 			if (handle && TC_U32_NODE(ht)) {
   1083 				fprintf(stderr, "\"ht\" must be a hash table.\n");
   1084 				return -1;
   1085 			}
   1086 			if (sample_ok)
   1087 				htid = (htid & 0xFF000) | (ht & 0xFFF00000);
   1088 			else
   1089 				htid = (ht & 0xFFFFF000);
   1090 		} else if (strcmp(*argv, "sample") == 0) {
   1091 			__u32 hash;
   1092 			unsigned int divisor = 0x100;
   1093 			struct {
   1094 				struct tc_u32_sel sel;
   1095 				struct tc_u32_key keys[4];
   1096 			} sel2 = {};
   1097 
   1098 			NEXT_ARG();
   1099 			if (parse_selector(&argc, &argv, &sel2.sel, n)) {
   1100 				fprintf(stderr, "Illegal \"sample\"\n");
   1101 				return -1;
   1102 			}
   1103 			if (sel2.sel.nkeys != 1) {
   1104 				fprintf(stderr, "\"sample\" must contain exactly ONE key.\n");
   1105 				return -1;
   1106 			}
   1107 			if (*argv != 0 && strcmp(*argv, "divisor") == 0) {
   1108 				NEXT_ARG();
   1109 				if (get_unsigned(&divisor, *argv, 0) ||
   1110 				    divisor == 0 || divisor > 0x100 ||
   1111 				    ((divisor - 1) & divisor)) {
   1112 					fprintf(stderr, "Illegal sample \"divisor\"\n");
   1113 					return -1;
   1114 				}
   1115 				NEXT_ARG();
   1116 			}
   1117 			hash = sel2.sel.keys[0].val & sel2.sel.keys[0].mask;
   1118 			hash ^= hash >> 16;
   1119 			hash ^= hash >> 8;
   1120 			htid = ((hash % divisor) << 12) | (htid & 0xFFF00000);
   1121 			sample_ok = 1;
   1122 			continue;
   1123 		} else if (strcmp(*argv, "indev") == 0) {
   1124 			char ind[IFNAMSIZ + 1] = {};
   1125 
   1126 			argc--;
   1127 			argv++;
   1128 			if (argc < 1) {
   1129 				fprintf(stderr, "Illegal indev\n");
   1130 				return -1;
   1131 			}
   1132 			strncpy(ind, *argv, sizeof(ind) - 1);
   1133 			addattr_l(n, MAX_MSG, TCA_U32_INDEV, ind,
   1134 				  strlen(ind) + 1);
   1135 
   1136 		} else if (matches(*argv, "action") == 0) {
   1137 			NEXT_ARG();
   1138 			if (parse_action(&argc, &argv, TCA_U32_ACT, n)) {
   1139 				fprintf(stderr, "Illegal \"action\"\n");
   1140 				return -1;
   1141 			}
   1142 			terminal_ok++;
   1143 			continue;
   1144 
   1145 		} else if (matches(*argv, "police") == 0) {
   1146 			NEXT_ARG();
   1147 			if (parse_police(&argc, &argv, TCA_U32_POLICE, n)) {
   1148 				fprintf(stderr, "Illegal \"police\"\n");
   1149 				return -1;
   1150 			}
   1151 			terminal_ok++;
   1152 			continue;
   1153 		} else if (strcmp(*argv, "skip_hw") == 0) {
   1154 			NEXT_ARG();
   1155 			flags |= TCA_CLS_FLAGS_SKIP_HW;
   1156 			continue;
   1157 		} else if (strcmp(*argv, "skip_sw") == 0) {
   1158 			NEXT_ARG();
   1159 			flags |= TCA_CLS_FLAGS_SKIP_SW;
   1160 			continue;
   1161 		} else if (strcmp(*argv, "help") == 0) {
   1162 			explain();
   1163 			return -1;
   1164 		} else {
   1165 			fprintf(stderr, "What is \"%s\"?\n", *argv);
   1166 			explain();
   1167 			return -1;
   1168 		}
   1169 		argc--; argv++;
   1170 	}
   1171 
   1172 	/* We dont necessarily need class/flowids */
   1173 	if (terminal_ok)
   1174 		sel.sel.flags |= TC_U32_TERMINAL;
   1175 
   1176 	if (order) {
   1177 		if (TC_U32_NODE(t->tcm_handle) &&
   1178 		    order != TC_U32_NODE(t->tcm_handle)) {
   1179 			fprintf(stderr, "\"order\" contradicts \"handle\"\n");
   1180 			return -1;
   1181 		}
   1182 		t->tcm_handle |= order;
   1183 	}
   1184 
   1185 	if (htid)
   1186 		addattr_l(n, MAX_MSG, TCA_U32_HASH, &htid, 4);
   1187 	if (sel_ok)
   1188 		addattr_l(n, MAX_MSG, TCA_U32_SEL, &sel,
   1189 			  sizeof(sel.sel) +
   1190 			  sel.sel.nkeys * sizeof(struct tc_u32_key));
   1191 	if (flags) {
   1192 		if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW |
   1193 			       TCA_CLS_FLAGS_SKIP_SW))) {
   1194 			fprintf(stderr,
   1195 				"skip_hw and skip_sw are mutually exclusive\n");
   1196 			return -1;
   1197 		}
   1198 		addattr_l(n, MAX_MSG, TCA_U32_FLAGS, &flags, 4);
   1199 	}
   1200 
   1201 	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
   1202 	return 0;
   1203 }
   1204 
   1205 static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
   1206 			 __u32 handle)
   1207 {
   1208 	struct rtattr *tb[TCA_U32_MAX + 1];
   1209 	struct tc_u32_sel *sel = NULL;
   1210 	struct tc_u32_pcnt *pf = NULL;
   1211 
   1212 	if (opt == NULL)
   1213 		return 0;
   1214 
   1215 	parse_rtattr_nested(tb, TCA_U32_MAX, opt);
   1216 
   1217 	if (handle) {
   1218 		SPRINT_BUF(b1);
   1219 		fprintf(f, "fh %s ", sprint_u32_handle(handle, b1));
   1220 	}
   1221 
   1222 	if (TC_U32_NODE(handle))
   1223 		fprintf(f, "order %d ", TC_U32_NODE(handle));
   1224 
   1225 	if (tb[TCA_U32_SEL]) {
   1226 		if (RTA_PAYLOAD(tb[TCA_U32_SEL])  < sizeof(*sel))
   1227 			return -1;
   1228 
   1229 		sel = RTA_DATA(tb[TCA_U32_SEL]);
   1230 	}
   1231 
   1232 	if (tb[TCA_U32_DIVISOR]) {
   1233 		fprintf(f, "ht divisor %d ",
   1234 			rta_getattr_u32(tb[TCA_U32_DIVISOR]));
   1235 	} else if (tb[TCA_U32_HASH]) {
   1236 		__u32 htid = rta_getattr_u32(tb[TCA_U32_HASH]);
   1237 
   1238 		fprintf(f, "key ht %x bkt %x ", TC_U32_USERHTID(htid),
   1239 			TC_U32_HASH(htid));
   1240 	} else {
   1241 		fprintf(f, "??? ");
   1242 	}
   1243 	if (tb[TCA_U32_CLASSID]) {
   1244 		SPRINT_BUF(b1);
   1245 		fprintf(f, "%sflowid %s ",
   1246 			!sel || !(sel->flags & TC_U32_TERMINAL) ? "*" : "",
   1247 			sprint_tc_classid(rta_getattr_u32(tb[TCA_U32_CLASSID]),
   1248 					  b1));
   1249 	} else if (sel && sel->flags & TC_U32_TERMINAL) {
   1250 		fprintf(f, "terminal flowid ??? ");
   1251 	}
   1252 	if (tb[TCA_U32_LINK]) {
   1253 		SPRINT_BUF(b1);
   1254 		fprintf(f, "link %s ",
   1255 			sprint_u32_handle(rta_getattr_u32(tb[TCA_U32_LINK]),
   1256 					  b1));
   1257 	}
   1258 
   1259 	if (tb[TCA_U32_FLAGS]) {
   1260 		__u32 flags = rta_getattr_u32(tb[TCA_U32_FLAGS]);
   1261 
   1262 		if (flags & TCA_CLS_FLAGS_SKIP_HW)
   1263 			fprintf(f, "skip_hw ");
   1264 		if (flags & TCA_CLS_FLAGS_SKIP_SW)
   1265 			fprintf(f, "skip_sw ");
   1266 
   1267 		if (flags & TCA_CLS_FLAGS_IN_HW)
   1268 			fprintf(f, "in_hw ");
   1269 		else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
   1270 			fprintf(f, "not_in_hw ");
   1271 	}
   1272 
   1273 	if (tb[TCA_U32_PCNT]) {
   1274 		if (RTA_PAYLOAD(tb[TCA_U32_PCNT])  < sizeof(*pf)) {
   1275 			fprintf(f, "Broken perf counters\n");
   1276 			return -1;
   1277 		}
   1278 		pf = RTA_DATA(tb[TCA_U32_PCNT]);
   1279 	}
   1280 
   1281 	if (sel && show_stats && NULL != pf)
   1282 		fprintf(f, " (rule hit %llu success %llu)",
   1283 			(unsigned long long) pf->rcnt,
   1284 			(unsigned long long) pf->rhit);
   1285 
   1286 	if (tb[TCA_U32_MARK]) {
   1287 		struct tc_u32_mark *mark = RTA_DATA(tb[TCA_U32_MARK]);
   1288 
   1289 		if (RTA_PAYLOAD(tb[TCA_U32_MARK]) < sizeof(*mark)) {
   1290 			fprintf(f, "\n  Invalid mark (kernel&iproute2 mismatch)\n");
   1291 		} else {
   1292 			fprintf(f, "\n  mark 0x%04x 0x%04x (success %d)",
   1293 				mark->val, mark->mask, mark->success);
   1294 		}
   1295 	}
   1296 
   1297 	if (sel) {
   1298 		if (sel->nkeys) {
   1299 			int i;
   1300 
   1301 			for (i = 0; i < sel->nkeys; i++) {
   1302 				show_keys(f, sel->keys + i);
   1303 				if (show_stats && NULL != pf)
   1304 					fprintf(f, " (success %llu ) ",
   1305 						(unsigned long long) pf->kcnts[i]);
   1306 			}
   1307 		}
   1308 
   1309 		if (sel->flags & (TC_U32_VAROFFSET | TC_U32_OFFSET)) {
   1310 			fprintf(f, "\n    offset ");
   1311 			if (sel->flags & TC_U32_VAROFFSET)
   1312 				fprintf(f, "%04x>>%d at %d ",
   1313 					ntohs(sel->offmask),
   1314 					sel->offshift,  sel->offoff);
   1315 			if (sel->off)
   1316 				fprintf(f, "plus %d ", sel->off);
   1317 		}
   1318 		if (sel->flags & TC_U32_EAT)
   1319 			fprintf(f, " eat ");
   1320 
   1321 		if (sel->hmask) {
   1322 			fprintf(f, "\n    hash mask %08x at %d ",
   1323 				(unsigned int)htonl(sel->hmask), sel->hoff);
   1324 		}
   1325 	}
   1326 
   1327 	if (tb[TCA_U32_POLICE]) {
   1328 		fprintf(f, "\n");
   1329 		tc_print_police(f, tb[TCA_U32_POLICE]);
   1330 	}
   1331 
   1332 	if (tb[TCA_U32_INDEV]) {
   1333 		struct rtattr *idev = tb[TCA_U32_INDEV];
   1334 
   1335 		fprintf(f, "\n  input dev %s\n", rta_getattr_str(idev));
   1336 	}
   1337 
   1338 	if (tb[TCA_U32_ACT])
   1339 		tc_print_action(f, tb[TCA_U32_ACT], 0);
   1340 
   1341 	return 0;
   1342 }
   1343 
   1344 struct filter_util u32_filter_util = {
   1345 	.id = "u32",
   1346 	.parse_fopt = u32_parse_opt,
   1347 	.print_fopt = u32_print_opt,
   1348 };
   1349