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