]>
git.proxmox.com Git - mirror_iproute2.git/blob - tc/tc.c
2 * tc.c "tc" utility frontend.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
13 * Petri Mattila <petri@prihateam.fi> 990308: wrong memset's resulted in faults
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
31 #include "tc_common.h"
36 int resolve_hosts
= 0;
39 static void *BODY
; /* cached handle dlopen(NULL) */
40 static struct qdisc_util
* qdisc_list
;
41 static struct filter_util
* filter_list
;
43 static int print_noqopt(struct qdisc_util
*qu
, FILE *f
,
46 if (opt
&& RTA_PAYLOAD(opt
))
47 fprintf(f
, "[Unknown qdisc, optlen=%u] ",
48 (unsigned) RTA_PAYLOAD(opt
));
52 static int parse_noqopt(struct qdisc_util
*qu
, int argc
, char **argv
, struct nlmsghdr
*n
)
55 fprintf(stderr
, "Unknown qdisc \"%s\", hence option \"%s\" is unparsable\n", qu
->id
, *argv
);
61 static int print_nofopt(struct filter_util
*qu
, FILE *f
, struct rtattr
*opt
, __u32 fhandle
)
63 if (opt
&& RTA_PAYLOAD(opt
))
64 fprintf(f
, "fh %08x [Unknown filter, optlen=%u] ",
65 fhandle
, (unsigned) RTA_PAYLOAD(opt
));
67 fprintf(f
, "fh %08x ", fhandle
);
71 static int parse_nofopt(struct filter_util
*qu
, char *fhandle
, int argc
, char **argv
, struct nlmsghdr
*n
)
76 fprintf(stderr
, "Unknown filter \"%s\", hence option \"%s\" is unparsable\n", qu
->id
, *argv
);
80 struct tcmsg
*t
= NLMSG_DATA(n
);
81 if (get_u32(&handle
, fhandle
, 16)) {
82 fprintf(stderr
, "Unparsable filter ID \"%s\"\n", fhandle
);
85 t
->tcm_handle
= handle
;
90 struct qdisc_util
*get_qdisc_kind(const char *str
)
96 for (q
= qdisc_list
; q
; q
= q
->next
)
97 if (strcmp(q
->id
, str
) == 0)
100 snprintf(buf
, sizeof(buf
), "/usr/lib/tc/q_%s.so", str
);
101 dlh
= dlopen(buf
, RTLD_LAZY
);
103 /* look in current binary, only open once */
106 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
112 snprintf(buf
, sizeof(buf
), "%s_qdisc_util", str
);
118 q
->next
= qdisc_list
;
123 q
= malloc(sizeof(*q
));
126 memset(q
, 0, sizeof(*q
));
127 q
->id
= strcpy(malloc(strlen(str
)+1), str
);
128 q
->parse_qopt
= parse_noqopt
;
129 q
->print_qopt
= print_noqopt
;
136 struct filter_util
*get_filter_kind(const char *str
)
140 struct filter_util
*q
;
142 for (q
= filter_list
; q
; q
= q
->next
)
143 if (strcmp(q
->id
, str
) == 0)
146 snprintf(buf
, sizeof(buf
), "/usr/lib/tc/f_%s.so", str
);
147 dlh
= dlopen(buf
, RTLD_LAZY
);
151 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
157 snprintf(buf
, sizeof(buf
), "%s_filter_util", str
);
163 q
->next
= filter_list
;
167 q
= malloc(sizeof(*q
));
169 memset(q
, 0, sizeof(*q
));
170 strncpy(q
->id
, str
, 15);
171 q
->parse_fopt
= parse_nofopt
;
172 q
->print_fopt
= print_nofopt
;
178 static void usage(void) __attribute__((noreturn
));
180 static void usage(void)
182 fprintf(stderr
, "Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n"
183 "where OBJECT := { qdisc | class | filter | action }\n"
184 " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -b[atch] file }\n");
190 int main(int argc
, char **argv
)
194 basename
= strrchr(argv
[0], '/');
195 if (basename
== NULL
)
202 if (argc
> 1 && matches(argv
[1], "-batch") == 0) {
207 #define BMAXARG (sizeof(largv)/sizeof(char *)-2)
210 fprintf(stderr
, "Wrong number of arguments in batch mode\n");
213 if (matches(argv
[2], "-") != 0) {
214 if ((batch
= fopen(argv
[2], "r")) == NULL
) {
215 fprintf(stderr
, "Cannot open file \"%s\" for reading: %s=n", argv
[2], strerror(errno
));
219 if ((batch
= fdopen(0, "r")) == NULL
) {
220 fprintf(stderr
, "Cannot open stdin for reading: %s=n", strerror(errno
));
227 while (fgets(line
, sizeof(line
)-1, batch
)) {
228 if (line
[strlen(line
)-1]=='\n') {
229 line
[strlen(line
)-1] = '\0';
231 fprintf(stderr
, "No newline at the end of line, looks like to long (%d chars or more)\n",
236 largv
[largc
]=strtok(line
, " ");
237 while ((largv
[++largc
]=strtok(NULL
, " ")) != NULL
) {
238 if (largc
> BMAXARG
) {
239 fprintf(stderr
, "Over %d arguments in batch mode, enough!\n",
245 if (matches(largv
[0], "qdisc") == 0) {
246 ret
+= do_qdisc(largc
-1, largv
+1);
247 } else if (matches(largv
[0], "class") == 0) {
248 ret
+= do_class(largc
-1, largv
+1);
249 } else if (matches(largv
[0], "filter") == 0) {
250 ret
+= do_filter(largc
-1, largv
+1);
251 } else if (matches(largv
[0], "action") == 0) {
252 ret
+= do_action(largc
-1, largv
+1);
253 } else if (matches(largv
[0], "help") == 0) {
254 usage(); /* note that usage() doesn't return */
256 fprintf(stderr
, "Object \"%s\" is unknown, try \"tc help\".\n", largv
[1]);
261 exit(0); /* end of batch, that's all */
265 if (argv
[1][0] != '-')
267 if (matches(argv
[1], "-stats") == 0 ||
268 matches(argv
[1], "-statistics") == 0) {
270 } else if (matches(argv
[1], "-details") == 0) {
272 } else if (matches(argv
[1], "-raw") == 0) {
274 } else if (matches(argv
[1], "-Version") == 0) {
275 printf("tc utility, iproute2-ss%s\n", SNAPSHOT
);
277 } else if (matches(argv
[1], "-iec") == 0) {
279 } else if (matches(argv
[1], "-help") == 0) {
282 fprintf(stderr
, "Option \"%s\" is unknown, try \"tc -help\".\n", argv
[1]);
291 if (matches(argv
[1], "qdisc") == 0)
292 return do_qdisc(argc
-2, argv
+2);
293 if (matches(argv
[1], "class") == 0)
294 return do_class(argc
-2, argv
+2);
295 if (matches(argv
[1], "filter") == 0)
296 return do_filter(argc
-2, argv
+2);
297 if (matches(argv
[1], "actions") == 0)
298 return do_action(argc
-2, argv
+2);
299 if (matches(argv
[1], "help") == 0)
301 fprintf(stderr
, "Object \"%s\" is unknown, try \"tc help\".\n", argv
[1]);