aboutsummaryrefslogtreecommitdiff
path: root/networking/libiproute/iproute.c
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2002-11-10 01:33:55 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2002-11-10 01:33:55 +0000
commit9a2d27249cc2235f7e001a9ea8d4605406bc5f38 (patch)
treeb7b2917c3cf46ac3fa25df5f9a27a9a9fbfb0398 /networking/libiproute/iproute.c
parent021fa7db9139bff3b4bf404dfd7d2b1541ed71f8 (diff)
downloadbusybox-w32-9a2d27249cc2235f7e001a9ea8d4605406bc5f38.tar.gz
busybox-w32-9a2d27249cc2235f7e001a9ea8d4605406bc5f38.tar.bz2
busybox-w32-9a2d27249cc2235f7e001a9ea8d4605406bc5f38.zip
IP applet by Bastian Blank <waldi@debian.org>
Diffstat (limited to 'networking/libiproute/iproute.c')
-rw-r--r--networking/libiproute/iproute.c674
1 files changed, 674 insertions, 0 deletions
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c
new file mode 100644
index 000000000..e38abcd01
--- /dev/null
+++ b/networking/libiproute/iproute.c
@@ -0,0 +1,674 @@
1/*
2 * iproute.c "ip route".
3 *
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.
8 *
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 *
11 *
12 * Changes:
13 *
14 * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
15 * Kunihiro Ishiguro <kunihiro@zebra.org> 001102: rtnh_ifindex was not initialized
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#include <syslog.h>
22#include <fcntl.h>
23#include <string.h>
24#include <sys/time.h>
25#include <sys/socket.h>
26#include <netinet/in.h>
27#include <netinet/ip.h>
28#include <arpa/inet.h>
29#include <linux/in_route.h>
30
31#include "rt_names.h"
32#include "utils.h"
33#include "ip_common.h"
34
35#include "busybox.h"
36
37#ifndef RTAX_RTTVAR
38#define RTAX_RTTVAR RTAX_HOPS
39#endif
40
41
42static struct
43{
44 int tb;
45 int flushp;
46 int flushe;
47 struct rtnl_handle *rth;
48 int protocol, protocolmask;
49 int scope, scopemask;
50 int type, typemask;
51 int tos, tosmask;
52 int iif, iifmask;
53 int oif, oifmask;
54 int realm, realmmask;
55 inet_prefix rprefsrc;
56 inet_prefix rvia;
57 inet_prefix rdst;
58 inet_prefix mdst;
59 inet_prefix rsrc;
60 inet_prefix msrc;
61} filter;
62
63int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
64{
65 FILE *fp = (FILE*)arg;
66 struct rtmsg *r = NLMSG_DATA(n);
67 int len = n->nlmsg_len;
68 struct rtattr * tb[RTA_MAX+1];
69 char abuf[256];
70 int host_len = -1;
71 SPRINT_BUF(b1);
72
73
74 if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
75 fprintf(stderr, "Not a route: %08x %08x %08x\n",
76 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
77 return 0;
78 }
79 len -= NLMSG_LENGTH(sizeof(*r));
80 if (len < 0) {
81 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
82 return -1;
83 }
84
85 if (r->rtm_family == AF_INET6)
86 host_len = 128;
87 else if (r->rtm_family == AF_INET)
88 host_len = 32;
89
90 if (r->rtm_family == AF_INET6) {
91 if (filter.tb) {
92 if (filter.tb < 0) {
93 if (!(r->rtm_flags&RTM_F_CLONED))
94 return 0;
95 } else {
96 if (r->rtm_flags&RTM_F_CLONED)
97 return 0;
98 if (filter.tb == RT_TABLE_LOCAL) {
99 if (r->rtm_type != RTN_LOCAL)
100 return 0;
101 } else if (filter.tb == RT_TABLE_MAIN) {
102 if (r->rtm_type == RTN_LOCAL)
103 return 0;
104 } else {
105 return 0;
106 }
107 }
108 }
109 } else {
110 if (filter.tb > 0 && filter.tb != r->rtm_table)
111 return 0;
112 }
113 if (filter.rdst.family &&
114 (r->rtm_family != filter.rdst.family || filter.rdst.bitlen > r->rtm_dst_len))
115 return 0;
116 if (filter.mdst.family &&
117 (r->rtm_family != filter.mdst.family ||
118 (filter.mdst.bitlen >= 0 && filter.mdst.bitlen < r->rtm_dst_len)))
119 return 0;
120 if (filter.rsrc.family &&
121 (r->rtm_family != filter.rsrc.family || filter.rsrc.bitlen > r->rtm_src_len))
122 return 0;
123 if (filter.msrc.family &&
124 (r->rtm_family != filter.msrc.family ||
125 (filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len)))
126 return 0;
127
128 memset(tb, 0, sizeof(tb));
129 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
130
131 if (n->nlmsg_type == RTM_DELROUTE)
132 fprintf(fp, "Deleted ");
133 if (r->rtm_type != RTN_UNICAST && !filter.type)
134 fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
135
136 if (tb[RTA_DST]) {
137 if (r->rtm_dst_len != host_len) {
138 fprintf(fp, "%s/%u ", rt_addr_n2a(r->rtm_family,
139 RTA_PAYLOAD(tb[RTA_DST]),
140 RTA_DATA(tb[RTA_DST]),
141 abuf, sizeof(abuf)),
142 r->rtm_dst_len
143 );
144 } else {
145 fprintf(fp, "%s ", format_host(r->rtm_family,
146 RTA_PAYLOAD(tb[RTA_DST]),
147 RTA_DATA(tb[RTA_DST]),
148 abuf, sizeof(abuf))
149 );
150 }
151 } else if (r->rtm_dst_len) {
152 fprintf(fp, "0/%d ", r->rtm_dst_len);
153 } else {
154 fprintf(fp, "default ");
155 }
156 if (tb[RTA_SRC]) {
157 if (r->rtm_src_len != host_len) {
158 fprintf(fp, "from %s/%u ", rt_addr_n2a(r->rtm_family,
159 RTA_PAYLOAD(tb[RTA_SRC]),
160 RTA_DATA(tb[RTA_SRC]),
161 abuf, sizeof(abuf)),
162 r->rtm_src_len
163 );
164 } else {
165 fprintf(fp, "from %s ", format_host(r->rtm_family,
166 RTA_PAYLOAD(tb[RTA_SRC]),
167 RTA_DATA(tb[RTA_SRC]),
168 abuf, sizeof(abuf))
169 );
170 }
171 } else if (r->rtm_src_len) {
172 fprintf(fp, "from 0/%u ", r->rtm_src_len);
173 }
174 if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len) {
175 fprintf(fp, "via %s ",
176 format_host(r->rtm_family,
177 RTA_PAYLOAD(tb[RTA_GATEWAY]),
178 RTA_DATA(tb[RTA_GATEWAY]),
179 abuf, sizeof(abuf)));
180 }
181 if (tb[RTA_OIF] && filter.oifmask != -1)
182 fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
183
184 if (tb[RTA_PREFSRC] && filter.rprefsrc.bitlen != host_len) {
185 /* Do not use format_host(). It is our local addr
186 and symbolic name will not be useful.
187 */
188 fprintf(fp, " src %s ",
189 rt_addr_n2a(r->rtm_family,
190 RTA_PAYLOAD(tb[RTA_PREFSRC]),
191 RTA_DATA(tb[RTA_PREFSRC]),
192 abuf, sizeof(abuf)));
193 }
194 if (tb[RTA_PRIORITY])
195 fprintf(fp, " metric %d ", *(__u32*)RTA_DATA(tb[RTA_PRIORITY]));
196 if (r->rtm_family == AF_INET6) {
197 struct rta_cacheinfo *ci = NULL;
198 if (tb[RTA_CACHEINFO])
199 ci = RTA_DATA(tb[RTA_CACHEINFO]);
200 if ((r->rtm_flags & RTM_F_CLONED) || (ci && ci->rta_expires)) {
201 static int hz;
202 if (!hz)
203 hz = get_hz();
204 if (r->rtm_flags & RTM_F_CLONED)
205 fprintf(fp, "%s cache ", _SL_);
206 if (ci->rta_expires)
207 fprintf(fp, " expires %dsec", ci->rta_expires/hz);
208 if (ci->rta_error != 0)
209 fprintf(fp, " error %d", ci->rta_error);
210 } else if (ci) {
211 if (ci->rta_error != 0)
212 fprintf(fp, " error %d", ci->rta_error);
213 }
214 }
215 if (tb[RTA_IIF] && filter.iifmask != -1) {
216 fprintf(fp, " iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF])));
217 }
218 fprintf(fp, "\n");
219 fflush(fp);
220 return 0;
221}
222
223int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
224{
225 struct rtnl_handle rth;
226 struct {
227 struct nlmsghdr n;
228 struct rtmsg r;
229 char buf[1024];
230 } req;
231 char mxbuf[256];
232 struct rtattr * mxrta = (void*)mxbuf;
233 unsigned mxlock = 0;
234 char *d = NULL;
235 int gw_ok = 0;
236 int dst_ok = 0;
237 //int nhs_ok = 0;
238 //int scope_ok = 0;
239 //int table_ok = 0;
240 int proto_ok = 0;
241 int type_ok = 0;
242
243 memset(&req, 0, sizeof(req));
244
245 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
246 req.n.nlmsg_flags = NLM_F_REQUEST|flags;
247 req.n.nlmsg_type = cmd;
248 req.r.rtm_family = preferred_family;
249 req.r.rtm_table = RT_TABLE_MAIN;
250 req.r.rtm_scope = RT_SCOPE_NOWHERE;
251
252 if (cmd != RTM_DELROUTE) {
253 req.r.rtm_protocol = RTPROT_BOOT;
254 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
255 req.r.rtm_type = RTN_UNICAST;
256 }
257
258 mxrta->rta_type = RTA_METRICS;
259 mxrta->rta_len = RTA_LENGTH(0);
260
261 while (argc > 0) {
262 if (strcmp(*argv, "src") == 0) {
263 inet_prefix addr;
264 NEXT_ARG();
265 get_addr(&addr, *argv, req.r.rtm_family);
266 if (req.r.rtm_family == AF_UNSPEC)
267 req.r.rtm_family = addr.family;
268 addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen);
269 } else if (strcmp(*argv, "via") == 0) {
270 inet_prefix addr;
271 gw_ok = 1;
272 NEXT_ARG();
273 get_addr(&addr, *argv, req.r.rtm_family);
274 if (req.r.rtm_family == AF_UNSPEC)
275 req.r.rtm_family = addr.family;
276 addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen);
277 } else if (strcmp(*argv, "mtu") == 0) {
278 unsigned mtu;
279 NEXT_ARG();
280 if (strcmp(*argv, "lock") == 0) {
281 mxlock |= (1<<RTAX_MTU);
282 NEXT_ARG();
283 }
284 if (get_unsigned(&mtu, *argv, 0))
285 invarg("\"mtu\" value is invalid\n", *argv);
286 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu);
287 } else if (matches(*argv, "protocol") == 0) {
288 int prot;
289 NEXT_ARG();
290 if (rtnl_rtprot_a2n(&prot, *argv))
291 invarg("\"protocol\" value is invalid\n", *argv);
292 req.r.rtm_protocol = prot;
293 proto_ok =1;
294 } else if (strcmp(*argv, "dev") == 0 ||
295 strcmp(*argv, "oif") == 0) {
296 NEXT_ARG();
297 d = *argv;
298 } else {
299 int type;
300 inet_prefix dst;
301
302 if (strcmp(*argv, "to") == 0) {
303 NEXT_ARG();
304 }
305 if ((**argv < '0' || **argv > '9') &&
306 rtnl_rtntype_a2n(&type, *argv) == 0) {
307 NEXT_ARG();
308 req.r.rtm_type = type;
309 type_ok = 1;
310 }
311
312 if (dst_ok)
313 duparg2("to", *argv);
314 get_prefix(&dst, *argv, req.r.rtm_family);
315 if (req.r.rtm_family == AF_UNSPEC)
316 req.r.rtm_family = dst.family;
317 req.r.rtm_dst_len = dst.bitlen;
318 dst_ok = 1;
319 if (dst.bytelen)
320 addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen);
321 }
322 argc--; argv++;
323 }
324
325 if (rtnl_open(&rth, 0) < 0)
326 exit(1);
327
328 if (mxrta->rta_len > RTA_LENGTH(0)) {
329 if (mxlock)
330 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_LOCK, mxlock);
331 addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta));
332 }
333
334 if (req.r.rtm_family == AF_UNSPEC)
335 req.r.rtm_family = AF_INET;
336
337 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
338 exit(2);
339
340 return 0;
341}
342
343static int rtnl_rtcache_request(struct rtnl_handle *rth, int family)
344{
345 struct {
346 struct nlmsghdr nlh;
347 struct rtmsg rtm;
348 } req;
349 struct sockaddr_nl nladdr;
350
351 memset(&nladdr, 0, sizeof(nladdr));
352 memset(&req, 0, sizeof(req));
353 nladdr.nl_family = AF_NETLINK;
354
355 req.nlh.nlmsg_len = sizeof(req);
356 req.nlh.nlmsg_type = RTM_GETROUTE;
357 req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST;
358 req.nlh.nlmsg_pid = 0;
359 req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
360 req.rtm.rtm_family = family;
361 req.rtm.rtm_flags |= RTM_F_CLONED;
362
363 return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
364}
365
366static int iproute_list(int argc, char **argv)
367{
368 int do_ipv6 = preferred_family;
369 struct rtnl_handle rth;
370 char *id = NULL;
371 char *od = NULL;
372
373 iproute_reset_filter();
374 filter.tb = RT_TABLE_MAIN;
375
376 while (argc > 0) {
377 if (matches(*argv, "protocol") == 0) {
378 int prot = 0;
379 NEXT_ARG();
380 filter.protocolmask = -1;
381 if (rtnl_rtprot_a2n(&prot, *argv)) {
382 if (strcmp(*argv, "all") != 0)
383 invarg("invalid \"protocol\"\n", *argv);
384 prot = 0;
385 filter.protocolmask = 0;
386 }
387 filter.protocol = prot;
388 } else if (strcmp(*argv, "dev") == 0 ||
389 strcmp(*argv, "oif") == 0) {
390 NEXT_ARG();
391 od = *argv;
392 } else if (strcmp(*argv, "iif") == 0) {
393 NEXT_ARG();
394 id = *argv;
395 } else if (matches(*argv, "from") == 0) {
396 NEXT_ARG();
397 if (matches(*argv, "root") == 0) {
398 NEXT_ARG();
399 get_prefix(&filter.rsrc, *argv, do_ipv6);
400 } else if (matches(*argv, "match") == 0) {
401 NEXT_ARG();
402 get_prefix(&filter.msrc, *argv, do_ipv6);
403 } else {
404 if (matches(*argv, "exact") == 0) {
405 NEXT_ARG();
406 }
407 get_prefix(&filter.msrc, *argv, do_ipv6);
408 filter.rsrc = filter.msrc;
409 }
410 } else {
411 if (matches(*argv, "to") == 0) {
412 NEXT_ARG();
413 }
414 if (matches(*argv, "root") == 0) {
415 NEXT_ARG();
416 get_prefix(&filter.rdst, *argv, do_ipv6);
417 } else if (matches(*argv, "match") == 0) {
418 NEXT_ARG();
419 get_prefix(&filter.mdst, *argv, do_ipv6);
420 } else {
421 if (matches(*argv, "exact") == 0) {
422 NEXT_ARG();
423 }
424 get_prefix(&filter.mdst, *argv, do_ipv6);
425 filter.rdst = filter.mdst;
426 }
427 }
428 argc--; argv++;
429 }
430
431 if (do_ipv6 == AF_UNSPEC && filter.tb)
432 do_ipv6 = AF_INET;
433
434 if (rtnl_open(&rth, 0) < 0)
435 exit(1);
436
437 ll_init_map(&rth);
438
439 if (id || od) {
440 int idx;
441
442 if (id) {
443 if ((idx = ll_name_to_index(id)) == 0) {
444 fprintf(stderr, "Cannot find device \"%s\"\n", id);
445 return -1;
446 }
447 filter.iif = idx;
448 filter.iifmask = -1;
449 }
450 if (od) {
451 if ((idx = ll_name_to_index(od)) == 0) {
452 fprintf(stderr, "Cannot find device \"%s\"\n", od);
453 return -1;
454 }
455 filter.oif = idx;
456 filter.oifmask = -1;
457 }
458 }
459
460 if (filter.tb != -1) {
461 if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
462 perror("Cannot send dump request");
463 exit(1);
464 }
465 } else {
466 if (rtnl_rtcache_request(&rth, do_ipv6) < 0) {
467 perror("Cannot send dump request");
468 exit(1);
469 }
470 }
471
472 if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
473 fprintf(stderr, "Dump terminated\n");
474 exit(1);
475 }
476
477 exit(0);
478}
479
480
481int iproute_get(int argc, char **argv)
482{
483 struct rtnl_handle rth;
484 struct {
485 struct nlmsghdr n;
486 struct rtmsg r;
487 char buf[1024];
488 } req;
489 char *idev = NULL;
490 char *odev = NULL;
491 int connected = 0;
492 int from_ok = 0;
493
494 memset(&req, 0, sizeof(req));
495
496 iproute_reset_filter();
497
498 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
499 req.n.nlmsg_flags = NLM_F_REQUEST;
500 req.n.nlmsg_type = RTM_GETROUTE;
501 req.r.rtm_family = preferred_family;
502 req.r.rtm_table = 0;
503 req.r.rtm_protocol = 0;
504 req.r.rtm_scope = 0;
505 req.r.rtm_type = 0;
506 req.r.rtm_src_len = 0;
507 req.r.rtm_dst_len = 0;
508 req.r.rtm_tos = 0;
509
510 while (argc > 0) {
511 if (matches(*argv, "from") == 0) {
512 inet_prefix addr;
513 NEXT_ARG();
514 from_ok = 1;
515 get_prefix(&addr, *argv, req.r.rtm_family);
516 if (req.r.rtm_family == AF_UNSPEC)
517 req.r.rtm_family = addr.family;
518 if (addr.bytelen)
519 addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen);
520 req.r.rtm_src_len = addr.bitlen;
521 } else if (matches(*argv, "iif") == 0) {
522 NEXT_ARG();
523 idev = *argv;
524 } else if (matches(*argv, "oif") == 0 ||
525 strcmp(*argv, "dev") == 0) {
526 NEXT_ARG();
527 odev = *argv;
528 } else if (matches(*argv, "notify") == 0) {
529 req.r.rtm_flags |= RTM_F_NOTIFY;
530 } else if (matches(*argv, "connected") == 0) {
531 connected = 1;
532 } else {
533 inet_prefix addr;
534 if (strcmp(*argv, "to") == 0) {
535 NEXT_ARG();
536 }
537 get_prefix(&addr, *argv, req.r.rtm_family);
538 if (req.r.rtm_family == AF_UNSPEC)
539 req.r.rtm_family = addr.family;
540 if (addr.bytelen)
541 addattr_l(&req.n, sizeof(req), RTA_DST, &addr.data, addr.bytelen);
542 req.r.rtm_dst_len = addr.bitlen;
543 }
544 argc--; argv++;
545 }
546
547 if (req.r.rtm_dst_len == 0) {
548 fprintf(stderr, "need at least destination address\n");
549 exit(1);
550 }
551
552 if (rtnl_open(&rth, 0) < 0)
553 exit(1);
554
555 ll_init_map(&rth);
556
557 if (idev || odev) {
558 int idx;
559
560 if (idev) {
561 if ((idx = ll_name_to_index(idev)) == 0) {
562 fprintf(stderr, "Cannot find device \"%s\"\n", idev);
563 return -1;
564 }
565 addattr32(&req.n, sizeof(req), RTA_IIF, idx);
566 }
567 if (odev) {
568 if ((idx = ll_name_to_index(odev)) == 0) {
569 fprintf(stderr, "Cannot find device \"%s\"\n", odev);
570 return -1;
571 }
572 addattr32(&req.n, sizeof(req), RTA_OIF, idx);
573 }
574 }
575
576 if (req.r.rtm_family == AF_UNSPEC)
577 req.r.rtm_family = AF_INET;
578
579 if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0)
580 exit(2);
581
582 if (connected && !from_ok) {
583 struct rtmsg *r = NLMSG_DATA(&req.n);
584 int len = req.n.nlmsg_len;
585 struct rtattr * tb[RTA_MAX+1];
586
587 if (print_route(NULL, &req.n, (void*)stdout) < 0) {
588 fprintf(stderr, "An error :-)\n");
589 exit(1);
590 }
591
592 if (req.n.nlmsg_type != RTM_NEWROUTE) {
593 fprintf(stderr, "Not a route?\n");
594 return -1;
595 }
596 len -= NLMSG_LENGTH(sizeof(*r));
597 if (len < 0) {
598 fprintf(stderr, "Wrong len %d\n", len);
599 return -1;
600 }
601
602 memset(tb, 0, sizeof(tb));
603 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
604
605 if (tb[RTA_PREFSRC]) {
606 tb[RTA_PREFSRC]->rta_type = RTA_SRC;
607 r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]);
608 } else if (!tb[RTA_SRC]) {
609 fprintf(stderr, "Failed to connect the route\n");
610 return -1;
611 }
612 if (!odev && tb[RTA_OIF])
613 tb[RTA_OIF]->rta_type = 0;
614 if (tb[RTA_GATEWAY])
615 tb[RTA_GATEWAY]->rta_type = 0;
616 if (!idev && tb[RTA_IIF])
617 tb[RTA_IIF]->rta_type = 0;
618 req.n.nlmsg_flags = NLM_F_REQUEST;
619 req.n.nlmsg_type = RTM_GETROUTE;
620
621 if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0)
622 exit(2);
623 }
624
625 if (print_route(NULL, &req.n, (void*)stdout) < 0) {
626 fprintf(stderr, "An error :-)\n");
627 exit(1);
628 }
629
630 exit(0);
631}
632
633void iproute_reset_filter()
634{
635 memset(&filter, 0, sizeof(filter));
636 filter.mdst.bitlen = -1;
637 filter.msrc.bitlen = -1;
638}
639
640int do_iproute(int argc, char **argv)
641{
642 if (argc < 1)
643 return iproute_list(0, NULL);
644
645 if (matches(*argv, "add") == 0)
646 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_EXCL,
647 argc-1, argv+1);
648 if (matches(*argv, "change") == 0 || strcmp(*argv, "chg") == 0)
649 return iproute_modify(RTM_NEWROUTE, NLM_F_REPLACE,
650 argc-1, argv+1);
651 if (matches(*argv, "replace") == 0)
652 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_REPLACE,
653 argc-1, argv+1);
654 if (matches(*argv, "prepend") == 0)
655 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE,
656 argc-1, argv+1);
657 if (matches(*argv, "append") == 0)
658 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_APPEND,
659 argc-1, argv+1);
660 if (matches(*argv, "test") == 0)
661 return iproute_modify(RTM_NEWROUTE, NLM_F_EXCL,
662 argc-1, argv+1);
663 if (matches(*argv, "delete") == 0)
664 return iproute_modify(RTM_DELROUTE, 0,
665 argc-1, argv+1);
666 if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
667 || matches(*argv, "lst") == 0)
668 return iproute_list(argc-1, argv+1);
669 if (matches(*argv, "get") == 0)
670 return iproute_get(argc-1, argv+1);
671 fprintf(stderr, "Command \"%s\" is unknown, try \"ip route help\".\n", *argv);
672 exit(-1);
673}
674