aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/traceroute.c107
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
700static int 701static int
701packet_ok(int read_len, len_and_sockaddr *from_lsa, 702packet6_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
797static int
798packet_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
796static ALWAYS_INLINE int 809static ALWAYS_INLINE int
797packet_ok(int read_len, 810packet_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,