]>
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"
32 #include "namespace.h"
47 static char *conf_file
;
49 struct rtnl_handle rth
;
51 static void *BODY
; /* cached handle dlopen(NULL) */
52 static struct qdisc_util
*qdisc_list
;
53 static struct filter_util
*filter_list
;
55 static int print_noqopt(struct qdisc_util
*qu
, FILE *f
,
58 if (opt
&& RTA_PAYLOAD(opt
))
59 fprintf(f
, "[Unknown qdisc, optlen=%u] ",
60 (unsigned int) RTA_PAYLOAD(opt
));
64 static int parse_noqopt(struct qdisc_util
*qu
, int argc
, char **argv
, struct nlmsghdr
*n
)
67 fprintf(stderr
, "Unknown qdisc \"%s\", hence option \"%s\" is unparsable\n", qu
->id
, *argv
);
73 static int print_nofopt(struct filter_util
*qu
, FILE *f
, struct rtattr
*opt
, __u32 fhandle
)
75 if (opt
&& RTA_PAYLOAD(opt
))
76 fprintf(f
, "fh %08x [Unknown filter, optlen=%u] ",
77 fhandle
, (unsigned int) RTA_PAYLOAD(opt
));
79 fprintf(f
, "fh %08x ", fhandle
);
83 static int parse_nofopt(struct filter_util
*qu
, char *fhandle
, int argc
, char **argv
, struct nlmsghdr
*n
)
88 fprintf(stderr
, "Unknown filter \"%s\", hence option \"%s\" is unparsable\n", qu
->id
, *argv
);
92 struct tcmsg
*t
= NLMSG_DATA(n
);
94 if (get_u32(&handle
, fhandle
, 16)) {
95 fprintf(stderr
, "Unparsable filter ID \"%s\"\n", fhandle
);
98 t
->tcm_handle
= handle
;
103 struct qdisc_util
*get_qdisc_kind(const char *str
)
107 struct qdisc_util
*q
;
109 for (q
= qdisc_list
; q
; q
= q
->next
)
110 if (strcmp(q
->id
, str
) == 0)
113 snprintf(buf
, sizeof(buf
), "%s/q_%s.so", get_tc_lib(), str
);
114 dlh
= dlopen(buf
, RTLD_LAZY
);
116 /* look in current binary, only open once */
119 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
125 snprintf(buf
, sizeof(buf
), "%s_qdisc_util", str
);
131 q
->next
= qdisc_list
;
136 q
= calloc(1, sizeof(*q
));
139 q
->parse_qopt
= parse_noqopt
;
140 q
->print_qopt
= print_noqopt
;
147 struct filter_util
*get_filter_kind(const char *str
)
151 struct filter_util
*q
;
153 for (q
= filter_list
; q
; q
= q
->next
)
154 if (strcmp(q
->id
, str
) == 0)
157 snprintf(buf
, sizeof(buf
), "%s/f_%s.so", get_tc_lib(), str
);
158 dlh
= dlopen(buf
, RTLD_LAZY
);
162 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
168 snprintf(buf
, sizeof(buf
), "%s_filter_util", str
);
174 q
->next
= filter_list
;
178 q
= calloc(1, sizeof(*q
));
180 strncpy(q
->id
, str
, 15);
181 q
->parse_fopt
= parse_nofopt
;
182 q
->print_fopt
= print_nofopt
;
188 static void usage(void)
190 fprintf(stderr
, "Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n"
191 " tc [-force] -batch filename\n"
192 "where OBJECT := { qdisc | class | filter | action | monitor | exec }\n"
193 " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -p[retty] | -b[atch] [filename] | -n[etns] name |\n"
194 " -nm | -nam[es] | { -cf | -conf } path }\n");
197 static int do_cmd(int argc
, char **argv
)
199 if (matches(*argv
, "qdisc") == 0)
200 return do_qdisc(argc
-1, argv
+1);
201 if (matches(*argv
, "class") == 0)
202 return do_class(argc
-1, argv
+1);
203 if (matches(*argv
, "filter") == 0)
204 return do_filter(argc
-1, argv
+1);
205 if (matches(*argv
, "actions") == 0)
206 return do_action(argc
-1, argv
+1);
207 if (matches(*argv
, "monitor") == 0)
208 return do_tcmonitor(argc
-1, argv
+1);
209 if (matches(*argv
, "exec") == 0)
210 return do_exec(argc
-1, argv
+1);
211 if (matches(*argv
, "help") == 0) {
216 fprintf(stderr
, "Object \"%s\" is unknown, try \"tc help\".\n",
221 static int batch(const char *name
)
228 if (name
&& strcmp(name
, "-") != 0) {
229 if (freopen(name
, "r", stdin
) == NULL
) {
230 fprintf(stderr
, "Cannot open file \"%s\" for reading: %s\n",
231 name
, strerror(errno
));
238 if (rtnl_open(&rth
, 0) < 0) {
239 fprintf(stderr
, "Cannot open rtnetlink\n");
244 while (getcmdline(&line
, &len
, stdin
) != -1) {
248 largc
= makeargs(line
, largv
, 100);
250 continue; /* blank line */
252 if (do_cmd(largc
, largv
)) {
253 fprintf(stderr
, "Command failed %s:%d\n", name
, cmdlineno
);
267 int main(int argc
, char **argv
)
270 char *batch_file
= NULL
;
273 if (argv
[1][0] != '-')
275 if (matches(argv
[1], "-stats") == 0 ||
276 matches(argv
[1], "-statistics") == 0) {
278 } else if (matches(argv
[1], "-details") == 0) {
280 } else if (matches(argv
[1], "-raw") == 0) {
282 } else if (matches(argv
[1], "-pretty") == 0) {
284 } else if (matches(argv
[1], "-graph") == 0) {
286 } else if (matches(argv
[1], "-Version") == 0) {
287 printf("tc utility, iproute2-ss%s\n", SNAPSHOT
);
289 } else if (matches(argv
[1], "-iec") == 0) {
291 } else if (matches(argv
[1], "-help") == 0) {
294 } else if (matches(argv
[1], "-force") == 0) {
296 } else if (matches(argv
[1], "-batch") == 0) {
300 batch_file
= argv
[1];
301 } else if (matches(argv
[1], "-netns") == 0) {
303 if (netns_switch(argv
[1]))
305 } else if (matches(argv
[1], "-names") == 0 ||
306 matches(argv
[1], "-nm") == 0) {
308 } else if (matches(argv
[1], "-cf") == 0 ||
309 matches(argv
[1], "-conf") == 0) {
312 } else if (matches(argv
[1], "-timestamp") == 0) {
314 } else if (matches(argv
[1], "-tshort") == 0) {
318 fprintf(stderr
, "Option \"%s\" is unknown, try \"tc -help\".\n", argv
[1]);
325 return batch(batch_file
);
333 if (rtnl_open(&rth
, 0) < 0) {
334 fprintf(stderr
, "Cannot open rtnetlink\n");
338 if (use_names
&& cls_names_init(conf_file
)) {
343 ret
= do_cmd(argc
-1, argv
+1);