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