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