diff options
-rw-r--r-- | networking/traceroute.c | 107 |
1 files changed, 58 insertions, 49 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c index ddde922bf..764d66ef8 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c | |||
@@ -475,7 +475,7 @@ send_probe(int seq, int ttl) | |||
475 | #if ENABLE_TRACEROUTE6 | 475 | #if ENABLE_TRACEROUTE6 |
476 | if (dest_lsa->u.sa.sa_family == AF_INET6) { | 476 | if (dest_lsa->u.sa.sa_family == AF_INET6) { |
477 | struct outdata6_t *pkt = (void *) outdata; | 477 | struct outdata6_t *pkt = (void *) outdata; |
478 | pkt->ident6 = htonl(ident); | 478 | pkt->ident6 = ident; |
479 | pkt->seq6 = htonl(seq); | 479 | pkt->seq6 = htonl(seq); |
480 | /*gettimeofday(&pkt->tv, &tz);*/ | 480 | /*gettimeofday(&pkt->tv, &tz);*/ |
481 | icp = outicmp6; | 481 | icp = outicmp6; |
@@ -631,7 +631,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
631 | 631 | ||
632 | if ((option_mask32 & OPT_USE_ICMP) | 632 | if ((option_mask32 & OPT_USE_ICMP) |
633 | && type == ICMP_ECHOREPLY | 633 | && type == ICMP_ECHOREPLY |
634 | && icp->icmp_id == htons(ident) | 634 | && icp->icmp_id == ident |
635 | && icp->icmp_seq == htons(seq) | 635 | && icp->icmp_seq == htons(seq) |
636 | ) { | 636 | ) { |
637 | /* In UDP mode, when we reach the machine, we (usually) | 637 | /* In UDP mode, when we reach the machine, we (usually) |
@@ -655,7 +655,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
655 | hicmp = (struct icmp *)((unsigned char *)hip + hlen); | 655 | hicmp = (struct icmp *)((unsigned char *)hip + hlen); |
656 | if (hlen + SIZEOF_ICMP_HDR <= read_len | 656 | if (hlen + SIZEOF_ICMP_HDR <= read_len |
657 | && hip->ip_p == IPPROTO_ICMP | 657 | && hip->ip_p == IPPROTO_ICMP |
658 | && hicmp->icmp_id == htons(ident) | 658 | && hicmp->icmp_id == ident |
659 | && hicmp->icmp_seq == htons(seq) | 659 | && hicmp->icmp_seq == htons(seq) |
660 | ) { | 660 | ) { |
661 | return (type == ICMP_TIMXCEED ? -1 : code + 1); | 661 | return (type == ICMP_TIMXCEED ? -1 : code + 1); |
@@ -667,7 +667,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
667 | // Off: since we do not form the entire IP packet, | 667 | // Off: since we do not form the entire IP packet, |
668 | // but defer it to kernel, we can't set source port, | 668 | // but defer it to kernel, we can't set source port, |
669 | // and thus can't check it here in the reply | 669 | // and thus can't check it here in the reply |
670 | /* && up->source == htons(ident) */ | 670 | /* && up->source == ident */ |
671 | && up->dest == htons(port + seq) | 671 | && up->dest == htons(port + seq) |
672 | ) { | 672 | ) { |
673 | return (type == ICMP_TIMXCEED ? -1 : code + 1); | 673 | return (type == ICMP_TIMXCEED ? -1 : code + 1); |
@@ -679,10 +679,10 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
679 | int i; | 679 | int i; |
680 | uint32_t *lp = (uint32_t *)&icp->icmp_ip; | 680 | uint32_t *lp = (uint32_t *)&icp->icmp_ip; |
681 | 681 | ||
682 | printf("\n%d bytes from %s to " | 682 | printf("\n%d bytes from %s", |
683 | "%s: icmp type %d (%s) code %d\n", | 683 | read_len, inet_ntoa(from->sin_addr)); |
684 | read_len, inet_ntoa(from->sin_addr), | 684 | /* Two separate printf() because inet_ntoa() returns static string */ |
685 | //BUG: inet_ntoa() returns static buf! x2 is NONO! | 685 | printf(" to %s: icmp type %d (%s) code %d\n", |
686 | inet_ntoa(ip->ip_dst), | 686 | inet_ntoa(ip->ip_dst), |
687 | type, pr_type(type), icp->icmp_code); | 687 | type, pr_type(type), icp->icmp_code); |
688 | for (i = 4; i < read_len; i += sizeof(*lp)) | 688 | for (i = 4; i < read_len; i += sizeof(*lp)) |
@@ -693,21 +693,19 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
693 | } | 693 | } |
694 | 694 | ||
695 | #if ENABLE_TRACEROUTE6 | 695 | #if ENABLE_TRACEROUTE6 |
696 | |||
696 | # if !ENABLE_FEATURE_TRACEROUTE_VERBOSE | 697 | # if !ENABLE_FEATURE_TRACEROUTE_VERBOSE |
697 | #define packet_ok(read_len, from_lsa, to, seq) \ | 698 | #define packet6_ok(read_len, from_lsa, to, seq) \ |
698 | packet_ok(read_len, from_lsa, seq) | 699 | packet6_ok(read_len, from_lsa, seq) |
699 | # endif | 700 | # endif |
700 | static int | 701 | static int |
701 | packet_ok(int read_len, len_and_sockaddr *from_lsa, | 702 | packet6_ok(int read_len, const struct sockaddr_in6 *from, |
702 | struct sockaddr *to, | 703 | struct sockaddr *to, |
703 | int seq) | 704 | int seq) |
704 | { | 705 | { |
705 | const struct icmp6_hdr *icp; | 706 | const struct icmp6_hdr *icp; |
706 | unsigned char type, code; | 707 | unsigned char type, code; |
707 | 708 | ||
708 | if (from_lsa->u.sa.sa_family == AF_INET) | ||
709 | return packet4_ok(read_len, &from_lsa->u.sin, seq); | ||
710 | |||
711 | /* NB: reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) socket | 709 | /* NB: reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) socket |
712 | * return only ICMP packet (IOW: they strip IPv6 header). | 710 | * return only ICMP packet (IOW: they strip IPv6 header). |
713 | * This differs from (AF_INET, SOCK_RAW, IPPROTO_ICMP) sockets!? | 711 | * This differs from (AF_INET, SOCK_RAW, IPPROTO_ICMP) sockets!? |
@@ -719,7 +717,7 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, | |||
719 | 717 | ||
720 | if ((option_mask32 & OPT_USE_ICMP) | 718 | if ((option_mask32 & OPT_USE_ICMP) |
721 | && type == ICMP6_ECHO_REPLY | 719 | && type == ICMP6_ECHO_REPLY |
722 | && icp->icmp6_id == htons(ident) | 720 | && icp->icmp6_id == ident |
723 | && icp->icmp6_seq == htons(seq) | 721 | && icp->icmp6_seq == htons(seq) |
724 | ) { | 722 | ) { |
725 | /* In UDP mode, when we reach the machine, we (usually) | 723 | /* In UDP mode, when we reach the machine, we (usually) |
@@ -749,7 +747,7 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, | |||
749 | 747 | ||
750 | pkt = (struct outdata6_t *) (up + 1); | 748 | pkt = (struct outdata6_t *) (up + 1); |
751 | 749 | ||
752 | if (ntohl(pkt->ident6) == ident | 750 | if (pkt->ident6 == ident |
753 | && ntohl(pkt->seq6) == seq | 751 | && ntohl(pkt->seq6) == seq |
754 | ) { | 752 | ) { |
755 | return (type == ICMP6_TIME_EXCEEDED ? -1 : (code<<8)+1); | 753 | return (type == ICMP6_TIME_EXCEEDED ? -1 : (code<<8)+1); |
@@ -763,17 +761,17 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, | |||
763 | # define MAXHOSTNAMELEN 80 | 761 | # define MAXHOSTNAMELEN 80 |
764 | # endif | 762 | # endif |
765 | unsigned char *p; | 763 | unsigned char *p; |
766 | char pa1[MAXHOSTNAMELEN]; | 764 | char pa[MAXHOSTNAMELEN]; |
767 | char pa2[MAXHOSTNAMELEN]; | ||
768 | int i; | 765 | int i; |
769 | 766 | ||
770 | p = (unsigned char *) (icp + 1); | 767 | p = (unsigned char *) (icp + 1); |
771 | 768 | ||
772 | printf("\n%d bytes from %s to " | 769 | printf("\n%d bytes from %s", |
773 | "%s: icmp type %d (%s) code %d\n", | ||
774 | read_len, | 770 | read_len, |
775 | inet_ntop(AF_INET6, &from_lsa->u.sin6.sin6_addr, pa1, sizeof(pa1)), | 771 | inet_ntop(AF_INET6, &from->sin6_addr, pa, sizeof(pa))); |
776 | inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa2, sizeof(pa2)), | 772 | /* Two printf() instead of one - reuse string constants */ |
773 | printf(" to %s: icmp type %d (%s) code %d\n", | ||
774 | inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa, sizeof(pa)), | ||
777 | type, pr_type(type), icp->icmp6_code); | 775 | type, pr_type(type), icp->icmp6_code); |
778 | 776 | ||
779 | read_len -= sizeof(struct icmp6_hdr); | 777 | read_len -= sizeof(struct icmp6_hdr); |
@@ -792,7 +790,22 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, | |||
792 | 790 | ||
793 | return 0; | 791 | return 0; |
794 | } | 792 | } |
793 | # if !ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
794 | #define packet_ok(read_len, from_lsa, to, seq) \ | ||
795 | packet_ok(read_len, from_lsa, seq) | ||
796 | # endif | ||
797 | static int | ||
798 | packet_ok(int read_len, len_and_sockaddr *from_lsa, | ||
799 | struct sockaddr *to, | ||
800 | int seq) | ||
801 | { | ||
802 | if (from_lsa->u.sa.sa_family == AF_INET) | ||
803 | return packet4_ok(read_len, &from_lsa->u.sin, seq); | ||
804 | return packet6_ok(read_len, &from_lsa->u.sin6, to, seq); | ||
805 | } | ||
806 | |||
795 | #else /* !ENABLE_TRACEROUTE6 */ | 807 | #else /* !ENABLE_TRACEROUTE6 */ |
808 | |||
796 | static ALWAYS_INLINE int | 809 | static ALWAYS_INLINE int |
797 | packet_ok(int read_len, | 810 | packet_ok(int read_len, |
798 | len_and_sockaddr *from_lsa IF_NOT_FEATURE_TRACEROUTE_VERBOSE(UNUSED_PARAM), | 811 | len_and_sockaddr *from_lsa IF_NOT_FEATURE_TRACEROUTE_VERBOSE(UNUSED_PARAM), |
@@ -801,6 +814,7 @@ packet_ok(int read_len, | |||
801 | { | 814 | { |
802 | return packet4_ok(read_len, &from_lsa->u.sin, seq); | 815 | return packet4_ok(read_len, &from_lsa->u.sin, seq); |
803 | } | 816 | } |
817 | |||
804 | #endif | 818 | #endif |
805 | 819 | ||
806 | /* | 820 | /* |
@@ -927,14 +941,6 @@ common_traceroute_main(int op, char **argv) | |||
927 | port = xatou16(port_str); | 941 | port = xatou16(port_str); |
928 | if (op & OPT_NPROBES) | 942 | if (op & OPT_NPROBES) |
929 | nprobes = xatou_range(nprobes_str, 1, INT_MAX); | 943 | nprobes = xatou_range(nprobes_str, 1, INT_MAX); |
930 | if (op & OPT_SOURCE) { | ||
931 | /* | ||
932 | * set the ip source address of the outbound | ||
933 | * probe (e.g., on a multi-homed host). | ||
934 | */ | ||
935 | if (getuid() != 0) | ||
936 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | ||
937 | } | ||
938 | if (op & OPT_WAITTIME) | 944 | if (op & OPT_WAITTIME) |
939 | waittime = xatou_range(waittime_str, 1, 24 * 60 * 60); | 945 | waittime = xatou_range(waittime_str, 1, 24 * 60 * 60); |
940 | if (op & OPT_PAUSE_MS) | 946 | if (op & OPT_PAUSE_MS) |
@@ -993,23 +999,26 @@ common_traceroute_main(int op, char **argv) | |||
993 | if (op & OPT_BYPASS_ROUTE) | 999 | if (op & OPT_BYPASS_ROUTE) |
994 | setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE); | 1000 | setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE); |
995 | 1001 | ||
1002 | { | ||
1003 | int snd; | ||
996 | #if ENABLE_TRACEROUTE6 | 1004 | #if ENABLE_TRACEROUTE6 |
997 | if (af == AF_INET6) { | 1005 | if (af == AF_INET6) { |
998 | if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) | 1006 | if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) |
999 | bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); | 1007 | bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); |
1000 | if (op & OPT_USE_ICMP) | 1008 | if (op & OPT_USE_ICMP) |
1001 | xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), sndsock); | 1009 | snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); |
1002 | else | 1010 | else |
1003 | xmove_fd(xsocket(AF_INET6, SOCK_DGRAM, 0), sndsock); | 1011 | snd = xsocket(AF_INET6, SOCK_DGRAM, 0); |
1004 | } else | 1012 | } else |
1005 | #endif | 1013 | #endif |
1006 | { | 1014 | { |
1007 | if (op & OPT_USE_ICMP) | 1015 | if (op & OPT_USE_ICMP) |
1008 | xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock); | 1016 | snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); |
1009 | else | 1017 | else |
1010 | xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); | 1018 | snd = xsocket(AF_INET, SOCK_DGRAM, 0); |
1019 | } | ||
1020 | xmove_fd(snd, sndsock); | ||
1011 | } | 1021 | } |
1012 | //TODO xmove_fd to here! | ||
1013 | 1022 | ||
1014 | #ifdef SO_SNDBUF | 1023 | #ifdef SO_SNDBUF |
1015 | if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) { | 1024 | if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) { |
@@ -1036,13 +1045,12 @@ common_traceroute_main(int op, char **argv) | |||
1036 | 1045 | ||
1037 | ident = getpid(); | 1046 | ident = getpid(); |
1038 | 1047 | ||
1048 | outdata = (void*)(outudp + 1); | ||
1039 | if (!ENABLE_TRACEROUTE6 || af == AF_INET) { | 1049 | if (!ENABLE_TRACEROUTE6 || af == AF_INET) { |
1040 | outdata = (void*)(outudp + 1); | ||
1041 | if (op & OPT_USE_ICMP) { | 1050 | if (op & OPT_USE_ICMP) { |
1042 | ident |= 0x8000; | ||
1043 | outicmp->icmp_type = ICMP_ECHO; | 1051 | outicmp->icmp_type = ICMP_ECHO; |
1044 | /*outicmp->icmp_code = 0; - set by xzalloc */ | 1052 | /*outicmp->icmp_code = 0; - set by xzalloc */ |
1045 | outicmp->icmp_id = htons(ident); | 1053 | outicmp->icmp_id = ident; |
1046 | outdata = (void*)((char *)outicmp + SIZEOF_ICMP_HDR); | 1054 | outdata = (void*)((char *)outicmp + SIZEOF_ICMP_HDR); |
1047 | } | 1055 | } |
1048 | } | 1056 | } |
@@ -1050,10 +1058,9 @@ common_traceroute_main(int op, char **argv) | |||
1050 | if (af == AF_INET6) { | 1058 | if (af == AF_INET6) { |
1051 | outdata = (void*)(outudp6 + 1); | 1059 | outdata = (void*)(outudp6 + 1); |
1052 | if (op & OPT_USE_ICMP) { | 1060 | if (op & OPT_USE_ICMP) { |
1053 | ident |= 0x8000; | ||
1054 | outicmp6->icmp_type = ICMP6_ECHO_REQUEST; | 1061 | outicmp6->icmp_type = ICMP6_ECHO_REQUEST; |
1055 | /*outicmp->icmp_code = 0; - set by xzalloc */ | 1062 | /*outicmp->icmp_code = 0; - set by xzalloc */ |
1056 | outicmp6->icmp_id = htons(ident); | 1063 | outicmp6->icmp_id = ident; |
1057 | outdata = (void*)((char *)outicmp6 + SIZEOF_ICMP_HDR); | 1064 | outdata = (void*)((char *)outicmp6 + SIZEOF_ICMP_HDR); |
1058 | } | 1065 | } |
1059 | } | 1066 | } |
@@ -1069,6 +1076,8 @@ common_traceroute_main(int op, char **argv) | |||
1069 | #else | 1076 | #else |
1070 | len_and_sockaddr *source_lsa = xdotted2sockaddr(source, 0); | 1077 | len_and_sockaddr *source_lsa = xdotted2sockaddr(source, 0); |
1071 | #endif | 1078 | #endif |
1079 | if (getuid() != 0) | ||
1080 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | ||
1072 | /* Ping4 does this (why?) */ | 1081 | /* Ping4 does this (why?) */ |
1073 | if (af == AF_INET) | 1082 | if (af == AF_INET) |
1074 | if (setsockopt(sndsock, IPPROTO_IP, IP_MULTICAST_IF, | 1083 | if (setsockopt(sndsock, IPPROTO_IP, IP_MULTICAST_IF, |