tc.c revision c5b66ed439aab1843d40a629347852359ba2ae70
1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*
2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * tc.c		"tc" utility frontend.
3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		This program is free software; you can redistribute it and/or
5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		modify it under the terms of the GNU General Public License
6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		as published by the Free Software Foundation; either version
7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		2 of the License, or (at your option) any later version.
8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Fixes:
12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Petri Mattila <petri@prihateam.fi> 990308: wrong memset's resulted in faults
14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */
15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h>
17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h>
18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h>
19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <syslog.h>
20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h>
21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <dlfcn.h>
22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h>
23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netinet/in.h>
24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <arpa/inet.h>
25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h>
26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <errno.h>
27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "SNAPSHOT.h"
29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h"
30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tc_util.h"
31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tc_common.h"
32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint show_stats = 0;
34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint show_details = 0;
35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint show_raw = 0;
36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint show_pretty = 0;
37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint resolve_hosts = 0;
39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint use_iec = 0;
40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint force = 0;
41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct rtnl_handle rth;
42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void *BODY = NULL;	/* cached handle dlopen(NULL) */
44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct qdisc_util * qdisc_list;
45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct filter_util * filter_list;
46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
47b856938e2c00fefb701f906a90d545f92007ac96San Mehat#ifdef ANDROID
48b856938e2c00fefb701f906a90d545f92007ac96San Mehatextern struct qdisc_util cbq_qdisc_util;
49c5b66ed439aab1843d40a629347852359ba2ae70San Mehatextern struct qdisc_util ingress_qdisc_util;
50b856938e2c00fefb701f906a90d545f92007ac96San Mehatextern struct filter_util u32_filter_util;
51b856938e2c00fefb701f906a90d545f92007ac96San Mehat#endif
52b856938e2c00fefb701f906a90d545f92007ac96San Mehat
53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int print_noqopt(struct qdisc_util *qu, FILE *f,
54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			struct rtattr *opt)
55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (opt && RTA_PAYLOAD(opt))
57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "[Unknown qdisc, optlen=%u] ",
58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			(unsigned) RTA_PAYLOAD(opt));
59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int parse_noqopt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (argc) {
65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr, "Unknown qdisc \"%s\", hence option \"%s\" is unparsable\n", qu->id, *argv);
66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int print_nofopt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 fhandle)
72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (opt && RTA_PAYLOAD(opt))
74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "fh %08x [Unknown filter, optlen=%u] ",
75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fhandle, (unsigned) RTA_PAYLOAD(opt));
76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (fhandle)
77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "fh %08x ", fhandle);
78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int parse_nofopt(struct filter_util *qu, char *fhandle, int argc, char **argv, struct nlmsghdr *n)
82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	__u32 handle;
84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (argc) {
86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr, "Unknown filter \"%s\", hence option \"%s\" is unparsable\n", qu->id, *argv);
87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (fhandle) {
90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct tcmsg *t = NLMSG_DATA(n);
91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (get_u32(&handle, fhandle, 16)) {
92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, "Unparsable filter ID \"%s\"\n", fhandle);
93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		t->tcm_handle = handle;
96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct qdisc_util *get_qdisc_kind(const char *str)
101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	void *dlh;
103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char buf[256];
104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct qdisc_util *q;
105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
106b856938e2c00fefb701f906a90d545f92007ac96San Mehat#ifdef ANDROID
107b856938e2c00fefb701f906a90d545f92007ac96San Mehat	if (!strcmp(str, "cbq"))
108b856938e2c00fefb701f906a90d545f92007ac96San Mehat		return &cbq_qdisc_util;
109c5b66ed439aab1843d40a629347852359ba2ae70San Mehat	else if (!strcmp(str, "ingress"))
110c5b66ed439aab1843d40a629347852359ba2ae70San Mehat		return &ingress_qdisc_util;
111b856938e2c00fefb701f906a90d545f92007ac96San Mehat	else {
112b856938e2c00fefb701f906a90d545f92007ac96San Mehat		fprintf(stderr, "Android does not support '%s'\n", str);
113b856938e2c00fefb701f906a90d545f92007ac96San Mehat		return NULL;
114b856938e2c00fefb701f906a90d545f92007ac96San Mehat	}
115b856938e2c00fefb701f906a90d545f92007ac96San Mehat#endif
116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (q = qdisc_list; q; q = q->next)
117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (strcmp(q->id, str) == 0)
118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return q;
119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	snprintf(buf, sizeof(buf), "%s/q_%s.so", get_tc_lib(), str);
121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	dlh = dlopen(buf, RTLD_LAZY);
122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!dlh) {
123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		/* look in current binary, only open once */
124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		dlh = BODY;
125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (dlh == NULL) {
126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			dlh = BODY = dlopen(NULL, RTLD_LAZY);
127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (dlh == NULL)
128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				goto noexist;
129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	snprintf(buf, sizeof(buf), "%s_qdisc_util", str);
133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	q = dlsym(dlh, buf);
134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (q == NULL)
135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		goto noexist;
136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatreg:
138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	q->next = qdisc_list;
139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	qdisc_list = q;
140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return q;
141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatnoexist:
143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	q = malloc(sizeof(*q));
144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (q) {
145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memset(q, 0, sizeof(*q));
147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		q->id = strcpy(malloc(strlen(str)+1), str);
148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		q->parse_qopt = parse_noqopt;
149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		q->print_qopt = print_noqopt;
150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		goto reg;
151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return q;
153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct filter_util *get_filter_kind(const char *str)
157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	void *dlh;
159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char buf[256];
160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct filter_util *q;
161b856938e2c00fefb701f906a90d545f92007ac96San Mehat#ifdef ANDROID
162b856938e2c00fefb701f906a90d545f92007ac96San Mehat	if (!strcmp(str, "u32"))
163b856938e2c00fefb701f906a90d545f92007ac96San Mehat		return &u32_filter_util;
164b856938e2c00fefb701f906a90d545f92007ac96San Mehat	else {
165b856938e2c00fefb701f906a90d545f92007ac96San Mehat		fprintf(stderr, "Android does not support '%s'\n", str);
166b856938e2c00fefb701f906a90d545f92007ac96San Mehat		return NULL;
167b856938e2c00fefb701f906a90d545f92007ac96San Mehat	}
168b856938e2c00fefb701f906a90d545f92007ac96San Mehat#endif
169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (q = filter_list; q; q = q->next)
171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (strcmp(q->id, str) == 0)
172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return q;
173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	snprintf(buf, sizeof(buf), "%s/f_%s.so", get_tc_lib(), str);
175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	dlh = dlopen(buf, RTLD_LAZY);
176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (dlh == NULL) {
177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		dlh = BODY;
178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (dlh == NULL) {
179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			dlh = BODY = dlopen(NULL, RTLD_LAZY);
180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (dlh == NULL)
181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				goto noexist;
182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	snprintf(buf, sizeof(buf), "%s_filter_util", str);
186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	q = dlsym(dlh, buf);
187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (q == NULL)
188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		goto noexist;
189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatreg:
191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	q->next = filter_list;
192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	filter_list = q;
193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return q;
194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatnoexist:
195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	q = malloc(sizeof(*q));
196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (q) {
197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memset(q, 0, sizeof(*q));
198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		strncpy(q->id, str, 15);
199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		q->parse_fopt = parse_nofopt;
200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		q->print_fopt = print_nofopt;
201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		goto reg;
202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return q;
204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void usage(void)
207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr, "Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n"
209f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#ifdef ANDROID
210f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat			"       tc [-force]\n"
211f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#else
212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			"       tc [-force] -batch filename\n"
213f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#endif
214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	                "where  OBJECT := { qdisc | class | filter | action | monitor }\n"
215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	                "       OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -p[retty] | -b[atch] [filename] }\n");
216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int do_cmd(int argc, char **argv)
219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "qdisc") == 0)
221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return do_qdisc(argc-1, argv+1);
222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "class") == 0)
224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return do_class(argc-1, argv+1);
225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "filter") == 0)
227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return do_filter(argc-1, argv+1);
228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "actions") == 0)
230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return do_action(argc-1, argv+1);
231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "monitor") == 0)
233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return do_tcmonitor(argc-1, argv+1);
234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "help") == 0) {
236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		usage();
237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return 0;
238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr, "Object \"%s\" is unknown, try \"tc help\".\n",
241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*argv);
242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return -1;
243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
245f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#ifndef ANDROID
246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int batch(const char *name)
247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *line = NULL;
249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	size_t len = 0;
250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int ret = 0;
251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (name && strcmp(name, "-") != 0) {
253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (freopen(name, "r", stdin) == NULL) {
254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, "Cannot open file \"%s\" for reading: %s\n",
255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				name, strerror(errno));
256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tc_core_init();
261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (rtnl_open(&rth, 0) < 0) {
263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr, "Cannot open rtnetlink\n");
264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	cmdlineno = 0;
268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (getcmdline(&line, &len, stdin) != -1) {
269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		char *largv[100];
270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int largc;
271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		largc = makeargs(line, largv, 100);
273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (largc == 0)
274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;	/* blank line */
275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (do_cmd(largc, largv)) {
277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, "Command failed %s:%d\n", name, cmdlineno);
278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			ret = 1;
279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (!force)
280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				break;
281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (line)
284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		free(line);
285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	rtnl_close(&rth);
287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return ret;
288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
289f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#endif
290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint main(int argc, char **argv)
292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int ret;
294f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#ifndef ANDROID
295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int do_batching = 0;
296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *batchfile = NULL;
297f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#endif
298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (argc > 1) {
300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (argv[1][0] != '-')
301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (matches(argv[1], "-stats") == 0 ||
303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			 matches(argv[1], "-statistics") == 0) {
304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			++show_stats;
305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else if (matches(argv[1], "-details") == 0) {
306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			++show_details;
307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else if (matches(argv[1], "-raw") == 0) {
308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			++show_raw;
309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else if (matches(argv[1], "-pretty") == 0) {
310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			++show_pretty;
311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else if (matches(argv[1], "-Version") == 0) {
312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			printf("tc utility, iproute2-ss%s\n", SNAPSHOT);
313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return 0;
314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else if (matches(argv[1], "-iec") == 0) {
315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			++use_iec;
316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else if (matches(argv[1], "-help") == 0) {
317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			usage();
318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return 0;
319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else if (matches(argv[1], "-force") == 0) {
320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			++force;
321f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#ifndef ANDROID
322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else 	if (matches(argv[1], "-batch") == 0) {
323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			do_batching = 1;
324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (argc > 2)
325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				batchfile = argv[2];
326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			argc--;	argv++;
327f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#endif
328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else {
329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, "Option \"%s\" is unknown, try \"tc -help\".\n", argv[1]);
330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		argc--;	argv++;
333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
334f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#ifndef ANDROID
335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (do_batching)
336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return batch(batchfile);
337f1cbadf4caabd2f5fb30b1e4f3728e1493d40bb7San Mehat#endif
338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (argc <= 1) {
340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		usage();
341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return 0;
342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tc_core_init();
345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (rtnl_open(&rth, 0) < 0) {
346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr, "Cannot open rtnetlink\n");
347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		exit(1);
348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	ret = do_cmd(argc-1, argv+1);
351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	rtnl_close(&rth);
352dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
353dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return ret;
354dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
355