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