diff options
-rw-r--r-- | libbb/xfuncs_printf.c | 2 | ||||
-rw-r--r-- | networking/traceroute.c | 218 |
2 files changed, 95 insertions, 125 deletions
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 46ae7ac60..cd0f84dea 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -440,7 +440,7 @@ void FAST_FUNC xlisten(int s, int backlog) | |||
440 | 440 | ||
441 | /* Die with an error message if sendto failed. | 441 | /* Die with an error message if sendto failed. |
442 | * Return bytes sent otherwise */ | 442 | * Return bytes sent otherwise */ |
443 | ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, | 443 | ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, |
444 | socklen_t tolen) | 444 | socklen_t tolen) |
445 | { | 445 | { |
446 | ssize_t ret = sendto(s, buf, len, 0, to, tolen); | 446 | ssize_t ret = sendto(s, buf, len, 0, to, tolen); |
diff --git a/networking/traceroute.c b/networking/traceroute.c index 5d1baacf5..958299aaa 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c | |||
@@ -223,11 +223,10 @@ | |||
223 | #define IPVERSION 4 | 223 | #define IPVERSION 4 |
224 | 224 | ||
225 | #ifndef IPPROTO_ICMP | 225 | #ifndef IPPROTO_ICMP |
226 | /* Grrrr.... */ | 226 | # define IPPROTO_ICMP 1 |
227 | #define IPPROTO_ICMP 1 | ||
228 | #endif | 227 | #endif |
229 | #ifndef IPPROTO_IP | 228 | #ifndef IPPROTO_IP |
230 | #define IPPROTO_IP 0 | 229 | # define IPPROTO_IP 0 |
231 | #endif | 230 | #endif |
232 | 231 | ||
233 | /* | 232 | /* |
@@ -482,7 +481,6 @@ ifaddrlist(struct IFADDRLIST **ipaddrp) | |||
482 | return nipaddr; | 481 | return nipaddr; |
483 | } | 482 | } |
484 | 483 | ||
485 | |||
486 | static void | 484 | static void |
487 | setsin(struct sockaddr_in *addr_sin, uint32_t addr) | 485 | setsin(struct sockaddr_in *addr_sin, uint32_t addr) |
488 | { | 486 | { |
@@ -494,7 +492,6 @@ setsin(struct sockaddr_in *addr_sin, uint32_t addr) | |||
494 | addr_sin->sin_addr.s_addr = addr; | 492 | addr_sin->sin_addr.s_addr = addr; |
495 | } | 493 | } |
496 | 494 | ||
497 | |||
498 | /* | 495 | /* |
499 | * Return the source address for the given destination address | 496 | * Return the source address for the given destination address |
500 | */ | 497 | */ |
@@ -547,13 +544,6 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from) | |||
547 | setsin(from, al->addr); | 544 | setsin(from, al->addr); |
548 | } | 545 | } |
549 | 546 | ||
550 | /* | ||
551 | "Usage: %s [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]\n" | ||
552 | "\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n" | ||
553 | "\t[-w waittime] [-z pausemsecs] host [packetlen]" | ||
554 | |||
555 | */ | ||
556 | |||
557 | static int | 547 | static int |
558 | wait_for_reply(int sock, struct sockaddr_in *fromp) | 548 | wait_for_reply(int sock, struct sockaddr_in *fromp) |
559 | { | 549 | { |
@@ -581,12 +571,12 @@ in_cksum(uint16_t *addr, int len) | |||
581 | int sum = 0; | 571 | int sum = 0; |
582 | 572 | ||
583 | /* | 573 | /* |
584 | * Our algorithm is simple, using a 32 bit accumulator (sum), | 574 | * Our algorithm is simple, using a 32 bit accumulator (sum), |
585 | * we add sequential 16 bit words to it, and at the end, fold | 575 | * we add sequential 16 bit words to it, and at the end, fold |
586 | * back all the carry bits from the top 16 bits into the lower | 576 | * back all the carry bits from the top 16 bits into the lower |
587 | * 16 bits. | 577 | * 16 bits. |
588 | */ | 578 | */ |
589 | while (nleft > 1) { | 579 | while (nleft > 1) { |
590 | sum += *w++; | 580 | sum += *w++; |
591 | nleft -= 2; | 581 | nleft -= 2; |
592 | } | 582 | } |
@@ -595,16 +585,13 @@ in_cksum(uint16_t *addr, int len) | |||
595 | if (nleft == 1) | 585 | if (nleft == 1) |
596 | sum += *(unsigned char *)w; | 586 | sum += *(unsigned char *)w; |
597 | 587 | ||
598 | /* | 588 | /* add back carry outs from top 16 bits to low 16 bits */ |
599 | * add back carry outs from top 16 bits to low 16 bits | ||
600 | */ | ||
601 | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | 589 | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ |
602 | sum += (sum >> 16); /* add carry */ | 590 | sum += (sum >> 16); /* add carry */ |
603 | answer = ~sum; /* truncate to 16 bits */ | 591 | answer = ~sum; /* truncate to 16 bits */ |
604 | return answer; | 592 | return answer; |
605 | } | 593 | } |
606 | 594 | ||
607 | |||
608 | static void | 595 | static void |
609 | send_probe(int seq, int ttl) | 596 | send_probe(int seq, int ttl) |
610 | { | 597 | { |
@@ -617,12 +604,10 @@ send_probe(int seq, int ttl) | |||
617 | 604 | ||
618 | /* | 605 | /* |
619 | * In most cases, the kernel will recalculate the ip checksum. | 606 | * In most cases, the kernel will recalculate the ip checksum. |
620 | * But we must do it anyway so that the udp checksum comes out | 607 | * But we must do it anyway so that the udp checksum comes out right. |
621 | * right. | ||
622 | */ | 608 | */ |
623 | if (doipcksum) { | 609 | if (doipcksum) { |
624 | outip->ip_sum = | 610 | outip->ip_sum = in_cksum((uint16_t *)outip, sizeof(*outip) + optlen); |
625 | in_cksum((uint16_t *)outip, sizeof(*outip) + optlen); | ||
626 | if (outip->ip_sum == 0) | 611 | if (outip->ip_sum == 0) |
627 | outip->ip_sum = 0xffff; | 612 | outip->ip_sum = 0xffff; |
628 | } | 613 | } |
@@ -645,7 +630,7 @@ send_probe(int seq, int ttl) | |||
645 | /* Always calculate checksum for icmp packets */ | 630 | /* Always calculate checksum for icmp packets */ |
646 | outicmp->icmp_cksum = 0; | 631 | outicmp->icmp_cksum = 0; |
647 | outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp, | 632 | outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp, |
648 | packlen - (sizeof(*outip) + optlen)); | 633 | packlen - (sizeof(*outip) + optlen)); |
649 | if (outicmp->icmp_cksum == 0) | 634 | if (outicmp->icmp_cksum == 0) |
650 | outicmp->icmp_cksum = 0xffff; | 635 | outicmp->icmp_cksum = 0xffff; |
651 | } else | 636 | } else |
@@ -656,7 +641,7 @@ send_probe(int seq, int ttl) | |||
656 | ui = (struct udpiphdr *)outip; | 641 | ui = (struct udpiphdr *)outip; |
657 | oui = (struct udpiphdr *)&tip; | 642 | oui = (struct udpiphdr *)&tip; |
658 | /* Easier to zero and put back things that are ok */ | 643 | /* Easier to zero and put back things that are ok */ |
659 | memset((char *)ui, 0, sizeof(ui->ui_i)); | 644 | memset(ui, 0, sizeof(ui->ui_i)); |
660 | ui->ui_src = oui->ui_src; | 645 | ui->ui_src = oui->ui_src; |
661 | ui->ui_dst = oui->ui_dst; | 646 | ui->ui_dst = oui->ui_dst; |
662 | ui->ui_pr = oui->ui_pr; | 647 | ui->ui_pr = oui->ui_pr; |
@@ -668,7 +653,8 @@ send_probe(int seq, int ttl) | |||
668 | *outip = tip; | 653 | *outip = tip; |
669 | } | 654 | } |
670 | 655 | ||
671 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | 656 | //BUG! verbose is (x & OPT_VERBOSE), not a counter! |
657 | #if 0 //ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
672 | /* XXX undocumented debugging hack */ | 658 | /* XXX undocumented debugging hack */ |
673 | if (verbose > 1) { | 659 | if (verbose > 1) { |
674 | const uint16_t *sp; | 660 | const uint16_t *sp; |
@@ -695,15 +681,15 @@ send_probe(int seq, int ttl) | |||
695 | 681 | ||
696 | #if !defined(IP_HDRINCL) && defined(IP_TTL) | 682 | #if !defined(IP_HDRINCL) && defined(IP_TTL) |
697 | if (setsockopt(sndsock, IPPROTO_IP, IP_TTL, | 683 | if (setsockopt(sndsock, IPPROTO_IP, IP_TTL, |
698 | (char *)&ttl, sizeof(ttl)) < 0) { | 684 | (char *)&ttl, sizeof(ttl)) < 0) { |
699 | bb_perror_msg_and_die("setsockopt ttl %d", ttl); | 685 | bb_perror_msg_and_die("setsockopt ttl %d", ttl); |
700 | } | 686 | } |
701 | #endif | 687 | #endif |
702 | 688 | ||
703 | cc = xsendto(sndsock, (char *)outip, | 689 | cc = xsendto(sndsock, outip, packlen, |
704 | packlen, (struct sockaddr *)&whereto, sizeof(whereto)); | 690 | (struct sockaddr *)&whereto, sizeof(whereto)); |
705 | if (cc != packlen) { | 691 | if (cc != packlen) { |
706 | bb_info_msg("wrote %s %d chars, ret=%d", hostname, packlen, cc); | 692 | bb_info_msg("sent %s %d octets, ret=%d", hostname, packlen, cc); |
707 | } | 693 | } |
708 | } | 694 | } |
709 | 695 | ||
@@ -722,7 +708,7 @@ pr_type(unsigned char t) | |||
722 | "Info Reply", "Mask Request", "Mask Reply" | 708 | "Info Reply", "Mask Request", "Mask Reply" |
723 | }; | 709 | }; |
724 | 710 | ||
725 | if (t > 18) | 711 | if (t >= ARRAY_SIZE(ttab)) |
726 | return "OUT-OF-RANGE"; | 712 | return "OUT-OF-RANGE"; |
727 | 713 | ||
728 | return ttab[t]; | 714 | return ttab[t]; |
@@ -734,12 +720,12 @@ pr_type(unsigned char t) | |||
734 | packet_ok(buf, cc, seq) | 720 | packet_ok(buf, cc, seq) |
735 | #endif | 721 | #endif |
736 | static int | 722 | static int |
737 | packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq) | 723 | packet_ok(const unsigned char *buf, int cc, const struct sockaddr_in *from, int seq) |
738 | { | 724 | { |
739 | struct icmp *icp; | 725 | const struct icmp *icp; |
740 | unsigned char type, code; | 726 | unsigned char type, code; |
741 | int hlen; | 727 | int hlen; |
742 | struct ip *ip; | 728 | const struct ip *ip; |
743 | 729 | ||
744 | ip = (struct ip *) buf; | 730 | ip = (struct ip *) buf; |
745 | hlen = ip->ip_hl << 2; | 731 | hlen = ip->ip_hl << 2; |
@@ -756,15 +742,16 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq) | |||
756 | type = icp->icmp_type; | 742 | type = icp->icmp_type; |
757 | code = icp->icmp_code; | 743 | code = icp->icmp_code; |
758 | /* Path MTU Discovery (RFC1191) */ | 744 | /* Path MTU Discovery (RFC1191) */ |
759 | if (code != ICMP_UNREACH_NEEDFRAG) | 745 | pmtu = 0; |
760 | pmtu = 0; | 746 | if (code == ICMP_UNREACH_NEEDFRAG) |
761 | else { | ||
762 | pmtu = ntohs(icp->icmp_nextmtu); | 747 | pmtu = ntohs(icp->icmp_nextmtu); |
763 | } | 748 | |
764 | if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || | 749 | if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) |
765 | type == ICMP_UNREACH || type == ICMP_ECHOREPLY) { | 750 | || type == ICMP_UNREACH |
766 | struct ip *hip; | 751 | || type == ICMP_ECHOREPLY |
767 | struct udphdr *up; | 752 | ) { |
753 | const struct ip *hip; | ||
754 | const struct udphdr *up; | ||
768 | 755 | ||
769 | hip = &icp->icmp_ip; | 756 | hip = &icp->icmp_ip; |
770 | hlen = hip->ip_hl << 2; | 757 | hlen = hip->ip_hl << 2; |
@@ -804,8 +791,9 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq) | |||
804 | 791 | ||
805 | printf("\n%d bytes from %s to " | 792 | printf("\n%d bytes from %s to " |
806 | "%s: icmp type %d (%s) code %d\n", | 793 | "%s: icmp type %d (%s) code %d\n", |
807 | cc, inet_ntoa(from->sin_addr), | 794 | cc, inet_ntoa(from->sin_addr), |
808 | inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); | 795 | inet_ntoa(ip->ip_dst), |
796 | type, pr_type(type), icp->icmp_code); | ||
809 | for (i = 4; i < cc; i += sizeof(*lp)) | 797 | for (i = 4; i < cc; i += sizeof(*lp)) |
810 | printf("%2d: x%8.8x\n", i, *lp++); | 798 | printf("%2d: x%8.8x\n", i, *lp++); |
811 | } | 799 | } |
@@ -813,14 +801,13 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq) | |||
813 | return 0; | 801 | return 0; |
814 | } | 802 | } |
815 | 803 | ||
816 | |||
817 | /* | 804 | /* |
818 | * Construct an Internet address representation. | 805 | * Construct an Internet address representation. |
819 | * If the nflag has been supplied, give | 806 | * If the -n flag has been supplied, give |
820 | * numeric value, otherwise try for symbolic name. | 807 | * numeric value, otherwise try for symbolic name. |
821 | */ | 808 | */ |
822 | static void | 809 | static void |
823 | print_inetname(struct sockaddr_in *from) | 810 | print_inetname(const struct sockaddr_in *from) |
824 | { | 811 | { |
825 | const char *ina; | 812 | const char *ina; |
826 | 813 | ||
@@ -837,9 +824,9 @@ print_inetname(struct sockaddr_in *from) | |||
837 | } | 824 | } |
838 | 825 | ||
839 | static void | 826 | static void |
840 | print(unsigned char *buf, int cc, struct sockaddr_in *from) | 827 | print(const unsigned char *buf, int cc, const struct sockaddr_in *from) |
841 | { | 828 | { |
842 | struct ip *ip; | 829 | const struct ip *ip; |
843 | int hlen; | 830 | int hlen; |
844 | 831 | ||
845 | ip = (struct ip *) buf; | 832 | ip = (struct ip *) buf; |
@@ -853,7 +840,6 @@ print(unsigned char *buf, int cc, struct sockaddr_in *from) | |||
853 | #endif | 840 | #endif |
854 | } | 841 | } |
855 | 842 | ||
856 | |||
857 | static struct hostinfo * | 843 | static struct hostinfo * |
858 | gethostinfo(const char *host) | 844 | gethostinfo(const char *host) |
859 | { | 845 | { |
@@ -910,15 +896,19 @@ static void | |||
910 | print_delta_ms(unsigned t1p, unsigned t2p) | 896 | print_delta_ms(unsigned t1p, unsigned t2p) |
911 | { | 897 | { |
912 | unsigned tt = t2p - t1p; | 898 | unsigned tt = t2p - t1p; |
913 | printf(" %u.%03u ms", tt/1000, tt%1000); | 899 | printf(" %u.%03u ms", tt / 1000, tt % 1000); |
914 | } | 900 | } |
915 | 901 | ||
902 | /* | ||
903 | "Usage: %s [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]\n" | ||
904 | "\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n" | ||
905 | "\t[-w waittime] [-z pausemsecs] host [packetlen]" | ||
906 | */ | ||
907 | |||
916 | int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 908 | int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
917 | int traceroute_main(int argc, char **argv) | 909 | int traceroute_main(int argc, char **argv) |
918 | { | 910 | { |
919 | int code, n; | ||
920 | unsigned char *outp; | 911 | unsigned char *outp; |
921 | uint32_t *ap; | ||
922 | struct sockaddr_in *from; | 912 | struct sockaddr_in *from; |
923 | struct sockaddr_in *to; | 913 | struct sockaddr_in *to; |
924 | struct hostinfo *hi; | 914 | struct hostinfo *hi; |
@@ -931,7 +921,6 @@ int traceroute_main(int argc, char **argv) | |||
931 | #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE | 921 | #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE |
932 | int lsrr = 0; | 922 | int lsrr = 0; |
933 | #endif | 923 | #endif |
934 | uint16_t off = 0; | ||
935 | struct IFADDRLIST *al; | 924 | struct IFADDRLIST *al; |
936 | char *device; | 925 | char *device; |
937 | int max_ttl = 30; | 926 | int max_ttl = 30; |
@@ -952,7 +941,6 @@ int traceroute_main(int argc, char **argv) | |||
952 | from = (struct sockaddr_in *)&wherefrom; | 941 | from = (struct sockaddr_in *)&wherefrom; |
953 | to = (struct sockaddr_in *)&whereto; | 942 | to = (struct sockaddr_in *)&whereto; |
954 | 943 | ||
955 | //opterr = 0; | ||
956 | #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE | 944 | #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE |
957 | opt_complementary = "x-x:g::"; | 945 | opt_complementary = "x-x:g::"; |
958 | #else | 946 | #else |
@@ -970,8 +958,6 @@ int traceroute_main(int argc, char **argv) | |||
970 | #endif | 958 | #endif |
971 | ); | 959 | ); |
972 | 960 | ||
973 | if (op & OPT_DONT_FRAGMNT) | ||
974 | off = IP_DF; | ||
975 | if (op & OPT_IP_CHKSUM) { | 961 | if (op & OPT_IP_CHKSUM) { |
976 | doipcksum = 0; | 962 | doipcksum = 0; |
977 | bb_error_msg("warning: ip checksums disabled"); | 963 | bb_error_msg("warning: ip checksums disabled"); |
@@ -989,15 +975,15 @@ int traceroute_main(int argc, char **argv) | |||
989 | * set the ip source address of the outbound | 975 | * set the ip source address of the outbound |
990 | * probe (e.g., on a multi-homed host). | 976 | * probe (e.g., on a multi-homed host). |
991 | */ | 977 | */ |
992 | if (getuid()) | 978 | if (getuid() != 0) |
993 | bb_error_msg_and_die("-s %s: permission denied", source); | 979 | bb_error_msg_and_die("you must be root to use -s"); |
994 | } | 980 | } |
995 | if (op & OPT_WAITTIME) | 981 | if (op & OPT_WAITTIME) |
996 | waittime = xatou_range(waittime_str, 2, 24 * 60 * 60); | 982 | waittime = xatou_range(waittime_str, 2, 24 * 60 * 60); |
997 | if (op & OPT_PAUSE_MS) | 983 | if (op & OPT_PAUSE_MS) |
998 | pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); | 984 | pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); |
999 | if (op & OPT_FIRST_TTL) | 985 | if (op & OPT_FIRST_TTL) |
1000 | first_ttl = xatou_range(first_ttl_str, 1, 255); | 986 | first_ttl = xatou_range(first_ttl_str, 1, max_ttl); |
1001 | 987 | ||
1002 | #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE | 988 | #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE |
1003 | if (source_route_list) { | 989 | if (source_route_list) { |
@@ -1011,12 +997,6 @@ int traceroute_main(int argc, char **argv) | |||
1011 | } | 997 | } |
1012 | #endif | 998 | #endif |
1013 | 999 | ||
1014 | if (first_ttl > max_ttl) { | ||
1015 | bb_error_msg_and_die( | ||
1016 | "first ttl (%d) may not be greater than max ttl (%d)", | ||
1017 | first_ttl, max_ttl); | ||
1018 | } | ||
1019 | |||
1020 | minpacket = sizeof(*outip) + sizeof(*outdata) + optlen; | 1000 | minpacket = sizeof(*outip) + sizeof(*outdata) + optlen; |
1021 | 1001 | ||
1022 | #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP | 1002 | #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP |
@@ -1028,14 +1008,14 @@ int traceroute_main(int argc, char **argv) | |||
1028 | packlen = minpacket; /* minimum sized packet */ | 1008 | packlen = minpacket; /* minimum sized packet */ |
1029 | 1009 | ||
1030 | /* Process destination and optional packet size */ | 1010 | /* Process destination and optional packet size */ |
1031 | switch (argc - optind) { | 1011 | argv += optind; |
1032 | 1012 | argc -= optind; | |
1013 | switch (argc) { | ||
1033 | case 2: | 1014 | case 2: |
1034 | packlen = xatoul_range(argv[optind + 1], minpacket, maxpacket); | 1015 | packlen = xatoul_range(argv[1], minpacket, maxpacket); |
1035 | /* Fall through */ | 1016 | /* Fall through */ |
1036 | |||
1037 | case 1: | 1017 | case 1: |
1038 | hostname = argv[optind]; | 1018 | hostname = argv[0]; |
1039 | hi = gethostinfo(hostname); | 1019 | hi = gethostinfo(hostname); |
1040 | setsin(to, hi->addrs[0]); | 1020 | setsin(to, hi->addrs[0]); |
1041 | if (hi->n > 1) | 1021 | if (hi->n > 1) |
@@ -1045,7 +1025,6 @@ int traceroute_main(int argc, char **argv) | |||
1045 | hi->name = NULL; | 1025 | hi->name = NULL; |
1046 | freehostinfo(hi); | 1026 | freehostinfo(hi); |
1047 | break; | 1027 | break; |
1048 | |||
1049 | default: | 1028 | default: |
1050 | bb_show_usage(); | 1029 | bb_show_usage(); |
1051 | } | 1030 | } |
@@ -1081,12 +1060,12 @@ int traceroute_main(int argc, char **argv) | |||
1081 | optlist[1] = IPOPT_LSRR; | 1060 | optlist[1] = IPOPT_LSRR; |
1082 | i = lsrr * sizeof(gwlist[0]); | 1061 | i = lsrr * sizeof(gwlist[0]); |
1083 | optlist[2] = i + 3; | 1062 | optlist[2] = i + 3; |
1084 | /* Pointer to LSRR addresses */ | 1063 | /* pointer to LSRR addresses */ |
1085 | optlist[3] = IPOPT_MINOFF; | 1064 | optlist[3] = IPOPT_MINOFF; |
1086 | memcpy(optlist + 4, gwlist, i); | 1065 | memcpy(optlist + 4, gwlist, i); |
1087 | 1066 | ||
1088 | if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, | 1067 | if (setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, |
1089 | (char *)optlist, i + sizeof(gwlist[0]))) < 0) { | 1068 | (char *)optlist, i + sizeof(gwlist[0])) < 0) { |
1090 | bb_perror_msg_and_die("IP_OPTIONS"); | 1069 | bb_perror_msg_and_die("IP_OPTIONS"); |
1091 | } | 1070 | } |
1092 | } | 1071 | } |
@@ -1106,7 +1085,7 @@ int traceroute_main(int argc, char **argv) | |||
1106 | } | 1085 | } |
1107 | #else | 1086 | #else |
1108 | #ifdef IP_TOS | 1087 | #ifdef IP_TOS |
1109 | if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) { | 1088 | if ((op & OPT_TOS) && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) { |
1110 | bb_perror_msg_and_die("setsockopt tos %d", tos); | 1089 | bb_perror_msg_and_die("setsockopt tos %d", tos); |
1111 | } | 1090 | } |
1112 | #endif | 1091 | #endif |
@@ -1127,10 +1106,11 @@ int traceroute_main(int argc, char **argv) | |||
1127 | outip = xzalloc(packlen); | 1106 | outip = xzalloc(packlen); |
1128 | 1107 | ||
1129 | outip->ip_v = IPVERSION; | 1108 | outip->ip_v = IPVERSION; |
1130 | if (tos_str) | 1109 | if (op & OPT_TOS) |
1131 | outip->ip_tos = tos; | 1110 | outip->ip_tos = tos; |
1132 | outip->ip_len = htons(packlen); | 1111 | outip->ip_len = htons(packlen); |
1133 | outip->ip_off = htons(off); | 1112 | if (op & OPT_DONT_FRAGMNT) |
1113 | outip->ip_off = htons(IP_DF); | ||
1134 | outp = (unsigned char *)(outip + 1); | 1114 | outp = (unsigned char *)(outip + 1); |
1135 | outip->ip_dst = to->sin_addr; | 1115 | outip->ip_dst = to->sin_addr; |
1136 | 1116 | ||
@@ -1153,12 +1133,11 @@ int traceroute_main(int argc, char **argv) | |||
1153 | outdata = (outdata_t *)(outudp + 1); | 1133 | outdata = (outdata_t *)(outudp + 1); |
1154 | } | 1134 | } |
1155 | 1135 | ||
1156 | /* Get the interface address list */ | ||
1157 | n = ifaddrlist(&al); | ||
1158 | |||
1159 | /* Look for a specific device */ | 1136 | /* Look for a specific device */ |
1160 | if (op & OPT_DEVICE) { | 1137 | if (op & OPT_DEVICE) { |
1161 | for (i = n; i > 0; --i, ++al) | 1138 | /* Get the interface address list */ |
1139 | int n = ifaddrlist(&al); | ||
1140 | for (; n > 0; --n, ++al) | ||
1162 | if (strcmp(device, al->device) == 0) | 1141 | if (strcmp(device, al->device) == 0) |
1163 | goto found_dev; | 1142 | goto found_dev; |
1164 | bb_error_msg_and_die("can't find interface %s", device); | 1143 | bb_error_msg_and_die("can't find interface %s", device); |
@@ -1185,6 +1164,7 @@ int traceroute_main(int argc, char **argv) | |||
1185 | * there are more than one). | 1164 | * there are more than one). |
1186 | */ | 1165 | */ |
1187 | if (op & OPT_DEVICE) { | 1166 | if (op & OPT_DEVICE) { |
1167 | uint32_t *ap; | ||
1188 | for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) | 1168 | for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) |
1189 | if (*ap == al->addr) | 1169 | if (*ap == al->addr) |
1190 | goto found_dev2; | 1170 | goto found_dev2; |
@@ -1197,7 +1177,7 @@ int traceroute_main(int argc, char **argv) | |||
1197 | if (hi->n > 1) | 1177 | if (hi->n > 1) |
1198 | bb_error_msg( | 1178 | bb_error_msg( |
1199 | "warning: %s has multiple addresses; using %s", | 1179 | "warning: %s has multiple addresses; using %s", |
1200 | source, inet_ntoa(from->sin_addr)); | 1180 | source, inet_ntoa(from->sin_addr)); |
1201 | } | 1181 | } |
1202 | freehostinfo(hi); | 1182 | freehostinfo(hi); |
1203 | } | 1183 | } |
@@ -1211,7 +1191,6 @@ int traceroute_main(int argc, char **argv) | |||
1211 | if (op & OPT_SOURCE) | 1191 | if (op & OPT_SOURCE) |
1212 | printf(" from %s", source); | 1192 | printf(" from %s", source); |
1213 | printf(", %d hops max, %d byte packets\n", max_ttl, packlen); | 1193 | printf(", %d hops max, %d byte packets\n", max_ttl, packlen); |
1214 | fflush(stdout); | ||
1215 | 1194 | ||
1216 | for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { | 1195 | for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { |
1217 | uint32_t lastaddr = 0; | 1196 | uint32_t lastaddr = 0; |
@@ -1229,17 +1208,21 @@ int traceroute_main(int argc, char **argv) | |||
1229 | 1208 | ||
1230 | if (sentfirst && pausemsecs > 0) | 1209 | if (sentfirst && pausemsecs > 0) |
1231 | usleep(pausemsecs * 1000); | 1210 | usleep(pausemsecs * 1000); |
1211 | fflush(stdout); | ||
1212 | |||
1232 | t1 = monotonic_us(); | 1213 | t1 = monotonic_us(); |
1233 | send_probe(++seq, ttl); | 1214 | send_probe(++seq, ttl); |
1234 | ++sentfirst; | 1215 | ++sentfirst; |
1216 | |||
1235 | while ((cc = wait_for_reply(rcvsock, from)) != 0) { | 1217 | while ((cc = wait_for_reply(rcvsock, from)) != 0) { |
1236 | t2 = monotonic_us(); | 1218 | t2 = monotonic_us(); |
1237 | i = packet_ok(packet, cc, from, seq); | 1219 | i = packet_ok(packet, cc, from, seq); |
1238 | /* Skip short packet */ | 1220 | /* Skip short packet */ |
1239 | if (i == 0) | 1221 | if (i == 0) |
1240 | continue; | 1222 | continue; |
1241 | if (!gotlastaddr || | 1223 | if (!gotlastaddr |
1242 | from->sin_addr.s_addr != lastaddr) { | 1224 | || from->sin_addr.s_addr != lastaddr |
1225 | ) { | ||
1243 | print(packet, cc, from); | 1226 | print(packet, cc, from); |
1244 | lastaddr = from->sin_addr.s_addr; | 1227 | lastaddr = from->sin_addr.s_addr; |
1245 | ++gotlastaddr; | 1228 | ++gotlastaddr; |
@@ -1251,99 +1234,86 @@ int traceroute_main(int argc, char **argv) | |||
1251 | if (i == -2) { | 1234 | if (i == -2) { |
1252 | if (ip->ip_ttl <= 1) | 1235 | if (ip->ip_ttl <= 1) |
1253 | printf(" !"); | 1236 | printf(" !"); |
1254 | ++got_there; | 1237 | got_there = 1; |
1255 | break; | 1238 | break; |
1256 | } | 1239 | } |
1257 | /* time exceeded in transit */ | 1240 | /* time exceeded in transit */ |
1258 | if (i == -1) | 1241 | if (i == -1) |
1259 | break; | 1242 | break; |
1260 | code = i - 1; | 1243 | i--; |
1261 | switch (code) { | 1244 | switch (i) { |
1262 | |||
1263 | case ICMP_UNREACH_PORT: | 1245 | case ICMP_UNREACH_PORT: |
1264 | if (ip->ip_ttl <= 1) | 1246 | if (ip->ip_ttl <= 1) |
1265 | printf(" !"); | 1247 | printf(" !"); |
1266 | ++got_there; | 1248 | got_there = 1; |
1267 | break; | 1249 | break; |
1268 | |||
1269 | case ICMP_UNREACH_NET: | 1250 | case ICMP_UNREACH_NET: |
1270 | ++unreachable; | ||
1271 | printf(" !N"); | 1251 | printf(" !N"); |
1252 | ++unreachable; | ||
1272 | break; | 1253 | break; |
1273 | |||
1274 | case ICMP_UNREACH_HOST: | 1254 | case ICMP_UNREACH_HOST: |
1275 | ++unreachable; | ||
1276 | printf(" !H"); | 1255 | printf(" !H"); |
1256 | ++unreachable; | ||
1277 | break; | 1257 | break; |
1278 | |||
1279 | case ICMP_UNREACH_PROTOCOL: | 1258 | case ICMP_UNREACH_PROTOCOL: |
1280 | ++got_there; | ||
1281 | printf(" !P"); | 1259 | printf(" !P"); |
1260 | got_there = 1; | ||
1282 | break; | 1261 | break; |
1283 | |||
1284 | case ICMP_UNREACH_NEEDFRAG: | 1262 | case ICMP_UNREACH_NEEDFRAG: |
1285 | ++unreachable; | ||
1286 | printf(" !F-%d", pmtu); | 1263 | printf(" !F-%d", pmtu); |
1264 | ++unreachable; | ||
1287 | break; | 1265 | break; |
1288 | |||
1289 | case ICMP_UNREACH_SRCFAIL: | 1266 | case ICMP_UNREACH_SRCFAIL: |
1290 | ++unreachable; | ||
1291 | printf(" !S"); | 1267 | printf(" !S"); |
1268 | ++unreachable; | ||
1292 | break; | 1269 | break; |
1293 | |||
1294 | case ICMP_UNREACH_FILTER_PROHIB: | 1270 | case ICMP_UNREACH_FILTER_PROHIB: |
1295 | case ICMP_UNREACH_NET_PROHIB: /* misuse */ | 1271 | case ICMP_UNREACH_NET_PROHIB: /* misuse */ |
1296 | ++unreachable; | ||
1297 | printf(" !A"); | 1272 | printf(" !A"); |
1273 | ++unreachable; | ||
1298 | break; | 1274 | break; |
1299 | |||
1300 | case ICMP_UNREACH_HOST_PROHIB: | 1275 | case ICMP_UNREACH_HOST_PROHIB: |
1301 | ++unreachable; | ||
1302 | printf(" !C"); | 1276 | printf(" !C"); |
1277 | ++unreachable; | ||
1303 | break; | 1278 | break; |
1304 | |||
1305 | case ICMP_UNREACH_HOST_PRECEDENCE: | 1279 | case ICMP_UNREACH_HOST_PRECEDENCE: |
1306 | ++unreachable; | ||
1307 | printf(" !V"); | 1280 | printf(" !V"); |
1281 | ++unreachable; | ||
1308 | break; | 1282 | break; |
1309 | |||
1310 | case ICMP_UNREACH_PRECEDENCE_CUTOFF: | 1283 | case ICMP_UNREACH_PRECEDENCE_CUTOFF: |
1311 | ++unreachable; | ||
1312 | printf(" !C"); | 1284 | printf(" !C"); |
1285 | ++unreachable; | ||
1313 | break; | 1286 | break; |
1314 | |||
1315 | case ICMP_UNREACH_NET_UNKNOWN: | 1287 | case ICMP_UNREACH_NET_UNKNOWN: |
1316 | case ICMP_UNREACH_HOST_UNKNOWN: | 1288 | case ICMP_UNREACH_HOST_UNKNOWN: |
1317 | ++unreachable; | ||
1318 | printf(" !U"); | 1289 | printf(" !U"); |
1290 | ++unreachable; | ||
1319 | break; | 1291 | break; |
1320 | |||
1321 | case ICMP_UNREACH_ISOLATED: | 1292 | case ICMP_UNREACH_ISOLATED: |
1322 | ++unreachable; | ||
1323 | printf(" !I"); | 1293 | printf(" !I"); |
1294 | ++unreachable; | ||
1324 | break; | 1295 | break; |
1325 | |||
1326 | case ICMP_UNREACH_TOSNET: | 1296 | case ICMP_UNREACH_TOSNET: |
1327 | case ICMP_UNREACH_TOSHOST: | 1297 | case ICMP_UNREACH_TOSHOST: |
1328 | ++unreachable; | ||
1329 | printf(" !T"); | 1298 | printf(" !T"); |
1299 | ++unreachable; | ||
1330 | break; | 1300 | break; |
1331 | |||
1332 | default: | 1301 | default: |
1302 | printf(" !<%d>", i); | ||
1333 | ++unreachable; | 1303 | ++unreachable; |
1334 | printf(" !<%d>", code); | ||
1335 | break; | 1304 | break; |
1336 | } | 1305 | } |
1337 | break; | 1306 | break; |
1338 | } | 1307 | } |
1339 | if (cc == 0) | 1308 | if (cc == 0) |
1340 | printf(" *"); | 1309 | printf(" *"); |
1341 | (void)fflush(stdout); | ||
1342 | } | 1310 | } |
1343 | bb_putchar('\n'); | 1311 | bb_putchar('\n'); |
1344 | if (got_there || | 1312 | if (got_there |
1345 | (unreachable > 0 && unreachable >= nprobes - 1)) | 1313 | || (unreachable > 0 && unreachable >= nprobes - 1) |
1314 | ) { | ||
1346 | break; | 1315 | break; |
1316 | } | ||
1347 | } | 1317 | } |
1348 | return 0; | 1318 | return 0; |
1349 | } | 1319 | } |