aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-11-23 06:15:38 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-11-23 06:15:38 +0100
commit0d56568654973a522bd005616b86d4dc8c833c81 (patch)
tree5ad6705c2868d1ed51a2411599d145a35536ecab
parent11f3a8b7ed366b23e4740fc847662a971cf65de3 (diff)
downloadbusybox-w32-0d56568654973a522bd005616b86d4dc8c833c81.tar.gz
busybox-w32-0d56568654973a522bd005616b86d4dc8c833c81.tar.bz2
busybox-w32-0d56568654973a522bd005616b86d4dc8c833c81.zip
traceroute: cleanup preparing it for traceroute6. -17 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/traceroute.c126
1 files changed, 63 insertions, 63 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c
index fa45db98a..d36ddee14 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -211,6 +211,13 @@
211#include <netinet/udp.h> 211#include <netinet/udp.h>
212#include <netinet/ip.h> 212#include <netinet/ip.h>
213#include <netinet/ip_icmp.h> 213#include <netinet/ip_icmp.h>
214#if ENABLE_FEATURE_IPV6
215# include <netinet/ip6.h>
216# include <netinet/icmp6.h>
217# ifndef SOL_IPV6
218# define SOL_IPV6 IPPROTO_IPV6
219# endif
220#endif
214 221
215#include "libbb.h" 222#include "libbb.h"
216#include "inet_common.h" 223#include "inet_common.h"
@@ -222,7 +229,9 @@
222# define IPPROTO_IP 0 229# define IPPROTO_IP 0
223#endif 230#endif
224 231
225/* Keep in sync with getopt32 call! */ 232
233#define OPT_STRING "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
234 IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:")
226enum { 235enum {
227 OPT_DONT_FRAGMNT = (1 << 0), /* F */ 236 OPT_DONT_FRAGMNT = (1 << 0), /* F */
228 OPT_USE_ICMP = (1 << 1) * ENABLE_FEATURE_TRACEROUTE_USE_ICMP, /* I */ 237 OPT_USE_ICMP = (1 << 1) * ENABLE_FEATURE_TRACEROUTE_USE_ICMP, /* I */
@@ -309,15 +318,15 @@ static int
309wait_for_reply(struct sockaddr_in *fromp) 318wait_for_reply(struct sockaddr_in *fromp)
310{ 319{
311 struct pollfd pfd[1]; 320 struct pollfd pfd[1];
312 int cc = 0; 321 int read_len = 0;
313 socklen_t fromlen = sizeof(*fromp); 322 socklen_t fromlen = sizeof(*fromp);
314 323
315 pfd[0].fd = rcvsock; 324 pfd[0].fd = rcvsock;
316 pfd[0].events = POLLIN; 325 pfd[0].events = POLLIN;
317 if (safe_poll(pfd, 1, waittime * 1000) > 0) 326 if (safe_poll(pfd, 1, waittime * 1000) > 0)
318 cc = recvfrom(rcvsock, recv_pkt, sizeof(recv_pkt), 0, 327 read_len = recvfrom(rcvsock, recv_pkt, sizeof(recv_pkt), 0,
319 (struct sockaddr *)fromp, &fromlen); 328 (struct sockaddr *)fromp, &fromlen);
320 return cc; 329 return read_len;
321} 330}
322 331
323/* 332/*
@@ -417,8 +426,7 @@ send_probe(int seq, int ttl)
417 len -= sizeof(*outudp); 426 len -= sizeof(*outudp);
418 set_nport(dest_lsa, htons(port + seq)); 427 set_nport(dest_lsa, htons(port + seq));
419 } 428 }
420 res = xsendto(sndsock, out, len, 429 res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len);
421 (struct sockaddr *)&dest_lsa->u.sa, dest_lsa->len);
422 if (res != len) { 430 if (res != len) {
423 bb_info_msg("sent %d octets, ret=%d", len, res); 431 bb_info_msg("sent %d octets, ret=%d", len, res);
424 } 432 }
@@ -447,11 +455,11 @@ pr_type(unsigned char t)
447#endif 455#endif
448 456
449#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE 457#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE
450#define packet_ok(cc, from, seq) \ 458#define packet_ok(read_len, from, seq) \
451 packet_ok(cc, seq) 459 packet_ok(read_len, seq)
452#endif 460#endif
453static int 461static int
454packet_ok(int cc, const struct sockaddr_in *from, int seq) 462packet_ok(int read_len, const struct sockaddr_in *from, int seq)
455{ 463{
456 const struct icmp *icp; 464 const struct icmp *icp;
457 unsigned char type, code; 465 unsigned char type, code;
@@ -460,15 +468,15 @@ packet_ok(int cc, const struct sockaddr_in *from, int seq)
460 468
461 ip = (struct ip *) recv_pkt; 469 ip = (struct ip *) recv_pkt;
462 hlen = ip->ip_hl << 2; 470 hlen = ip->ip_hl << 2;
463 if (cc < hlen + ICMP_MINLEN) { 471 if (read_len < hlen + ICMP_MINLEN) {
464#if ENABLE_FEATURE_TRACEROUTE_VERBOSE 472#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
465 if (verbose) 473 if (verbose)
466 printf("packet too short (%d bytes) from %s\n", cc, 474 printf("packet too short (%d bytes) from %s\n", read_len,
467 inet_ntoa(from->sin_addr)); 475 inet_ntoa(from->sin_addr));
468#endif 476#endif
469 return 0; 477 return 0;
470 } 478 }
471 cc -= hlen; 479 read_len -= hlen;
472 icp = (struct icmp *)(recv_pkt + hlen); 480 icp = (struct icmp *)(recv_pkt + hlen);
473 type = icp->icmp_type; 481 type = icp->icmp_type;
474 code = icp->icmp_code; 482 code = icp->icmp_code;
@@ -498,7 +506,7 @@ packet_ok(int cc, const struct sockaddr_in *from, int seq)
498 } 506 }
499 507
500 hicmp = (struct icmp *)((unsigned char *)hip + hlen); 508 hicmp = (struct icmp *)((unsigned char *)hip + hlen);
501 if (hlen + SIZEOF_ICMP_HDR <= cc 509 if (hlen + SIZEOF_ICMP_HDR <= read_len
502 && hip->ip_p == IPPROTO_ICMP 510 && hip->ip_p == IPPROTO_ICMP
503 && hicmp->icmp_id == htons(ident) 511 && hicmp->icmp_id == htons(ident)
504 && hicmp->icmp_seq == htons(seq) 512 && hicmp->icmp_seq == htons(seq)
@@ -507,7 +515,7 @@ packet_ok(int cc, const struct sockaddr_in *from, int seq)
507 } 515 }
508 } else { 516 } else {
509 up = (struct udphdr *)((char *)hip + hlen); 517 up = (struct udphdr *)((char *)hip + hlen);
510 if (hlen + 12 <= cc 518 if (hlen + 12 <= read_len
511 && hip->ip_p == IPPROTO_UDP 519 && hip->ip_p == IPPROTO_UDP
512// Off: since we do not form the entire IP packet, 520// Off: since we do not form the entire IP packet,
513// but defer it to kernel, we can't set source port, 521// but defer it to kernel, we can't set source port,
@@ -526,10 +534,10 @@ packet_ok(int cc, const struct sockaddr_in *from, int seq)
526 534
527 printf("\n%d bytes from %s to " 535 printf("\n%d bytes from %s to "
528 "%s: icmp type %d (%s) code %d\n", 536 "%s: icmp type %d (%s) code %d\n",
529 cc, inet_ntoa(from->sin_addr), 537 read_len, inet_ntoa(from->sin_addr),
530 inet_ntoa(ip->ip_dst), 538 inet_ntoa(ip->ip_dst),
531 type, pr_type(type), icp->icmp_code); 539 type, pr_type(type), icp->icmp_code);
532 for (i = 4; i < cc; i += sizeof(*lp)) 540 for (i = 4; i < read_len; i += sizeof(*lp))
533 printf("%2d: x%8.8x\n", i, *lp++); 541 printf("%2d: x%8.8x\n", i, *lp++);
534 } 542 }
535#endif 543#endif
@@ -542,34 +550,39 @@ packet_ok(int cc, const struct sockaddr_in *from, int seq)
542 * numeric value, otherwise try for symbolic name. 550 * numeric value, otherwise try for symbolic name.
543 */ 551 */
544static void 552static void
545print_inetname(const struct sockaddr_in *from) 553print_inetname(const struct sockaddr *from)
546{ 554{
547 const char *ina; 555 char *ina = xmalloc_sockaddr2dotted_noport(from);
548 556
549 ina = inet_ntoa(from->sin_addr); 557 if (option_mask32 & OPT_ADDR_NUM) {
550 if (option_mask32 & OPT_ADDR_NUM)
551 printf(" %s", ina); 558 printf(" %s", ina);
552 else { 559 } else {
553 char *n = NULL; 560 char *n = NULL;
554 if (from->sin_addr.s_addr != INADDR_ANY) 561
562 if (from->sa_family != AF_INET
563 || ((struct sockaddr_in*)from)->sin_addr.s_addr != INADDR_ANY
564 ) {
565 /* Try to reverse resolve if it is not 0.0.0.0 */
555 n = xmalloc_sockaddr2host_noport((struct sockaddr*)from); 566 n = xmalloc_sockaddr2host_noport((struct sockaddr*)from);
567 }
556 printf(" %s (%s)", (n ? n : ina), ina); 568 printf(" %s (%s)", (n ? n : ina), ina);
557 free(n); 569 free(n);
558 } 570 }
571 free(ina);
559} 572}
560 573
561static void 574static void
562print(int cc, const struct sockaddr_in *from) 575print(int read_len, const struct sockaddr_in *from)
563{ 576{
564 print_inetname(from); 577 print_inetname((const struct sockaddr*)from);
565 if (verbose) { 578 if (verbose) {
566 const struct ip *ip; 579 const struct ip *ip;
567 int hlen; 580 int hlen;
568 581
569 ip = (struct ip *) recv_pkt; 582 ip = (struct ip *) recv_pkt;
570 hlen = ip->ip_hl << 2; 583 hlen = ip->ip_hl << 2;
571 cc -= hlen; 584 read_len -= hlen;
572 printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst)); 585 printf(" %d bytes to %s", read_len, inet_ntoa(ip->ip_dst));
573 } 586 }
574} 587}
575 588
@@ -581,17 +594,16 @@ print_delta_ms(unsigned t1p, unsigned t2p)
581} 594}
582 595
583/* 596/*
584Usage: [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl] 597 * Usage: [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]
585[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos] 598 * [-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]
586[-w waittime] [-z pausemsecs] host [packetlen]" 599 * [-w waittime] [-z pausemsecs] host [packetlen]"
587*/ 600 */
588 601
589int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 602int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
590int traceroute_main(int argc, char **argv) 603int traceroute_main(int argc UNUSED_PARAM, char **argv)
591{ 604{
605 int i;
592 int minpacket; 606 int minpacket;
593 int ttl, i;
594 int seq = 0;
595 int tos = 0; 607 int tos = 0;
596 int max_ttl = 30; 608 int max_ttl = 30;
597 int nprobes = 3; 609 int nprobes = 3;
@@ -611,19 +623,14 @@ int traceroute_main(int argc, char **argv)
611 llist_t *source_route_list = NULL; 623 llist_t *source_route_list = NULL;
612 int lsrr = 0; 624 int lsrr = 0;
613#endif 625#endif
626 int ttl;
627 int seq;
614 628
615 INIT_G(); 629 INIT_G();
616 630
617#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 631 /* minimum 1 arg */
618 opt_complementary = "x-x:g::"; 632 opt_complementary = "-1:x-x" IF_FEATURE_TRACEROUTE_SOURCE_ROUTE(":g::");
619#else 633 op = getopt32(argv, OPT_STRING
620 opt_complementary = "x-x";
621#endif
622
623 op = getopt32(argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:"
624#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
625 "g:"
626#endif
627 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str 634 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str
628 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str 635 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str
629#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 636#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
@@ -681,17 +688,9 @@ int traceroute_main(int argc, char **argv)
681 688
682 /* Process destination and optional packet size */ 689 /* Process destination and optional packet size */
683 argv += optind; 690 argv += optind;
684 argc -= optind; 691 if (argv[1])
685 switch (argc) {
686 case 2:
687 packlen = xatoul_range(argv[1], minpacket, 32 * 1024); 692 packlen = xatoul_range(argv[1], minpacket, 32 * 1024);
688 /* Fall through */ 693 dest_lsa = xhost2sockaddr(argv[0], port);
689 case 1:
690 dest_lsa = xhost2sockaddr(argv[0], port);
691 break;
692 default:
693 bb_show_usage();
694 }
695 694
696 /* Ensure the socket fds won't be 0, 1 or 2 */ 695 /* Ensure the socket fds won't be 0, 1 or 2 */
697 bb_sanitize_stdio(); 696 bb_sanitize_stdio();
@@ -710,8 +709,7 @@ int traceroute_main(int argc, char **argv)
710 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock); 709 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock);
711 else 710 else
712 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); 711 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock);
713#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 712#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE && defined IP_OPTIONS
714#if defined(IP_OPTIONS)
715 if (lsrr > 0) { 713 if (lsrr > 0) {
716 unsigned char optlist[MAX_IPOPTLEN]; 714 unsigned char optlist[MAX_IPOPTLEN];
717 715
@@ -734,8 +732,7 @@ int traceroute_main(int argc, char **argv)
734 bb_perror_msg_and_die("IP_OPTIONS"); 732 bb_perror_msg_and_die("IP_OPTIONS");
735 } 733 }
736 } 734 }
737#endif /* IP_OPTIONS */ 735#endif
738#endif /* CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE */
739#ifdef SO_SNDBUF 736#ifdef SO_SNDBUF
740 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) { 737 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) {
741 bb_perror_msg_and_die("SO_SNDBUF"); 738 bb_perror_msg_and_die("SO_SNDBUF");
@@ -796,6 +793,7 @@ int traceroute_main(int argc, char **argv)
796 printf(" from %s", source); 793 printf(" from %s", source);
797 printf(", %d hops max, %d byte packets\n", max_ttl, packlen); 794 printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
798 795
796 seq = 0;
799 for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { 797 for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
800//TODO: make it protocol agnostic (get rid of sockaddr_in) 798//TODO: make it protocol agnostic (get rid of sockaddr_in)
801 struct sockaddr_in from; 799 struct sockaddr_in from;
@@ -808,7 +806,7 @@ int traceroute_main(int argc, char **argv)
808 806
809 printf("%2d", ttl); 807 printf("%2d", ttl);
810 for (probe = 0; probe < nprobes; ++probe) { 808 for (probe = 0; probe < nprobes; ++probe) {
811 int cc; 809 int read_len;
812 unsigned t1; 810 unsigned t1;
813 unsigned t2; 811 unsigned t2;
814 struct ip *ip; 812 struct ip *ip;
@@ -819,18 +817,18 @@ int traceroute_main(int argc, char **argv)
819 817
820 t1 = monotonic_us(); 818 t1 = monotonic_us();
821 send_probe(++seq, ttl); 819 send_probe(++seq, ttl);
822 first = 0;
823 820
824 while ((cc = wait_for_reply(&from)) != 0) { 821 first = 0;
822 while ((read_len = wait_for_reply(&from)) != 0) {
825 t2 = monotonic_us(); 823 t2 = monotonic_us();
826 i = packet_ok(cc, &from, seq); 824 i = packet_ok(read_len, &from, seq);
827 /* Skip short packet */ 825 /* Skip short packet */
828 if (i == 0) 826 if (i == 0)
829 continue; 827 continue;
830 if (!gotlastaddr 828 if (!gotlastaddr
831 || from.sin_addr.s_addr != lastaddr 829 || from.sin_addr.s_addr != lastaddr
832 ) { 830 ) {
833 print(cc, &from); 831 print(read_len, &from);
834 lastaddr = from.sin_addr.s_addr; 832 lastaddr = from.sin_addr.s_addr;
835 gotlastaddr = 1; 833 gotlastaddr = 1;
836 } 834 }
@@ -912,7 +910,8 @@ int traceroute_main(int argc, char **argv)
912 } 910 }
913 break; 911 break;
914 } 912 }
915 if (cc == 0) 913 /* there was no packet at all? */
914 if (read_len == 0)
916 printf(" *"); 915 printf(" *");
917 } 916 }
918 bb_putchar('\n'); 917 bb_putchar('\n');
@@ -922,5 +921,6 @@ int traceroute_main(int argc, char **argv)
922 break; 921 break;
923 } 922 }
924 } 923 }
924
925 return 0; 925 return 0;
926} 926}