aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/traceroute.c105
1 files changed, 41 insertions, 64 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c
index e6afdd8b9..cf2b3cc64 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -413,7 +413,6 @@ struct globals {
413#define port (G.port ) 413#define port (G.port )
414#define waittime (G.waittime ) 414#define waittime (G.waittime )
415#define recv_pkt (G.recv_pkt ) 415#define recv_pkt (G.recv_pkt )
416#define gwlist (G.gwlist )
417#define INIT_G() do { \ 416#define INIT_G() do { \
418 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 417 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
419} while (0) 418} while (0)
@@ -683,12 +682,15 @@ packet4_ok(int read_len, int seq)
683 int i; 682 int i;
684 uint32_t *lp = (uint32_t *)&icp->icmp_ip; 683 uint32_t *lp = (uint32_t *)&icp->icmp_ip;
685 684
686 printf("\n%d bytes from %s", 685 printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
687 read_len, inet_ntoa(G.from_lsa->u.sin.sin_addr)); 686 read_len,
688 /* Two separate printf() because inet_ntoa() returns static string */ 687 /* inet_ntoa(G.from_lsa->u.sin.sin_addr) - two calls of inet_ntoa()
689 printf(" to %s: icmp type %d (%s) code %d\n", 688 * are unsafe (use the same buffer), using this instead:
689 */
690 auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
690 inet_ntoa(ip->ip_dst), 691 inet_ntoa(ip->ip_dst),
691 type, pr_type(type), icp->icmp_code); 692 type, pr_type(type), icp->icmp_code
693 );
692 for (i = 4; i < read_len; i += sizeof(*lp)) 694 for (i = 4; i < read_len; i += sizeof(*lp))
693 printf("%2d: x%8.8x\n", i, *lp++); 695 printf("%2d: x%8.8x\n", i, *lp++);
694 } 696 }
@@ -756,19 +758,16 @@ packet6_ok(int read_len, int seq)
756# if ENABLE_FEATURE_TRACEROUTE_VERBOSE 758# if ENABLE_FEATURE_TRACEROUTE_VERBOSE
757 if (verbose) { 759 if (verbose) {
758 unsigned char *p; 760 unsigned char *p;
759 char pa[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + 4];
760 int i; 761 int i;
761 762
762 p = (unsigned char *) (icp + 1); 763 p = (unsigned char *) (icp + 1);
763 764
764 printf("\n%d bytes from %s", 765 printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
765 read_len, 766 read_len,
766 inet_ntop(AF_INET6, &G.from_lsa->u.sin6.sin6_addr, pa, sizeof(pa))); 767 auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
767 /* Two printf() instead of one - reuse string constants */ 768 auto_string(xmalloc_sockaddr2dotted_noport(G.to)),
768 printf(" to %s: icmp type %d (%s) code %d\n", 769 type, pr_type(type), icp->icmp6_code
769 inet_ntop(AF_INET6, &((struct sockaddr_in6*)G.to)->sin6_addr, pa, sizeof(pa)), 770 );
770 type, pr_type(type), icp->icmp6_code);
771
772 read_len -= sizeof(struct icmp6_hdr); 771 read_len -= sizeof(struct icmp6_hdr);
773 for (i = 0; i < read_len; i++) { 772 for (i = 0; i < read_len; i++) {
774 if (i % 16 == 0) 773 if (i % 16 == 0)
@@ -796,55 +795,36 @@ packet_ok(int read_len, int seq)
796 795
797#else /* !ENABLE_TRACEROUTE6 */ 796#else /* !ENABLE_TRACEROUTE6 */
798 797
799static ALWAYS_INLINE int 798# define packet_ok(read_len, seq) packet4_ok(read_len, seq)
800packet_ok(int read_len, int seq)
801{
802 return packet4_ok(read_len, seq);
803}
804 799
805#endif 800#endif
806 801
807/*
808 * Construct an Internet address representation.
809 * If the -n flag has been supplied, give
810 * numeric value, otherwise try for symbolic name.
811 */
812static void 802static void
813print_inetname(const struct sockaddr *from) 803print(int read_len)
814{ 804{
815 char *ina = xmalloc_sockaddr2dotted_noport(from); 805 char *ina = auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa));
816 806
817 if (option_mask32 & OPT_ADDR_NUM) { 807 if (option_mask32 & OPT_ADDR_NUM) {
818 printf(" %s", ina); 808 printf(" %s", ina);
819 } else { 809 } else {
820 char *n = NULL; 810 char *n = NULL;
821 811 if (G.from_lsa->u.sa.sa_family != AF_INET
822 if (from->sa_family != AF_INET 812 || G.from_lsa->u.sin.sin_addr.s_addr != INADDR_ANY
823 || ((struct sockaddr_in*)from)->sin_addr.s_addr != INADDR_ANY
824 ) { 813 ) {
825 /* Try to reverse resolve if it is not 0.0.0.0 */ 814 /* Try to reverse resolve if it is not 0.0.0.0 */
826 n = xmalloc_sockaddr2host_noport((struct sockaddr*)from); 815 n = auto_string(xmalloc_sockaddr2host_noport(&G.from_lsa->u.sa));
827 } 816 }
828 printf(" %s (%s)", (n ? n : ina), ina); 817 printf(" %s (%s)", (n ? n : ina), ina);
829 free(n);
830 } 818 }
831 free(ina);
832}
833
834static void
835print(int read_len)
836{
837 print_inetname(&G.from_lsa->u.sa);
838 819
839 if (verbose) { 820 if (verbose) {
840 char *ina = xmalloc_sockaddr2dotted_noport(G.to);
841#if ENABLE_TRACEROUTE6 821#if ENABLE_TRACEROUTE6
842 /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket 822 /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket
843 * return the entire IP packet (IOW: they do not strip IP header). 823 * return the entire IP packet (IOW: they do not strip IP header).
844 * Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6 824 * Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6
845 * header and return only ICMP6 packet. Weird. 825 * header and return only ICMP6 packet. Weird.
846 */ 826 */
847 if (G.to->sa_family == AF_INET6) { 827 if (G.from_lsa->u.sa.sa_family == AF_INET6) {
848 /* read_len -= sizeof(struct ip6_hdr); - WRONG! */ 828 /* read_len -= sizeof(struct ip6_hdr); - WRONG! */
849 } else 829 } else
850#endif 830#endif
@@ -852,8 +832,9 @@ print(int read_len)
852 struct ip *ip4packet = (struct ip*)recv_pkt; 832 struct ip *ip4packet = (struct ip*)recv_pkt;
853 read_len -= ip4packet->ip_hl << 2; 833 read_len -= ip4packet->ip_hl << 2;
854 } 834 }
855 printf(" %d bytes to %s", read_len, ina); 835 printf(" %d bytes to %s", read_len,
856 free(ina); 836 auto_string(xmalloc_sockaddr2dotted_noport(G.to))
837 );
857 } 838 }
858} 839}
859 840
@@ -870,10 +851,6 @@ print_delta_ms(unsigned t1p, unsigned t2p)
870static NOINLINE void 851static NOINLINE void
871traceroute_init(int op, char **argv) 852traceroute_init(int op, char **argv)
872{ 853{
873 int minpacket;
874#ifdef IP_TOS
875 int tos = 0;
876#endif
877 char *source; 854 char *source;
878 char *device; 855 char *device;
879 char *tos_str; 856 char *tos_str;
@@ -912,10 +889,6 @@ traceroute_init(int op, char **argv)
912 if (op & OPT_IP_CHKSUM) 889 if (op & OPT_IP_CHKSUM)
913 bb_error_msg("warning: ip checksums disabled"); 890 bb_error_msg("warning: ip checksums disabled");
914#endif 891#endif
915#ifdef IP_TOS
916 if (op & OPT_TOS)
917 tos = xatou_range(tos_str, 0, 255);
918#endif
919 if (op & OPT_MAX_TTL) 892 if (op & OPT_MAX_TTL)
920 G.max_ttl = xatou_range(max_ttl_str, 1, 255); 893 G.max_ttl = xatou_range(max_ttl_str, 1, 255);
921 if (op & OPT_PORT) 894 if (op & OPT_PORT)
@@ -930,11 +903,11 @@ traceroute_init(int op, char **argv)
930 G.first_ttl = xatou_range(first_ttl_str, 1, G.max_ttl); 903 G.first_ttl = xatou_range(first_ttl_str, 1, G.max_ttl);
931 904
932 /* Process destination and optional packet size */ 905 /* Process destination and optional packet size */
933 minpacket = sizeof(struct ip) 906 packlen = sizeof(struct ip)
934 + sizeof(struct udphdr) 907 + sizeof(struct udphdr)
935 + sizeof(struct outdata_t); 908 + sizeof(struct outdata_t);
936 if (op & OPT_USE_ICMP) { 909 if (op & OPT_USE_ICMP) {
937 minpacket = sizeof(struct ip) 910 packlen = sizeof(struct ip)
938 + SIZEOF_ICMP_HDR 911 + SIZEOF_ICMP_HDR
939 + sizeof(struct outdata_t); 912 + sizeof(struct outdata_t);
940 port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL */ 913 port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL */
@@ -948,11 +921,11 @@ traceroute_init(int op, char **argv)
948 dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); 921 dest_lsa = xhost_and_af2sockaddr(argv[0], port, af);
949 af = dest_lsa->u.sa.sa_family; 922 af = dest_lsa->u.sa.sa_family;
950 if (af == AF_INET6) { 923 if (af == AF_INET6) {
951 minpacket = sizeof(struct ip6_hdr) 924 packlen = sizeof(struct ip6_hdr)
952 + sizeof(struct udphdr) 925 + sizeof(struct udphdr)
953 + sizeof(struct outdata6_t); 926 + sizeof(struct outdata6_t);
954 if (op & OPT_USE_ICMP) 927 if (op & OPT_USE_ICMP)
955 minpacket = sizeof(struct ip6_hdr) 928 packlen = sizeof(struct ip6_hdr)
956 + SIZEOF_ICMP_HDR 929 + SIZEOF_ICMP_HDR
957 + sizeof(struct outdata6_t); 930 + sizeof(struct outdata6_t);
958 } 931 }
@@ -961,19 +934,20 @@ traceroute_init(int op, char **argv)
961#endif 934#endif
962 G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); 935 G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len);
963 G.to = xzalloc(dest_lsa->len); 936 G.to = xzalloc(dest_lsa->len);
964
965 packlen = minpacket;
966 if (argv[1]) 937 if (argv[1])
967 packlen = xatoul_range(argv[1], minpacket, 32 * 1024); 938 packlen = xatoul_range(argv[1], packlen, 32 * 1024);
968 939
969#if ENABLE_TRACEROUTE6 940#if ENABLE_TRACEROUTE6
970 if (af == AF_INET6) { 941 if (af == AF_INET6) {
971 xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); 942 xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
972 setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); //why? 943 /* want recvmsg to report target local address (for -v) */
944 setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO);
973 } else 945 } else
974#endif 946#endif
975 { 947 {
976 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock); 948 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock);
949 /* want recvmsg to report target local address (for -v) */
950 setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO);
977 } 951 }
978 952
979#if TRACEROUTE_SO_DEBUG 953#if TRACEROUTE_SO_DEBUG
@@ -1010,8 +984,10 @@ traceroute_init(int op, char **argv)
1010 } 984 }
1011#endif 985#endif
1012#ifdef IP_TOS 986#ifdef IP_TOS
1013 if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) { 987 if (op & OPT_TOS) {
1014 bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos); 988 int tos = xatou_range(tos_str, 0, 255);
989 if (setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0)
990 bb_perror_msg_and_die("setsockopt(%s,%d)", "TOS", tos);
1015 } 991 }
1016#endif 992#endif
1017#ifdef IP_DONTFRAG 993#ifdef IP_DONTFRAG
@@ -1070,7 +1046,8 @@ traceroute_init(int op, char **argv)
1070//TODO: we can query source port we bound to, 1046//TODO: we can query source port we bound to,
1071// and check it in replies... if we care enough 1047// and check it in replies... if we care enough
1072 xbind(sndsock, &source_lsa->u.sa, source_lsa->len); 1048 xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
1073 free(source_lsa); 1049 if (ENABLE_FEATURE_CLEAN_UP)
1050 free(source_lsa);
1074 } 1051 }
1075#if ENABLE_TRACEROUTE6 1052#if ENABLE_TRACEROUTE6
1076 else if (af == AF_INET6) { 1053 else if (af == AF_INET6) {
@@ -1087,7 +1064,8 @@ traceroute_init(int op, char **argv)
1087 /* bind our recv socket to this IP (but not port) */ 1064 /* bind our recv socket to this IP (but not port) */
1088 set_nport(&source_lsa->u.sa, 0); 1065 set_nport(&source_lsa->u.sa, 0);
1089 xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); 1066 xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
1090 free(source_lsa); 1067 if (ENABLE_FEATURE_CLEAN_UP)
1068 free(source_lsa);
1091 } 1069 }
1092#endif 1070#endif
1093 1071
@@ -1097,9 +1075,8 @@ traceroute_init(int op, char **argv)
1097 1075
1098 dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa); 1076 dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa);
1099 printf("traceroute to %s (%s)", argv[0], dest_str); 1077 printf("traceroute to %s (%s)", argv[0], dest_str);
1100 if (ENABLE_FEATURE_CLEAN_UP) { 1078 if (ENABLE_FEATURE_CLEAN_UP)
1101 free(dest_str); 1079 free(dest_str);
1102 }
1103 1080
1104 if (op & OPT_SOURCE) 1081 if (op & OPT_SOURCE)
1105 printf(" from %s", source); 1082 printf(" from %s", source);