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