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@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
25#include "utils.h"
26#include "tc_util.h"
27
28static void explain(void)
29{
30	fprintf(stderr, "Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]\n");
31	fprintf(stderr, "               [ police POLICE_SPEC ] [ offset OFFSET_SPEC ]\n");
32	fprintf(stderr, "               [ ht HTID ] [ hashkey HASHKEY_SPEC ]\n");
33	fprintf(stderr, "               [ sample SAMPLE ]\n");
34	fprintf(stderr, "or         u32 divisor DIVISOR\n");
35	fprintf(stderr, "\n");
36	fprintf(stderr, "Where: SELECTOR := SAMPLE SAMPLE ...\n");
37	fprintf(stderr, "       SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark } SAMPLE_ARGS\n");
38	fprintf(stderr, "       FILTERID := X:Y:Z\n");
39}
40
41#define usage() return(-1)
42
43int get_u32_handle(__u32 *handle, char *str)
44{
45	__u32 htid=0, hash=0, nodeid=0;
46	char *tmp = strchr(str, ':');
47
48	if (tmp == NULL) {
49		if (memcmp("0x", str, 2) == 0)
50			return get_u32(handle, str, 16);
51		return -1;
52	}
53	htid = strtoul(str, &tmp, 16);
54	if (tmp == str && *str != ':' && *str != 0)
55		return -1;
56	if (htid>=0x1000)
57		return -1;
58	if (*tmp) {
59		str = tmp+1;
60		hash = strtoul(str, &tmp, 16);
61		if (tmp == str && *str != ':' && *str != 0)
62			return -1;
63		if (hash>=0x100)
64			return -1;
65		if (*tmp) {
66			str = tmp+1;
67			nodeid = strtoul(str, &tmp, 16);
68			if (tmp == str && *str != 0)
69				return -1;
70			if (nodeid>=0x1000)
71				return -1;
72		}
73	}
74	*handle = (htid<<20)|(hash<<12)|nodeid;
75	return 0;
76}
77
78char * sprint_u32_handle(__u32 handle, char *buf)
79{
80	int bsize = SPRINT_BSIZE-1;
81	__u32 htid = TC_U32_HTID(handle);
82	__u32 hash = TC_U32_HASH(handle);
83	__u32 nodeid = TC_U32_NODE(handle);
84	char *b = buf;
85
86	if (handle == 0) {
87		snprintf(b, bsize, "none");
88		return b;
89	}
90	if (htid) {
91		int l = snprintf(b, bsize, "%x:", htid>>20);
92		bsize -= l;
93		b += l;
94	}
95	if (nodeid|hash) {
96		if (hash) {
97			int l = snprintf(b, bsize, "%x", hash);
98			bsize -= l;
99			b += l;
100		}
101		if (nodeid) {
102			int l = snprintf(b, bsize, ":%x", nodeid);
103			bsize -= l;
104			b += l;
105		}
106	}
107	if (show_raw)
108		snprintf(b, bsize, "[%08x] ", handle);
109	return buf;
110}
111
112static int pack_key(struct tc_u32_sel *sel, __u32 key, __u32 mask, int off, int offmask)
113{
114	int i;
115	int hwm = sel->nkeys;
116
117	key &= mask;
118
119	for (i=0; i<hwm; i++) {
120		if (sel->keys[i].off == off && sel->keys[i].offmask == offmask) {
121			__u32 intersect = mask&sel->keys[i].mask;
122
123			if ((key^sel->keys[i].val) & intersect)
124				return -1;
125			sel->keys[i].val |= key;
126			sel->keys[i].mask |= mask;
127			return 0;
128		}
129	}
130
131	if (hwm >= 128)
132		return -1;
133	if (off % 4)
134		return -1;
135	sel->keys[hwm].val = key;
136	sel->keys[hwm].mask = mask;
137	sel->keys[hwm].off = off;
138	sel->keys[hwm].offmask = offmask;
139	sel->nkeys++;
140	return 0;
141}
142
143static int pack_key32(struct tc_u32_sel *sel, __u32 key, __u32 mask, int off, int offmask)
144{
145	key = htonl(key);
146	mask = htonl(mask);
147	return pack_key(sel, key, mask, off, offmask);
148}
149
150static int pack_key16(struct tc_u32_sel *sel, __u32 key, __u32 mask, int off, int offmask)
151{
152	if (key > 0xFFFF || mask > 0xFFFF)
153		return -1;
154
155	if ((off & 3) == 0) {
156		key <<= 16;
157		mask <<= 16;
158	}
159	off &= ~3;
160	key = htonl(key);
161	mask = htonl(mask);
162
163	return pack_key(sel, key, mask, off, offmask);
164}
165
166static int pack_key8(struct tc_u32_sel *sel, __u32 key, __u32 mask, int off, int offmask)
167{
168	if (key > 0xFF || mask > 0xFF)
169		return -1;
170
171	if ((off & 3) == 0) {
172		key <<= 24;
173		mask <<= 24;
174	} else if ((off & 3) == 1) {
175		key <<= 16;
176		mask <<= 16;
177	} else if ((off & 3) == 2) {
178		key <<= 8;
179		mask <<= 8;
180	}
181	off &= ~3;
182	key = htonl(key);
183	mask = htonl(mask);
184
185	return pack_key(sel, key, mask, off, offmask);
186}
187
188
189int parse_at(int *argc_p, char ***argv_p, int *off, int *offmask)
190{
191	int argc = *argc_p;
192	char **argv = *argv_p;
193	char *p = *argv;
194
195	if (argc <= 0)
196		return -1;
197
198	if (strlen(p) > strlen("nexthdr+") &&
199	    memcmp(p, "nexthdr+", strlen("nexthdr+")) == 0) {
200		*offmask = -1;
201		p += strlen("nexthdr+");
202	} else if (matches(*argv, "nexthdr+") == 0) {
203		NEXT_ARG();
204		*offmask = -1;
205		p = *argv;
206	}
207
208	if (get_integer(off, p, 0))
209		return -1;
210	argc--; argv++;
211
212	*argc_p = argc;
213	*argv_p = argv;
214	return 0;
215}
216
217
218static int parse_u32(int *argc_p, char ***argv_p, struct tc_u32_sel *sel, int off, int offmask)
219{
220	int res = -1;
221	int argc = *argc_p;
222	char **argv = *argv_p;
223	__u32 key;
224	__u32 mask;
225
226	if (argc < 2)
227		return -1;
228
229	if (get_u32(&key, *argv, 0))
230		return -1;
231	argc--; argv++;
232
233	if (get_u32(&mask, *argv, 16))
234		return -1;
235	argc--; argv++;
236
237	if (argc > 0 && strcmp(argv[0], "at") == 0) {
238		NEXT_ARG();
239		if (parse_at(&argc, &argv, &off, &offmask))
240			return -1;
241	}
242
243	res = pack_key32(sel, key, mask, off, offmask);
244	*argc_p = argc;
245	*argv_p = argv;
246	return res;
247}
248
249static int parse_u16(int *argc_p, char ***argv_p, struct tc_u32_sel *sel, int off, int offmask)
250{
251	int res = -1;
252	int argc = *argc_p;
253	char **argv = *argv_p;
254	__u32 key;
255	__u32 mask;
256
257	if (argc < 2)
258		return -1;
259
260	if (get_u32(&key, *argv, 0))
261		return -1;
262	argc--; argv++;
263
264	if (get_u32(&mask, *argv, 16))
265		return -1;
266	argc--; argv++;
267
268	if (argc > 0 && strcmp(argv[0], "at") == 0) {
269		NEXT_ARG();
270		if (parse_at(&argc, &argv, &off, &offmask))
271			return -1;
272	}
273	res = pack_key16(sel, key, mask, off, offmask);
274	*argc_p = argc;
275	*argv_p = argv;
276	return res;
277}
278
279static int parse_u8(int *argc_p, char ***argv_p, struct tc_u32_sel *sel, int off, int offmask)
280{
281	int res = -1;
282	int argc = *argc_p;
283	char **argv = *argv_p;
284	__u32 key;
285	__u32 mask;
286
287	if (argc < 2)
288		return -1;
289
290	if (get_u32(&key, *argv, 0))
291		return -1;
292	argc--; argv++;
293
294	if (get_u32(&mask, *argv, 16))
295		return -1;
296	argc--; argv++;
297
298	if (key > 0xFF || mask > 0xFF)
299		return -1;
300
301	if (argc > 0 && strcmp(argv[0], "at") == 0) {
302		NEXT_ARG();
303		if (parse_at(&argc, &argv, &off, &offmask))
304			return -1;
305	}
306
307	res = pack_key8(sel, key, mask, off, offmask);
308	*argc_p = argc;
309	*argv_p = argv;
310	return res;
311}
312
313static int parse_ip_addr(int *argc_p, char ***argv_p, struct tc_u32_sel *sel, int off)
314{
315	int res = -1;
316	int argc = *argc_p;
317	char **argv = *argv_p;
318	inet_prefix addr;
319	__u32 mask;
320	int offmask = 0;
321
322	if (argc < 1)
323		return -1;
324
325	if (get_prefix_1(&addr, *argv, AF_INET))
326		return -1;
327	argc--; argv++;
328
329	if (argc > 0 && strcmp(argv[0], "at") == 0) {
330		NEXT_ARG();
331		if (parse_at(&argc, &argv, &off, &offmask))
332			return -1;
333	}
334
335	mask = 0;
336	if (addr.bitlen)
337		mask = htonl(0xFFFFFFFF<<(32-addr.bitlen));
338	if (pack_key(sel, addr.data[0], mask, off, offmask) < 0)
339		return -1;
340	res = 0;
341
342	*argc_p = argc;
343	*argv_p = argv;
344	return res;
345}
346
347static int parse_ip6_addr(int *argc_p, char ***argv_p, struct tc_u32_sel *sel, int off)
348{
349	int res = -1;
350	int argc = *argc_p;
351	char **argv = *argv_p;
352	int plen = 128;
353	int i;
354	inet_prefix addr;
355	int offmask = 0;
356
357	if (argc < 1)
358		return -1;
359
360	if (get_prefix_1(&addr, *argv, AF_INET6))
361		return -1;
362	argc--; argv++;
363
364	if (argc > 0 && strcmp(argv[0], "at") == 0) {
365		NEXT_ARG();
366		if (parse_at(&argc, &argv, &off, &offmask))
367			return -1;
368	}
369
370	plen = addr.bitlen;
371	for (i=0; i<plen; i+=32) {
372//		if (((i+31)&~0x1F)<=plen) {
373		if (((i+31))<=plen) {
374			if ((res = pack_key(sel, addr.data[i/32], 0xFFFFFFFF, off+4*(i/32), offmask)) < 0)
375				return -1;
376		} else if (i<plen) {
377			__u32 mask = htonl(0xFFFFFFFF<<(32-(plen-i)));
378			if ((res = pack_key(sel, addr.data[i/32], mask, off+4*(i/32), offmask)) < 0)
379				return -1;
380		}
381	}
382	res = 0;
383
384	*argc_p = argc;
385	*argv_p = argv;
386	return res;
387}
388
389static int parse_ip(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
390{
391	int res = -1;
392	int argc = *argc_p;
393	char **argv = *argv_p;
394
395	if (argc < 2)
396		return -1;
397
398	if (strcmp(*argv, "src") == 0) {
399		NEXT_ARG();
400		res = parse_ip_addr(&argc, &argv, sel, 12);
401		goto done;
402	}
403	if (strcmp(*argv, "dst") == 0) {
404		NEXT_ARG();
405		res = parse_ip_addr(&argc, &argv, sel, 16);
406		goto done;
407	}
408	if (strcmp(*argv, "tos") == 0 ||
409	    matches(*argv, "dsfield") == 0) {
410		NEXT_ARG();
411		res = parse_u8(&argc, &argv, sel, 1, 0);
412		goto done;
413	}
414	if (strcmp(*argv, "ihl") == 0) {
415		NEXT_ARG();
416		res = parse_u8(&argc, &argv, sel, 0, 0);
417		goto done;
418	}
419	if (strcmp(*argv, "protocol") == 0) {
420		NEXT_ARG();
421		res = parse_u8(&argc, &argv, sel, 9, 0);
422		goto done;
423	}
424	if (matches(*argv, "precedence") == 0) {
425		NEXT_ARG();
426		res = parse_u8(&argc, &argv, sel, 1, 0);
427		goto done;
428	}
429	if (strcmp(*argv, "nofrag") == 0) {
430		argc--; argv++;
431		res = pack_key16(sel, 0, 0x3FFF, 6, 0);
432		goto done;
433	}
434	if (strcmp(*argv, "firstfrag") == 0) {
435		argc--; argv++;
436		res = pack_key16(sel, 0, 0x1FFF, 6, 0);
437		goto done;
438	}
439	if (strcmp(*argv, "df") == 0) {
440		argc--; argv++;
441		res = pack_key16(sel, 0x4000, 0x4000, 6, 0);
442		goto done;
443	}
444	if (strcmp(*argv, "mf") == 0) {
445		argc--; argv++;
446		res = pack_key16(sel, 0x2000, 0x2000, 6, 0);
447		goto done;
448	}
449	if (strcmp(*argv, "dport") == 0) {
450		NEXT_ARG();
451		res = parse_u16(&argc, &argv, sel, 22, 0);
452		goto done;
453	}
454	if (strcmp(*argv, "sport") == 0) {
455		NEXT_ARG();
456		res = parse_u16(&argc, &argv, sel, 20, 0);
457		goto done;
458	}
459	if (strcmp(*argv, "icmp_type") == 0) {
460		NEXT_ARG();
461		res = parse_u8(&argc, &argv, sel, 20, 0);
462		goto done;
463	}
464	if (strcmp(*argv, "icmp_code") == 0) {
465		NEXT_ARG();
466		res = parse_u8(&argc, &argv, sel, 20, 1);
467		goto done;
468	}
469	return -1;
470
471done:
472	*argc_p = argc;
473	*argv_p = argv;
474	return res;
475}
476
477static int parse_ip6(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
478{
479	int res = -1;
480	int argc = *argc_p;
481	char **argv = *argv_p;
482
483	if (argc < 2)
484		return -1;
485
486	if (strcmp(*argv, "src") == 0) {
487		NEXT_ARG();
488		res = parse_ip6_addr(&argc, &argv, sel, 8);
489		goto done;
490	}
491	if (strcmp(*argv, "dst") == 0) {
492		NEXT_ARG();
493		res = parse_ip6_addr(&argc, &argv, sel, 24);
494		goto done;
495	}
496	if (strcmp(*argv, "priority") == 0) {
497		NEXT_ARG();
498		res = parse_u8(&argc, &argv, sel, 0, 0);
499		goto done;
500	}
501	if (strcmp(*argv, "protocol") == 0) {
502		NEXT_ARG();
503		res = parse_u8(&argc, &argv, sel, 6, 0);
504		goto done;
505	}
506	if (strcmp(*argv, "flowlabel") == 0) {
507		NEXT_ARG();
508		res = parse_u32(&argc, &argv, sel, 0, 0);
509		goto done;
510	}
511	if (strcmp(*argv, "dport") == 0) {
512		NEXT_ARG();
513		res = parse_u16(&argc, &argv, sel, 42, 0);
514		goto done;
515	}
516	if (strcmp(*argv, "sport") == 0) {
517		NEXT_ARG();
518		res = parse_u16(&argc, &argv, sel, 40, 0);
519		goto done;
520	}
521	if (strcmp(*argv, "icmp_type") == 0) {
522		NEXT_ARG();
523		res = parse_u8(&argc, &argv, sel, 40, 0);
524		goto done;
525	}
526	if (strcmp(*argv, "icmp_code") == 0) {
527		NEXT_ARG();
528		res = parse_u8(&argc, &argv, sel, 41, 1);
529		goto done;
530	}
531	return -1;
532
533done:
534	*argc_p = argc;
535	*argv_p = argv;
536	return res;
537}
538
539#define parse_tcp parse_udp
540static int parse_udp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
541{
542	int res = -1;
543	int argc = *argc_p;
544	char **argv = *argv_p;
545
546	if (argc < 2)
547		return -1;
548
549	if (strcmp(*argv, "src") == 0) {
550		NEXT_ARG();
551		res = parse_u16(&argc, &argv, sel, 0, -1);
552		goto done;
553	}
554	if (strcmp(*argv, "dst") == 0) {
555		NEXT_ARG();
556		res = parse_u16(&argc, &argv, sel, 2, -1);
557		goto done;
558	}
559	return -1;
560
561done:
562	*argc_p = argc;
563	*argv_p = argv;
564	return res;
565}
566
567static int parse_icmp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
568{
569	int res = -1;
570	int argc = *argc_p;
571	char **argv = *argv_p;
572
573	if (argc < 2)
574		return -1;
575
576	if (strcmp(*argv, "type") == 0) {
577		NEXT_ARG();
578		res = parse_u8(&argc, &argv, sel, 0, -1);
579		goto done;
580	}
581	if (strcmp(*argv, "code") == 0) {
582		NEXT_ARG();
583		res = parse_u8(&argc, &argv, sel, 1, -1);
584		goto done;
585	}
586	return -1;
587
588done:
589	*argc_p = argc;
590	*argv_p = argv;
591	return res;
592}
593
594static int parse_mark(int *argc_p, char ***argv_p, struct nlmsghdr *n)
595{
596	int res = -1;
597	int argc = *argc_p;
598	char **argv = *argv_p;
599	struct tc_u32_mark mark;
600
601	if (argc <= 1)
602		return -1;
603
604	if (get_u32(&mark.val, *argv, 0)) {
605		fprintf(stderr, "Illegal \"mark\" value\n");
606		return -1;
607	}
608	NEXT_ARG();
609
610	if (get_u32(&mark.mask, *argv, 0)) {
611		fprintf(stderr, "Illegal \"mark\" mask\n");
612		return -1;
613	}
614	NEXT_ARG();
615
616	if ((mark.val & mark.mask) != mark.val) {
617		fprintf(stderr, "Illegal \"mark\" (impossible combination)\n");
618		return -1;
619	}
620
621	addattr_l(n, MAX_MSG, TCA_U32_MARK, &mark, sizeof(mark));
622	res = 0;
623
624	*argc_p = argc;
625	*argv_p = argv;
626	return res;
627}
628
629static int parse_selector(int *argc_p, char ***argv_p, struct tc_u32_sel *sel, struct nlmsghdr *n)
630{
631	int argc = *argc_p;
632	char **argv = *argv_p;
633	int res = -1;
634
635	if (argc <= 0)
636		return -1;
637
638	if (matches(*argv, "u32") == 0) {
639		NEXT_ARG();
640		res = parse_u32(&argc, &argv, sel, 0, 0);
641		goto done;
642	}
643	if (matches(*argv, "u16") == 0) {
644		NEXT_ARG();
645		res = parse_u16(&argc, &argv, sel, 0, 0);
646		goto done;
647	}
648	if (matches(*argv, "u8") == 0) {
649		NEXT_ARG();
650		res = parse_u8(&argc, &argv, sel, 0, 0);
651		goto done;
652	}
653	if (matches(*argv, "ip") == 0) {
654		NEXT_ARG();
655		res = parse_ip(&argc, &argv, sel);
656		goto done;
657	}
658	if (matches(*argv, "ip6") == 0) {
659		NEXT_ARG();
660		res = parse_ip6(&argc, &argv, sel);
661		goto done;
662	}
663	if (matches(*argv, "udp") == 0) {
664		NEXT_ARG();
665		res = parse_udp(&argc, &argv, sel);
666		goto done;
667	}
668	if (matches(*argv, "tcp") == 0) {
669		NEXT_ARG();
670		res = parse_tcp(&argc, &argv, sel);
671		goto done;
672	}
673	if (matches(*argv, "icmp") == 0) {
674		NEXT_ARG();
675		res = parse_icmp(&argc, &argv, sel);
676		goto done;
677	}
678	if (matches(*argv, "mark") == 0) {
679		NEXT_ARG();
680		res = parse_mark(&argc, &argv, n);
681		goto done;
682	}
683
684	return -1;
685
686done:
687	*argc_p = argc;
688	*argv_p = argv;
689	return res;
690}
691
692static int parse_offset(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
693{
694	int argc = *argc_p;
695	char **argv = *argv_p;
696
697	while (argc > 0) {
698		if (matches(*argv, "plus") == 0) {
699			int off;
700			NEXT_ARG();
701			if (get_integer(&off, *argv, 0))
702				return -1;
703			sel->off = off;
704			sel->flags |= TC_U32_OFFSET;
705		} else if (matches(*argv, "at") == 0) {
706			int off;
707			NEXT_ARG();
708			if (get_integer(&off, *argv, 0))
709				return -1;
710			sel->offoff = off;
711			if (off%2) {
712				fprintf(stderr, "offset \"at\" must be even\n");
713				return -1;
714			}
715			sel->flags |= TC_U32_VAROFFSET;
716		} else if (matches(*argv, "mask") == 0) {
717			__u16 mask;
718			NEXT_ARG();
719			if (get_u16(&mask, *argv, 16))
720				return -1;
721			sel->offmask = htons(mask);
722			sel->flags |= TC_U32_VAROFFSET;
723		} else if (matches(*argv, "shift") == 0) {
724			int shift;
725			NEXT_ARG();
726			if (get_integer(&shift, *argv, 0))
727				return -1;
728			sel->offshift = shift;
729			sel->flags |= TC_U32_VAROFFSET;
730		} else if (matches(*argv, "eat") == 0) {
731			sel->flags |= TC_U32_EAT;
732		} else {
733			break;
734		}
735		argc--; argv++;
736	}
737
738	*argc_p = argc;
739	*argv_p = argv;
740	return 0;
741}
742
743static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
744{
745	int argc = *argc_p;
746	char **argv = *argv_p;
747
748	while (argc > 0) {
749		if (matches(*argv, "mask") == 0) {
750			__u32 mask;
751			NEXT_ARG();
752			if (get_u32(&mask, *argv, 16))
753				return -1;
754			sel->hmask = htonl(mask);
755		} else if (matches(*argv, "at") == 0) {
756			int num;
757			NEXT_ARG();
758			if (get_integer(&num, *argv, 0))
759				return -1;
760			if (num%4)
761				return -1;
762			sel->hoff = num;
763		} else {
764			break;
765		}
766		argc--; argv++;
767	}
768
769	*argc_p = argc;
770	*argv_p = argv;
771	return 0;
772}
773
774static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
775{
776	struct {
777		struct tc_u32_sel sel;
778		struct tc_u32_key keys[128];
779	} sel;
780	struct tcmsg *t = NLMSG_DATA(n);
781	struct rtattr *tail;
782	int sel_ok = 0;
783	int sample_ok = 0;
784	__u32 htid = 0;
785	__u32 order = 0;
786
787	memset(&sel, 0, sizeof(sel));
788
789	if (handle && get_u32_handle(&t->tcm_handle, handle)) {
790		fprintf(stderr, "Illegal filter ID\n");
791		return -1;
792	}
793
794	if (argc == 0)
795		return 0;
796
797	tail = NLMSG_TAIL(n);
798	addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
799
800	while (argc > 0) {
801		if (matches(*argv, "match") == 0) {
802			NEXT_ARG();
803			if (parse_selector(&argc, &argv, &sel.sel, n)) {
804				fprintf(stderr, "Illegal \"match\"\n");
805				return -1;
806			}
807			sel_ok++;
808			continue;
809		} else if (matches(*argv, "offset") == 0) {
810			NEXT_ARG();
811			if (parse_offset(&argc, &argv, &sel.sel)) {
812				fprintf(stderr, "Illegal \"offset\"\n");
813				return -1;
814			}
815			continue;
816		} else if (matches(*argv, "hashkey") == 0) {
817			NEXT_ARG();
818			if (parse_hashkey(&argc, &argv, &sel.sel)) {
819				fprintf(stderr, "Illegal \"hashkey\"\n");
820				return -1;
821			}
822			continue;
823		} else if (matches(*argv, "classid") == 0 ||
824			   strcmp(*argv, "flowid") == 0) {
825			unsigned handle;
826			NEXT_ARG();
827			if (get_tc_classid(&handle, *argv)) {
828				fprintf(stderr, "Illegal \"classid\"\n");
829				return -1;
830			}
831			addattr_l(n, MAX_MSG, TCA_U32_CLASSID, &handle, 4);
832			sel.sel.flags |= TC_U32_TERMINAL;
833		} else if (matches(*argv, "divisor") == 0) {
834			unsigned divisor;
835			NEXT_ARG();
836			if (get_unsigned(&divisor, *argv, 0) || divisor == 0 ||
837			    divisor > 0x100) {
838				fprintf(stderr, "Illegal \"divisor\"\n");
839				return -1;
840			}
841			addattr_l(n, MAX_MSG, TCA_U32_DIVISOR, &divisor, 4);
842		} else if (matches(*argv, "order") == 0) {
843			NEXT_ARG();
844			if (get_u32(&order, *argv, 0)) {
845				fprintf(stderr, "Illegal \"order\"\n");
846				return -1;
847			}
848		} else if (strcmp(*argv, "link") == 0) {
849			unsigned handle;
850			NEXT_ARG();
851			if (get_u32_handle(&handle, *argv)) {
852				fprintf(stderr, "Illegal \"link\"\n");
853				return -1;
854			}
855			if (handle && TC_U32_NODE(handle)) {
856				fprintf(stderr, "\"link\" must be a hash table.\n");
857				return -1;
858			}
859			addattr_l(n, MAX_MSG, TCA_U32_LINK, &handle, 4);
860		} else if (strcmp(*argv, "ht") == 0) {
861			unsigned handle;
862			NEXT_ARG();
863			if (get_u32_handle(&handle, *argv)) {
864				fprintf(stderr, "Illegal \"ht\"\n");
865				return -1;
866			}
867			if (handle && TC_U32_NODE(handle)) {
868				fprintf(stderr, "\"ht\" must be a hash table.\n");
869				return -1;
870			}
871			if (sample_ok)
872				htid = (htid&0xFF000)|(handle&0xFFF00000);
873			else
874				htid = (handle&0xFFFFF000);
875		} else if (strcmp(*argv, "sample") == 0) {
876			__u32 hash;
877			struct {
878				struct tc_u32_sel sel;
879				struct tc_u32_key keys[4];
880			} sel2;
881			NEXT_ARG();
882			if (parse_selector(&argc, &argv, &sel2.sel, n)) {
883				fprintf(stderr, "Illegal \"sample\"\n");
884				return -1;
885			}
886			if (sel2.sel.nkeys != 1) {
887				fprintf(stderr, "\"sample\" must contain exactly ONE key.\n");
888				return -1;
889			}
890			hash = sel2.sel.keys[0].val&sel2.sel.keys[0].mask;
891			hash ^= hash>>16;
892			hash ^= hash>>8;
893			htid = ((hash<<12)&0xFF000)|(htid&0xFFF00000);
894			sample_ok = 1;
895			continue;
896		} else if (strcmp(*argv, "indev") == 0) {
897			char ind[IFNAMSIZ + 1];
898			memset(ind, 0, sizeof (ind));
899			argc--;
900			argv++;
901			if (argc < 1) {
902				fprintf(stderr, "Illegal indev\n");
903				return -1;
904			}
905			strncpy(ind, *argv, sizeof (ind) - 1);
906			addattr_l(n, MAX_MSG, TCA_U32_INDEV, ind, strlen(ind) + 1);
907
908		} else if (matches(*argv, "action") == 0) {
909			NEXT_ARG();
910			if (parse_action(&argc, &argv, TCA_U32_ACT, n)) {
911				fprintf(stderr, "Illegal \"action\"\n");
912				return -1;
913			}
914			continue;
915
916		} else if (matches(*argv, "police") == 0) {
917			NEXT_ARG();
918			if (parse_police(&argc, &argv, TCA_U32_POLICE, n)) {
919				fprintf(stderr, "Illegal \"police\"\n");
920				return -1;
921			}
922			continue;
923		} else if (strcmp(*argv, "help") == 0) {
924			explain();
925			return -1;
926		} else {
927			fprintf(stderr, "What is \"%s\"?\n", *argv);
928			explain();
929			return -1;
930		}
931		argc--; argv++;
932	}
933
934	if (order) {
935		if (TC_U32_NODE(t->tcm_handle) && order != TC_U32_NODE(t->tcm_handle)) {
936			fprintf(stderr, "\"order\" contradicts \"handle\"\n");
937			return -1;
938		}
939		t->tcm_handle |= order;
940	}
941
942	if (htid)
943		addattr_l(n, MAX_MSG, TCA_U32_HASH, &htid, 4);
944	if (sel_ok)
945		addattr_l(n, MAX_MSG, TCA_U32_SEL, &sel, sizeof(sel.sel)+sel.sel.nkeys*sizeof(struct tc_u32_key));
946	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
947	return 0;
948}
949
950static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle)
951{
952	struct rtattr *tb[TCA_U32_MAX+1];
953	struct tc_u32_sel *sel = NULL;
954	struct tc_u32_pcnt *pf = NULL;
955
956	if (opt == NULL)
957		return 0;
958
959	parse_rtattr_nested(tb, TCA_U32_MAX, opt);
960
961	if (handle) {
962		SPRINT_BUF(b1);
963		fprintf(f, "fh %s ", sprint_u32_handle(handle, b1));
964	}
965	if (TC_U32_NODE(handle)) {
966		fprintf(f, "order %d ", TC_U32_NODE(handle));
967	}
968
969	if (tb[TCA_U32_SEL]) {
970		if (RTA_PAYLOAD(tb[TCA_U32_SEL])  < sizeof(*sel))
971			return -1;
972
973		sel = RTA_DATA(tb[TCA_U32_SEL]);
974	}
975
976	if (tb[TCA_U32_DIVISOR]) {
977		fprintf(f, "ht divisor %d ", *(__u32*)RTA_DATA(tb[TCA_U32_DIVISOR]));
978	} else if (tb[TCA_U32_HASH]) {
979		__u32 htid = *(__u32*)RTA_DATA(tb[TCA_U32_HASH]);
980		fprintf(f, "key ht %x bkt %x ", TC_U32_USERHTID(htid), TC_U32_HASH(htid));
981	} else {
982		fprintf(f, "??? ");
983	}
984	if (tb[TCA_U32_CLASSID]) {
985		SPRINT_BUF(b1);
986		fprintf(f, "%sflowid %s ",
987			!sel || !(sel->flags&TC_U32_TERMINAL) ? "*" : "",
988			sprint_tc_classid(*(__u32*)RTA_DATA(tb[TCA_U32_CLASSID]), b1));
989	} else if (sel && sel->flags&TC_U32_TERMINAL) {
990		fprintf(f, "terminal flowid ??? ");
991	}
992	if (tb[TCA_U32_LINK]) {
993		SPRINT_BUF(b1);
994		fprintf(f, "link %s ", sprint_u32_handle(*(__u32*)RTA_DATA(tb[TCA_U32_LINK]), b1));
995	}
996
997	if (tb[TCA_U32_PCNT]) {
998		if (RTA_PAYLOAD(tb[TCA_U32_PCNT])  < sizeof(*pf)) {
999			fprintf(f, "Broken perf counters \n");
1000			return -1;
1001		}
1002		pf = RTA_DATA(tb[TCA_U32_PCNT]);
1003	}
1004
1005	if (sel && show_stats && NULL != pf)
1006		fprintf(f, " (rule hit %llu success %llu)",
1007			(unsigned long long) pf->rcnt,
1008			(unsigned long long) pf->rhit);
1009
1010	if (tb[TCA_U32_MARK]) {
1011		struct tc_u32_mark *mark = RTA_DATA(tb[TCA_U32_MARK]);
1012		if (RTA_PAYLOAD(tb[TCA_U32_MARK]) < sizeof(*mark)) {
1013			fprintf(f, "\n  Invalid mark (kernel&iproute2 mismatch)\n");
1014		} else {
1015			fprintf(f, "\n  mark 0x%04x 0x%04x (success %d)",
1016				mark->val, mark->mask, mark->success);
1017		}
1018	}
1019
1020	if (sel) {
1021		int i;
1022		struct tc_u32_key *key = sel->keys;
1023		if (sel->nkeys) {
1024			for (i=0; i<sel->nkeys; i++, key++) {
1025				fprintf(f, "\n  match %08x/%08x at %s%d",
1026					(unsigned int)ntohl(key->val),
1027					(unsigned int)ntohl(key->mask),
1028					key->offmask ? "nexthdr+" : "",
1029					key->off);
1030				if (show_stats && NULL != pf)
1031					fprintf(f, " (success %lld ) ",
1032						(unsigned long long) pf->kcnts[i]);
1033			}
1034		}
1035
1036		if (sel->flags&(TC_U32_VAROFFSET|TC_U32_OFFSET)) {
1037			fprintf(f, "\n    offset ");
1038			if (sel->flags&TC_U32_VAROFFSET)
1039				fprintf(f, "%04x>>%d at %d ", ntohs(sel->offmask), sel->offshift,  sel->offoff);
1040			if (sel->off)
1041				fprintf(f, "plus %d ", sel->off);
1042		}
1043		if (sel->flags&TC_U32_EAT)
1044			fprintf(f, " eat ");
1045
1046		if (sel->hmask) {
1047			fprintf(f, "\n    hash mask %08x at %d ",
1048				(unsigned int)htonl(sel->hmask), sel->hoff);
1049		}
1050	}
1051
1052	if (tb[TCA_U32_POLICE]) {
1053		fprintf(f, "\n");
1054		tc_print_police(f, tb[TCA_U32_POLICE]);
1055	}
1056	if (tb[TCA_U32_INDEV]) {
1057		struct rtattr *idev = tb[TCA_U32_INDEV];
1058		fprintf(f, "\n  input dev %s\n", (char *) RTA_DATA(idev));
1059	}
1060	if (tb[TCA_U32_ACT]) {
1061		tc_print_action(f, tb[TCA_U32_ACT]);
1062	}
1063
1064	return 0;
1065}
1066
1067struct filter_util u32_filter_util = {
1068	.id = "u32",
1069	.parse_fopt = u32_parse_opt,
1070	.print_fopt = u32_print_opt,
1071};
1072