aboutsummaryrefslogtreecommitdiff
path: root/networking/route.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-07-03 11:46:38 +0000
committerEric Andersen <andersen@codepoet.org>2002-07-03 11:46:38 +0000
commit51b8bd68bb22b1cc5d95e418813c2f08a194ec2b (patch)
tree905d4f1b1e557950272ac98e1540fa06f732f42f /networking/route.c
parent599e3ce163c43c3dfb24d06f8f707c783bc9ab9c (diff)
downloadbusybox-w32-51b8bd68bb22b1cc5d95e418813c2f08a194ec2b.tar.gz
busybox-w32-51b8bd68bb22b1cc5d95e418813c2f08a194ec2b.tar.bz2
busybox-w32-51b8bd68bb22b1cc5d95e418813c2f08a194ec2b.zip
This patch from Bart Visscher <magick@linux-fan.com> adds
IPV6 support to busybox. This patch does the following: * Add IPv6 support to libbb * Enable IPv6 interface address display * Add IPv6 config option * Adds ping6, an adaptation of the ping applet for IPv6 * Adds support routines for ping6: - xgethostbyname2 - create_icmp6_socket * Adds ifconfig support for IPv6 * Add support IPv6 to netstat * Add IPv6 support to route Thanks Bart!
Diffstat (limited to 'networking/route.c')
-rw-r--r--networking/route.c243
1 files changed, 240 insertions, 3 deletions
diff --git a/networking/route.c b/networking/route.c
index 26162ee87..76e76b4b7 100644
--- a/networking/route.c
+++ b/networking/route.c
@@ -1,7 +1,7 @@
1/* route 1/* route
2 * 2 *
3 * Similar to the standard Unix route, but with only the necessary 3 * Similar to the standard Unix route, but with only the necessary
4 * parts for AF_INET 4 * parts for AF_INET and AF_INET6
5 * 5 *
6 * Bjorn Wesen, Axis Communications AB 6 * Bjorn Wesen, Axis Communications AB
7 * 7 *
@@ -15,16 +15,19 @@
15 * Foundation; either version 2 of the License, or (at 15 * Foundation; either version 2 of the License, or (at
16 * your option) any later version. 16 * your option) any later version.
17 * 17 *
18 * $Id: route.c,v 1.16 2002/05/16 19:14:15 sandman Exp $ 18 * $Id: route.c,v 1.17 2002/07/03 11:46:34 andersen Exp $
19 * 19 *
20 * displayroute() code added by Vladimir N. Oleynik <dzo@simtreas.ru> 20 * displayroute() code added by Vladimir N. Oleynik <dzo@simtreas.ru>
21 * adjustments by Larry Doolittle <LRDoolittle@lbl.gov> 21 * adjustments by Larry Doolittle <LRDoolittle@lbl.gov>
22 *
23 * IPV6 support added by Bart Visscher <magick@linux-fan.com>
22 */ 24 */
23 25
24#include <sys/types.h> 26#include <sys/types.h>
25#include <sys/ioctl.h> 27#include <sys/ioctl.h>
26#include "inet_common.h" 28#include "inet_common.h"
27#include <net/route.h> 29#include <net/route.h>
30#include <net/if.h>
28#include <linux/param.h> // HZ 31#include <linux/param.h> // HZ
29#include <stdio.h> 32#include <stdio.h>
30#include <errno.h> 33#include <errno.h>
@@ -325,6 +328,139 @@ INET_setroute(int action, int options, char **args)
325 return EXIT_SUCCESS; 328 return EXIT_SUCCESS;
326} 329}
327 330
331#if CONFIG_FEATURE_IPV6
332static int INET6_setroute(int action, int options, char **args)
333{
334 struct in6_rtmsg rt;
335 struct ifreq ifr;
336 struct sockaddr_in6 sa6;
337 char target[128], gateway[128] = "NONE";
338 int metric, prefix_len;
339 char *devname = NULL;
340 char *cp;
341 int skfd;
342
343 if (*args == NULL)
344 show_usage();
345
346 strcpy(target, *args++);
347 if (!strcmp(target, "default")) {
348 prefix_len = 0;
349 memset(&sa6, 0, sizeof(sa6));
350 } else {
351 if ((cp = strchr(target, '/'))) {
352 prefix_len = atol(cp + 1);
353 if ((prefix_len < 0) || (prefix_len > 128))
354 show_usage();
355 *cp = 0;
356 } else {
357 prefix_len = 128;
358 }
359 if (INET6_resolve(target, (struct sockaddr_in6 *)&sa6) < 0) {
360 error_msg(_("can't resolve %s"), target);
361 return EXIT_FAILURE; /* XXX change to E_something */
362 }
363 }
364
365 /* Clean out the RTREQ structure. */
366 memset((char *) &rt, 0, sizeof(struct in6_rtmsg));
367
368 memcpy(&rt.rtmsg_dst, sa6.sin6_addr.s6_addr, sizeof(struct in6_addr));
369
370 /* Fill in the other fields. */
371 rt.rtmsg_flags = RTF_UP;
372 if (prefix_len == 128)
373 rt.rtmsg_flags |= RTF_HOST;
374 rt.rtmsg_metric = 1;
375 rt.rtmsg_dst_len = prefix_len;
376
377 while (*args) {
378 if (!strcmp(*args, "metric")) {
379
380 args++;
381 if (!*args || !isdigit(**args))
382 show_usage();
383 metric = atoi(*args);
384 rt.rtmsg_metric = metric;
385 args++;
386 continue;
387 }
388 if (!strcmp(*args, "gw") || !strcmp(*args, "gateway")) {
389 args++;
390 if (!*args)
391 show_usage();
392 if (rt.rtmsg_flags & RTF_GATEWAY)
393 show_usage();
394 strcpy(gateway, *args);
395 if (INET6_resolve(gateway, (struct sockaddr_in6 *)&sa6) < 0) {
396 error_msg(_("can't resolve gw %s"), gateway);
397 return (E_LOOKUP);
398 }
399 memcpy(&rt.rtmsg_gateway, sa6.sin6_addr.s6_addr,
400 sizeof(struct in6_addr));
401 rt.rtmsg_flags |= RTF_GATEWAY;
402 args++;
403 continue;
404 }
405 if (!strcmp(*args, "mod")) {
406 args++;
407 rt.rtmsg_flags |= RTF_MODIFIED;
408 continue;
409 }
410 if (!strcmp(*args, "dyn")) {
411 args++;
412 rt.rtmsg_flags |= RTF_DYNAMIC;
413 continue;
414 }
415 if (!strcmp(*args, "device") || !strcmp(*args, "dev")) {
416 args++;
417 if (!*args)
418 show_usage();
419 } else if (args[1])
420 show_usage();
421
422 devname = *args;
423 args++;
424 }
425
426 /* Create a socket to the INET6 kernel. */
427 if ((skfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
428 perror("socket");
429 return (E_SOCK);
430 }
431 if (devname) {
432 memset(&ifr, 0, sizeof(ifr));
433 strcpy(ifr.ifr_name, devname);
434
435 if (ioctl(skfd, SIOGIFINDEX, &ifr) < 0) {
436 perror("SIOGIFINDEX");
437 return (E_SOCK);
438 }
439 rt.rtmsg_ifindex = ifr.ifr_ifindex;
440 } else
441 rt.rtmsg_ifindex = 0;
442
443 /* Tell the kernel to accept this route. */
444 if (action == RTACTION_DEL) {
445 if (ioctl(skfd, SIOCDELRT, &rt) < 0) {
446 perror("SIOCDELRT");
447 close(skfd);
448 return (E_SOCK);
449 }
450 } else {
451 if (ioctl(skfd, SIOCADDRT, &rt) < 0) {
452 perror("SIOCADDRT");
453 close(skfd);
454 return (E_SOCK);
455 }
456 }
457
458 /* Close the socket. */
459 (void) close(skfd);
460 return (0);
461}
462#endif
463
328#ifndef RTF_UP 464#ifndef RTF_UP
329/* Keep this in sync with /usr/src/linux/include/linux/route.h */ 465/* Keep this in sync with /usr/src/linux/include/linux/route.h */
330#define RTF_UP 0x0001 /* route usable */ 466#define RTF_UP 0x0001 /* route usable */
@@ -418,17 +554,103 @@ void displayroutes(int noresolve, int netstatfmt)
418 } 554 }
419} 555}
420 556
557#if CONFIG_FEATURE_IPV6
558static void INET6_displayroutes(int noresolve)
559{
560 char buff[256];
561 char iface[16], flags[16];
562 char addr6[128], naddr6[128];
563 struct sockaddr_in6 saddr6, snaddr6;
564 int iflags, metric, refcnt, use, prefix_len, slen;
565 int numeric;
566
567 char addr6p[8][5], saddr6p[8][5], naddr6p[8][5];
568
569 FILE *fp = xfopen("/proc/net/ipv6_route", "r");
570 flags[0]='U';
571
572 if(noresolve)
573 noresolve = 0x0fff;
574 numeric = noresolve | 0x8000; /* default instead of * */
575
576 printf("Kernel IPv6 routing table\n"
577 "Destination "
578 "Next Hop "
579 "Flags Metric Ref Use Iface\n");
580
581 while( fgets(buff, sizeof(buff), fp) != NULL ) {
582 int ifl;
583
584 if(sscanf(buff, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
585 "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
586 "%4s%4s%4s%4s%4s%4s%4s%4s %08x %08x %08x %08x %s\n",
587 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
588 addr6p[4], addr6p[5], addr6p[6], addr6p[7],
589 &prefix_len,
590 saddr6p[0], saddr6p[1], saddr6p[2], saddr6p[3],
591 saddr6p[4], saddr6p[5], saddr6p[6], saddr6p[7],
592 &slen,
593 naddr6p[0], naddr6p[1], naddr6p[2], naddr6p[3],
594 naddr6p[4], naddr6p[5], naddr6p[6], naddr6p[7],
595 &metric, &use, &refcnt, &iflags, iface)!=31) {
596 error_msg_and_die( "Unsuported kernel route format\n");
597 }
598
599 ifl = 1; /* parse flags */
600 if (!(iflags & RTF_UP))
601 continue;
602 if (iflags & RTF_GATEWAY)
603 flags[ifl++]='G';
604 if (iflags & RTF_HOST)
605 flags[ifl++]='H';
606 if (iflags & RTF_DEFAULT)
607 flags[ifl++]='D';
608 if (iflags & RTF_ADDRCONF)
609 flags[ifl++]='A';
610 if (iflags & RTF_CACHE)
611 flags[ifl++]='C';
612 flags[ifl]=0;
613
614 /* Fetch and resolve the target address. */
615 snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s",
616 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
617 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
618 inet_pton(AF_INET6, addr6, (struct sockaddr *) &saddr6.sin6_addr);
619 saddr6.sin6_family=AF_INET6;
620
621 INET6_rresolve(addr6, sizeof(addr6), (struct sockaddr_in6 *) &saddr6, numeric);
622 snprintf(addr6, sizeof(addr6), "%s/%d", addr6, prefix_len);
623
624 /* Fetch and resolve the nexthop address. */
625 snprintf(naddr6, sizeof(naddr6), "%s:%s:%s:%s:%s:%s:%s:%s",
626 naddr6p[0], naddr6p[1], naddr6p[2], naddr6p[3],
627 naddr6p[4], naddr6p[5], naddr6p[6], naddr6p[7]);
628 inet_pton(AF_INET6, naddr6, (struct sockaddr *) &snaddr6.sin6_addr);
629 snaddr6.sin6_family=AF_INET6;
630
631 INET6_rresolve(naddr6, sizeof(naddr6), (struct sockaddr_in6 *) &snaddr6, numeric);
632
633 /* Print the info. */
634 printf("%-43s %-39s %-5s %-6d %-2d %7d %-8s\n",
635 addr6, naddr6, flags, metric, refcnt, use, iface);
636 }
637}
638#endif
639
421int route_main(int argc, char **argv) 640int route_main(int argc, char **argv)
422{ 641{
423 int opt; 642 int opt;
424 int what = 0; 643 int what = 0;
644#if CONFIG_FEATURE_IPV6
645 int af=AF_INET;
646#endif
425 647
426 if ( !argv [1] || ( argv [1][0] == '-' )) { 648 if ( !argv [1] || ( argv [1][0] == '-' )) {
427 /* check options */ 649 /* check options */
428 int noresolve = 0; 650 int noresolve = 0;
429 int extended = 0; 651 int extended = 0;
430 652
431 while ((opt = getopt(argc, argv, "ne")) > 0) { 653 while ((opt = getopt(argc, argv, "A:ne")) > 0) {
432 switch (opt) { 654 switch (opt) {
433 case 'n': 655 case 'n':
434 noresolve = 1; 656 noresolve = 1;
@@ -436,11 +658,22 @@ int route_main(int argc, char **argv)
436 case 'e': 658 case 'e':
437 extended = 1; 659 extended = 1;
438 break; 660 break;
661 case 'A':
662#if CONFIG_FEATURE_IPV6
663 if (strcmp(optarg, "inet6")==0)
664 af=AF_INET6;
665 break;
666#endif
439 default: 667 default:
440 show_usage ( ); 668 show_usage ( );
441 } 669 }
442 } 670 }
443 671
672#if CONFIG_FEATURE_IPV6
673 if (af==AF_INET6)
674 INET6_displayroutes(*argv != NULL);
675 else
676#endif
444 displayroutes ( noresolve, extended ); 677 displayroutes ( noresolve, extended );
445 return EXIT_SUCCESS; 678 return EXIT_SUCCESS;
446 } else { 679 } else {
@@ -455,5 +688,9 @@ int route_main(int argc, char **argv)
455 show_usage(); 688 show_usage();
456 } 689 }
457 690
691#if CONFIG_FEATURE_IPV6
692 if (af==AF_INET6)
693 return INET6_setroute(what, 0, argv+2);
694#endif
458 return INET_setroute(what, 0, argv+2 ); 695 return INET_setroute(what, 0, argv+2 );
459} 696}