quip_client.c revision 1.9 1 1.9 peter /* $NetBSD: quip_client.c,v 1.9 2006/10/12 19:59:13 peter Exp $ */
2 1.9 peter /* $KAME: quip_client.c,v 1.9 2003/05/17 05:59:00 itojun Exp $ */
3 1.1 thorpej /*
4 1.1 thorpej * Copyright (C) 1999-2000
5 1.1 thorpej * Sony Computer Science Laboratories, Inc. All rights reserved.
6 1.1 thorpej *
7 1.1 thorpej * Redistribution and use in source and binary forms, with or without
8 1.1 thorpej * modification, are permitted provided that the following conditions
9 1.1 thorpej * are met:
10 1.1 thorpej * 1. Redistributions of source code must retain the above copyright
11 1.1 thorpej * notice, this list of conditions and the following disclaimer.
12 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 thorpej * notice, this list of conditions and the following disclaimer in the
14 1.1 thorpej * documentation and/or other materials provided with the distribution.
15 1.1 thorpej *
16 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
17 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
20 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.1 thorpej * SUCH DAMAGE.
27 1.1 thorpej */
28 1.1 thorpej
29 1.1 thorpej #include <sys/param.h>
30 1.1 thorpej #include <sys/socket.h>
31 1.8 kleink #include <sys/time.h>
32 1.1 thorpej #include <sys/un.h>
33 1.1 thorpej
34 1.1 thorpej #include <stdio.h>
35 1.1 thorpej #include <stdlib.h>
36 1.1 thorpej #include <unistd.h>
37 1.1 thorpej #include <string.h>
38 1.1 thorpej #include <errno.h>
39 1.1 thorpej #include <err.h>
40 1.1 thorpej
41 1.1 thorpej #include "quip_client.h"
42 1.1 thorpej #include "altqstat.h"
43 1.1 thorpej
44 1.1 thorpej /*
45 1.1 thorpej * quip (queue information protocol) is a http-like protocol
46 1.1 thorpej * in order to retrieve information from the server.
47 1.1 thorpej * a unix domain TCP socket "/var/run/altq_quip" is used for
48 1.5 wiz * client-server style communication.
49 1.1 thorpej *
50 1.1 thorpej * there are 2 quip message types: request and response.
51 1.1 thorpej * request format: (only single-line request message is used at this moment)
52 1.1 thorpej * request-line
53 1.1 thorpej *
54 1.1 thorpej * request-line = <method> <operation>[?<query>] <quip-version>
55 1.1 thorpej * <method> = GET (only GET is defined at this moment)
56 1.1 thorpej * <operation> = list | handle-to-name | qdisc | filter
57 1.1 thorpej * query format is operation dependent but most query takes
58 1.1 thorpej * <interface> or <class> or <filter>.
59 1.1 thorpej * <interface> = <if_name>
60 1.1 thorpej * <class> = <if_name>:<class_path>/<class_name>
61 1.1 thorpej * <filter> = <if_name>:<class_path>/<class_name>:<filter_name>
62 1.1 thorpej * "list" operation accepts "*" as a wildcard.
63 1.1 thorpej *
64 1.1 thorpej * response format:
65 1.1 thorpej * status-line
66 1.1 thorpej * response-headers (0 or more)
67 1.1 thorpej * <blank line>
68 1.1 thorpej * body
69 1.1 thorpej *
70 1.1 thorpej * status-line = <quip-version> <status-code> <reason phrase>
71 1.1 thorpej * response-header = Content-Length:<value>
72 1.1 thorpej *
73 1.1 thorpej * "Content-Length" specifies the length of the message body.
74 1.1 thorpej *
75 1.1 thorpej * example:
76 1.1 thorpej * to retrieve a list of classes (handle and name) on interface "fxp0":
77 1.1 thorpej * a request message looks like,
78 1.1 thorpej * GET list?fxp0:* QUIP/1.0<cr>
79 1.1 thorpej * a response message looks like,
80 1.1 thorpej * QUIP/1.0 200 OK<cr>
81 1.1 thorpej * Content-Length:86<cr>
82 1.1 thorpej * <cr>
83 1.1 thorpej * 0000000000 fxp0:/root<cr>
84 1.1 thorpej * 0xc0d1be00 fxp0:/root/parent<cr>
85 1.1 thorpej * 0xc0d1ba00 fxp0:/root/parent/child<cr>
86 1.1 thorpej *
87 1.1 thorpej * other examples:
88 1.1 thorpej * list all interfaces, classes, and filters:
89 1.1 thorpej * GET list QUIP/1.0<cr>
90 1.1 thorpej * list all interfaces:
91 1.1 thorpej * GET list?* QUIP/1.0<cr>
92 1.1 thorpej * list all classes:
93 1.1 thorpej * GET list?*:* QUIP/1.0<cr>
94 1.1 thorpej * list all filters:
95 1.1 thorpej * GET list?*:*:* QUIP/1.0<cr>
96 1.1 thorpej * convert class handle to class name:
97 1.1 thorpej * GET handle-to-name?fxp0:0xc0d1be00 QUIP/1.0<cr>
98 1.1 thorpej * convert filter handle to filter name:
99 1.1 thorpej * GET handle-to-name?fxp0::0x1000000a QUIP/1.0<cr>
100 1.1 thorpej */
101 1.1 thorpej
102 1.4 itojun #define MAXLINESIZE 1024
103 1.4 itojun
104 1.1 thorpej enum nametype { INTERFACE, CLASS, FILTER, CONDITIONER };
105 1.1 thorpej
106 1.1 thorpej static FILE *server = NULL;
107 1.1 thorpej int quip_echo = 0;
108 1.1 thorpej
109 1.2 itojun static char *extract_ifname(const char *);
110 1.1 thorpej
111 1.1 thorpej int
112 1.1 thorpej quip_openserver(void)
113 1.1 thorpej {
114 1.1 thorpej struct sockaddr_un addr;
115 1.1 thorpej int fd;
116 1.1 thorpej
117 1.1 thorpej if ((fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
118 1.1 thorpej err(1, "can't open socket");
119 1.1 thorpej
120 1.1 thorpej bzero(&addr, sizeof(addr));
121 1.1 thorpej addr.sun_family = AF_LOCAL;
122 1.2 itojun strlcpy(addr.sun_path, QUIP_PATH,sizeof(addr.sun_path));
123 1.1 thorpej
124 1.1 thorpej if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
125 1.1 thorpej fprintf(stderr, "can't talk to altqd!\n"
126 1.1 thorpej "probably, altqd is not running\n");
127 1.1 thorpej return (-1);
128 1.1 thorpej }
129 1.1 thorpej
130 1.1 thorpej if ((server = fdopen(fd, "r+")) == NULL) {
131 1.1 thorpej warn("fdopen: can't open stream to the quip server");
132 1.1 thorpej return (-1);
133 1.1 thorpej }
134 1.1 thorpej return (0);
135 1.1 thorpej }
136 1.1 thorpej
137 1.1 thorpej int
138 1.1 thorpej quip_closeserver(void)
139 1.1 thorpej {
140 1.1 thorpej if (server != NULL)
141 1.1 thorpej return fclose(server);
142 1.1 thorpej return (0);
143 1.1 thorpej }
144 1.1 thorpej
145 1.1 thorpej void
146 1.1 thorpej quip_sendrequest(FILE *fp, const char *request)
147 1.1 thorpej {
148 1.2 itojun char buf[QUIPMSG_MAXSIZE], *cp;
149 1.1 thorpej int n;
150 1.1 thorpej
151 1.1 thorpej if ((cp = strstr(request, "QUIP")) == NULL) {
152 1.1 thorpej cp = strchr(request, '\n');
153 1.1 thorpej n = cp - request;
154 1.2 itojun if (cp == NULL || n > REQ_MAXSIZE - 10)
155 1.2 itojun return;
156 1.1 thorpej strncpy(buf, request, n);
157 1.4 itojun snprintf(buf + n, REQ_MAXSIZE - n, " QUIP/1.0");
158 1.4 itojun strlcat(buf, cp, REQ_MAXSIZE);
159 1.1 thorpej }
160 1.1 thorpej else
161 1.2 itojun strlcpy(buf, request, REQ_MAXSIZE);
162 1.1 thorpej
163 1.1 thorpej if (fputs(buf, fp) != 0)
164 1.1 thorpej err(1, "fputs");
165 1.1 thorpej if (fflush(fp) != 0)
166 1.1 thorpej err(1, "fflush");
167 1.1 thorpej if (quip_echo) {
168 1.1 thorpej fputs("<< ", stdout);
169 1.1 thorpej fputs(buf, stdout);
170 1.1 thorpej }
171 1.1 thorpej }
172 1.1 thorpej
173 1.1 thorpej /*
174 1.1 thorpej * recv_response receives a response message from the server
175 1.1 thorpej * and returns status_code.
176 1.1 thorpej */
177 1.1 thorpej int
178 1.1 thorpej quip_recvresponse(FILE *fp, char *header, char *body, int *blen)
179 1.1 thorpej {
180 1.4 itojun char buf[MAXLINESIZE], version[MAXLINESIZE];
181 1.4 itojun int code, resid, len, buflen;
182 1.1 thorpej int end_of_header = 0;
183 1.1 thorpej
184 1.1 thorpej if (blen != NULL)
185 1.1 thorpej *blen = 0;
186 1.1 thorpej code = 0;
187 1.1 thorpej resid = 0;
188 1.4 itojun buflen = RES_MAXSIZE;
189 1.2 itojun while (fgets(buf, sizeof(buf), fp) != 0) {
190 1.1 thorpej if (quip_echo) {
191 1.1 thorpej fputs("> ", stdout);
192 1.1 thorpej fputs(buf, stdout);
193 1.1 thorpej }
194 1.1 thorpej
195 1.1 thorpej if (!end_of_header) {
196 1.1 thorpej /* process message header */
197 1.4 itojun if (header != NULL) {
198 1.4 itojun len = strlcpy(header, buf, buflen);
199 1.4 itojun if (len >= buflen) {
200 1.4 itojun /* header too long */
201 1.4 itojun fpurge(fp);
202 1.4 itojun return (-1);
203 1.4 itojun }
204 1.4 itojun header += len;
205 1.4 itojun buflen -= len;
206 1.4 itojun }
207 1.1 thorpej
208 1.1 thorpej if (code == 0) {
209 1.1 thorpej /* status line expected */
210 1.1 thorpej if (buf[0] == '\n') {
211 1.1 thorpej /* ignore blank lines */
212 1.1 thorpej }
213 1.9 peter /* XXX sizeof(version) == 1024 */
214 1.7 itojun else if (sscanf(buf, "%1023s %d",
215 1.1 thorpej version, &code) != 2) {
216 1.1 thorpej /* can't get result code */
217 1.1 thorpej fpurge(fp);
218 1.1 thorpej return (-1);
219 1.1 thorpej }
220 1.1 thorpej }
221 1.1 thorpej else {
222 1.1 thorpej /* entity header expected */
223 1.1 thorpej char *field, *cp;
224 1.1 thorpej
225 1.1 thorpej if (buf[0] == '\n') {
226 1.1 thorpej /* end of header */
227 1.1 thorpej end_of_header = 1;
228 1.4 itojun buflen = BODY_MAXSIZE;
229 1.1 thorpej if (resid == 0)
230 1.1 thorpej /* no message body */
231 1.1 thorpej return (code);
232 1.1 thorpej }
233 1.1 thorpej
234 1.1 thorpej cp = buf;
235 1.1 thorpej field = strsep(&cp, ":");
236 1.1 thorpej if (strcmp(field, "Content-Length") == 0) {
237 1.2 itojun if (sscanf(cp, "%d", &resid) != 1) {
238 1.2 itojun fpurge(fp);
239 1.2 itojun return (-1);
240 1.2 itojun }
241 1.1 thorpej if (blen != NULL)
242 1.1 thorpej *blen = resid;
243 1.1 thorpej }
244 1.1 thorpej }
245 1.1 thorpej }
246 1.1 thorpej else {
247 1.1 thorpej /* process message body */
248 1.1 thorpej if (body != NULL) {
249 1.4 itojun len = strlcpy(body, buf, buflen);
250 1.4 itojun if (len >= buflen) {
251 1.4 itojun /* body too long */
252 1.4 itojun fpurge(fp);
253 1.4 itojun return (-1);
254 1.4 itojun }
255 1.1 thorpej body += len;
256 1.4 itojun buflen -= len;
257 1.1 thorpej }
258 1.1 thorpej else
259 1.1 thorpej len = strlen(buf);
260 1.1 thorpej resid -= len;
261 1.1 thorpej if (resid <= 0)
262 1.1 thorpej return (code);
263 1.1 thorpej }
264 1.1 thorpej }
265 1.1 thorpej return (-1);
266 1.1 thorpej }
267 1.1 thorpej
268 1.1 thorpej void
269 1.1 thorpej quip_rawmode(void)
270 1.1 thorpej {
271 1.4 itojun char line[MAXLINESIZE];
272 1.1 thorpej int result_code;
273 1.1 thorpej
274 1.1 thorpej printf(">>>Entering the raw interactive mode to the server:\n\n");
275 1.1 thorpej if (server == NULL) {
276 1.1 thorpej printf("No server available!\n");
277 1.1 thorpej return;
278 1.1 thorpej }
279 1.1 thorpej
280 1.1 thorpej while (1) {
281 1.1 thorpej printf("%% "); fflush(stdout);
282 1.1 thorpej /* read a line from stdin */
283 1.4 itojun if (fgets(line, sizeof(line), stdin) == NULL)
284 1.1 thorpej break;
285 1.1 thorpej
286 1.1 thorpej if (line[0] == '\n') {
287 1.1 thorpej /* if a blank line, echo locally */
288 1.1 thorpej fputs(line, stdout);
289 1.1 thorpej continue;
290 1.1 thorpej }
291 1.1 thorpej if (line[0] == 'q') {
292 1.1 thorpej printf("Exit\n");
293 1.1 thorpej break;
294 1.1 thorpej }
295 1.1 thorpej
296 1.1 thorpej /* send the input line to the server */
297 1.1 thorpej quip_sendrequest(server, line);
298 1.1 thorpej
299 1.1 thorpej /* get a response message from the server */
300 1.1 thorpej result_code = quip_recvresponse(server, NULL, NULL, NULL);
301 1.1 thorpej }
302 1.1 thorpej }
303 1.1 thorpej
304 1.1 thorpej char *
305 1.1 thorpej quip_selectinterface(char *ifname)
306 1.1 thorpej {
307 1.4 itojun char buf[BODY_MAXSIZE], *cp;
308 1.1 thorpej int result_code, len;
309 1.1 thorpej u_int if_index;
310 1.1 thorpej static char interface[64];
311 1.1 thorpej
312 1.1 thorpej if (server == NULL)
313 1.1 thorpej return (ifname);
314 1.1 thorpej
315 1.1 thorpej /* get an inferface list from the server */
316 1.1 thorpej quip_sendrequest(server, "GET list?*\n");
317 1.1 thorpej
318 1.1 thorpej result_code = quip_recvresponse(server, NULL, buf, &len);
319 1.1 thorpej if (result_code != 200)
320 1.1 thorpej errx(1, "can't get interface list");
321 1.1 thorpej
322 1.1 thorpej cp = buf;
323 1.1 thorpej while (1) {
324 1.7 itojun if (sscanf(cp, "%x %63s", &if_index, interface) != 2)
325 1.1 thorpej break;
326 1.1 thorpej if (ifname == NULL) {
327 1.1 thorpej /* if name isn't specified, return the 1st entry */
328 1.1 thorpej return (interface);
329 1.1 thorpej }
330 1.1 thorpej if (strcmp(ifname, interface) == 0)
331 1.4 itojun /* found the matching entry */
332 1.4 itojun return (interface);
333 1.1 thorpej if ((cp = strchr(cp+1, '\n')) == NULL)
334 1.1 thorpej break;
335 1.1 thorpej }
336 1.1 thorpej errx(1, "can't get interface");
337 1.1 thorpej return (NULL);
338 1.1 thorpej }
339 1.1 thorpej
340 1.1 thorpej char *
341 1.1 thorpej quip_selectqdisc(char *ifname, char *qdisc_name)
342 1.1 thorpej {
343 1.2 itojun char buf[BODY_MAXSIZE], req[REQ_MAXSIZE];
344 1.1 thorpej int result_code, len;
345 1.1 thorpej static char qdisc[64];
346 1.1 thorpej
347 1.1 thorpej if (server == NULL) {
348 1.1 thorpej if (ifname == NULL || qdisc_name == NULL)
349 1.1 thorpej errx(1, "when disabling server communication,\n"
350 1.1 thorpej "specify both interface (-i) and qdisc (-q)!");
351 1.1 thorpej return (qdisc_name);
352 1.1 thorpej }
353 1.1 thorpej
354 1.1 thorpej /* get qdisc info from the server */
355 1.2 itojun snprintf(req, sizeof(req), "GET qdisc?%s\n", ifname);
356 1.1 thorpej quip_sendrequest(server, req);
357 1.1 thorpej
358 1.1 thorpej result_code = quip_recvresponse(server, NULL, buf, &len);
359 1.1 thorpej if (result_code != 200)
360 1.1 thorpej errx(1, "can't get qdisc info");
361 1.1 thorpej
362 1.9 peter if (sscanf(buf, "%s", qdisc) != 1)
363 1.1 thorpej errx(1, "can't get qdisc name");
364 1.1 thorpej
365 1.1 thorpej if (qdisc_name != NULL && strcmp(qdisc, qdisc_name) != 0)
366 1.1 thorpej errx(1, "qdisc %s on %s doesn't match specified qdisc %s",
367 1.1 thorpej qdisc, ifname, qdisc_name);
368 1.1 thorpej
369 1.1 thorpej return (qdisc);
370 1.1 thorpej }
371 1.1 thorpej
372 1.1 thorpej void
373 1.2 itojun quip_chandle2name(const char *ifname, u_long handle, char *name, size_t size)
374 1.1 thorpej {
375 1.2 itojun char buf[BODY_MAXSIZE], req[REQ_MAXSIZE], *cp;
376 1.1 thorpej int result_code, len;
377 1.1 thorpej
378 1.1 thorpej name[0] = '\0';
379 1.1 thorpej if (server == NULL)
380 1.1 thorpej return;
381 1.1 thorpej
382 1.1 thorpej /* get class name from the server */
383 1.2 itojun snprintf(req, sizeof(req), "GET handle-to-name?%s:%#lx\n", ifname, handle);
384 1.1 thorpej quip_sendrequest(server, req);
385 1.1 thorpej
386 1.1 thorpej result_code = quip_recvresponse(server, NULL, buf, &len);
387 1.1 thorpej if (result_code != 200)
388 1.1 thorpej errx(1, "can't get class name");
389 1.1 thorpej
390 1.1 thorpej if ((cp = strchr(buf, '\n')) != NULL)
391 1.1 thorpej *cp = '\0';
392 1.1 thorpej if ((cp = strrchr(buf, '/')) != NULL)
393 1.2 itojun strlcpy(name, cp+1, size);
394 1.1 thorpej }
395 1.1 thorpej
396 1.1 thorpej void
397 1.1 thorpej quip_printqdisc(const char *ifname)
398 1.1 thorpej {
399 1.2 itojun char buf[BODY_MAXSIZE], req[REQ_MAXSIZE], *cp;
400 1.1 thorpej int result_code, len;
401 1.1 thorpej
402 1.1 thorpej if (server == NULL) {
403 1.1 thorpej printf("No server available!\n");
404 1.1 thorpej return;
405 1.1 thorpej }
406 1.1 thorpej
407 1.1 thorpej /* get qdisc info from the server */
408 1.2 itojun snprintf(req, sizeof(req), "GET qdisc?%s\n", ifname);
409 1.1 thorpej quip_sendrequest(server, req);
410 1.1 thorpej
411 1.1 thorpej result_code = quip_recvresponse(server, NULL, buf, &len);
412 1.1 thorpej if (result_code != 200)
413 1.1 thorpej errx(1, "can't get qdisc info");
414 1.1 thorpej
415 1.1 thorpej /* replace newline by space */
416 1.1 thorpej cp = buf;
417 1.1 thorpej while ((cp = strchr(cp, '\n')) != NULL)
418 1.1 thorpej *cp = ' ';
419 1.1 thorpej
420 1.1 thorpej printf(" qdisc:%s\n", buf);
421 1.1 thorpej }
422 1.1 thorpej
423 1.1 thorpej void
424 1.1 thorpej quip_printfilter(const char *ifname, const u_long handle)
425 1.1 thorpej {
426 1.2 itojun char buf[BODY_MAXSIZE], req[REQ_MAXSIZE], *cp;
427 1.1 thorpej int result_code, len;
428 1.1 thorpej
429 1.9 peter if (server == NULL) {
430 1.9 peter printf("No server available!\n");
431 1.9 peter return;
432 1.9 peter }
433 1.9 peter
434 1.1 thorpej /* get qdisc info from the server */
435 1.2 itojun snprintf(req, sizeof(req), "GET filter?%s::%#lx\n", ifname, handle);
436 1.1 thorpej quip_sendrequest(server, req);
437 1.1 thorpej
438 1.1 thorpej result_code = quip_recvresponse(server, NULL, buf, &len);
439 1.1 thorpej if (result_code != 200)
440 1.1 thorpej errx(1, "can't get filter info");
441 1.1 thorpej
442 1.1 thorpej if ((cp = strchr(buf, '\n')) != NULL)
443 1.1 thorpej *cp = '\0';
444 1.1 thorpej printf("%s", buf);
445 1.1 thorpej }
446 1.1 thorpej
447 1.1 thorpej static char *
448 1.1 thorpej extract_ifname(const char *name)
449 1.1 thorpej {
450 1.1 thorpej char *cp;
451 1.1 thorpej int len;
452 1.1 thorpej static char ifname[64];
453 1.1 thorpej
454 1.1 thorpej if ((cp = strchr(name, ':')) != NULL)
455 1.1 thorpej len = cp - name;
456 1.1 thorpej else
457 1.1 thorpej len = strlen(name);
458 1.1 thorpej len = MIN(len, 63);
459 1.1 thorpej strncpy(ifname, name, len);
460 1.1 thorpej ifname[len] = '\0';
461 1.1 thorpej return (ifname);
462 1.1 thorpej }
463 1.1 thorpej
464 1.1 thorpej void
465 1.1 thorpej quip_printconfig(void)
466 1.1 thorpej {
467 1.4 itojun char buf[BODY_MAXSIZE], name[256], *cp, *p, *flname;
468 1.1 thorpej int result_code, len;
469 1.1 thorpej enum nametype type;
470 1.1 thorpej u_long handle;
471 1.1 thorpej
472 1.9 peter if (server == NULL) {
473 1.9 peter printf("No server available!\n");
474 1.9 peter return;
475 1.9 peter }
476 1.9 peter
477 1.1 thorpej /* get a total list from the server */
478 1.1 thorpej quip_sendrequest(server, "GET list\n");
479 1.1 thorpej
480 1.1 thorpej result_code = quip_recvresponse(server, NULL, buf, &len);
481 1.1 thorpej if (result_code != 200)
482 1.1 thorpej errx(1, "can't get total list");
483 1.1 thorpej
484 1.1 thorpej printf("------------ current configuration ------------");
485 1.1 thorpej
486 1.1 thorpej cp = buf;
487 1.1 thorpej while (1) {
488 1.7 itojun if (sscanf(cp, "%lx %255s", &handle, name) != 2)
489 1.1 thorpej break;
490 1.1 thorpej
491 1.1 thorpej if ((p = strchr(name, ':')) == NULL)
492 1.1 thorpej type = INTERFACE;
493 1.1 thorpej else if (strchr(p+1, ':') == NULL)
494 1.1 thorpej type = CLASS;
495 1.1 thorpej else
496 1.1 thorpej type = FILTER;
497 1.1 thorpej
498 1.1 thorpej switch (type) {
499 1.1 thorpej case INTERFACE:
500 1.1 thorpej printf("\ninterface: %s (index:%lu)\n",
501 1.1 thorpej name, handle);
502 1.1 thorpej quip_printqdisc(name);
503 1.1 thorpej break;
504 1.1 thorpej case CLASS:
505 1.1 thorpej printf("class: %s (handle:%#lx)\n",
506 1.1 thorpej name, handle);
507 1.1 thorpej break;
508 1.1 thorpej case FILTER:
509 1.1 thorpej flname = strrchr(name, ':') + 1;
510 1.1 thorpej printf(" filter: name:%s [", flname);
511 1.1 thorpej quip_printfilter(extract_ifname(name), handle);
512 1.1 thorpej printf("] (handle:%#lx)\n", handle);
513 1.1 thorpej break;
514 1.1 thorpej case CONDITIONER:
515 1.1 thorpej break;
516 1.1 thorpej }
517 1.1 thorpej
518 1.1 thorpej if ((cp = strchr(cp+1, '\n')) == NULL)
519 1.1 thorpej break;
520 1.1 thorpej }
521 1.1 thorpej printf("-----------------------------------------------\n\n");
522 1.1 thorpej }
523 1.1 thorpej
524