aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-12-12 21:09:21 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-12-12 21:09:21 +0100
commite76f03b267aed3c7c9a247ef4b27e1bb1c56e024 (patch)
tree39407a48884c155794f5780f68651d73e8ebf29c
parentdf5c5394b081d5b6a374a5025082c88fc05d0951 (diff)
downloadbusybox-w32-e76f03b267aed3c7c9a247ef4b27e1bb1c56e024.tar.gz
busybox-w32-e76f03b267aed3c7c9a247ef4b27e1bb1c56e024.tar.bz2
busybox-w32-e76f03b267aed3c7c9a247ef4b27e1bb1c56e024.zip
traceroute: commonalize verbose printing
function old new delta hexdump - 274 +274 traceroute_init 1172 1147 -25 pr_type 79 - -79 common_traceroute_main 2091 1785 -306 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/2 up/down: 274/-410) Total: -136 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/traceroute.c145
1 files changed, 62 insertions, 83 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c
index cf2b3cc64..0fb01ff5b 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -358,7 +358,11 @@ enum {
358 OPT_IPV4 = (1 << 17), /* 4 */ 358 OPT_IPV4 = (1 << 17), /* 4 */
359 OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */ 359 OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */
360}; 360};
361#define verbose (option_mask32 & OPT_VERBOSE) 361#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
362# define verbose (option_mask32 & OPT_VERBOSE)
363#else
364# define verbose 0
365#endif
362 366
363enum { 367enum {
364 SIZEOF_ICMP_HDR = 8, 368 SIZEOF_ICMP_HDR = 8,
@@ -559,9 +563,7 @@ send_probe(int seq, int ttl)
559} 563}
560 564
561#if ENABLE_FEATURE_TRACEROUTE_VERBOSE 565#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
562/* 566/* Convert an ICMP "type" field to a printable string */
563 * Convert an ICMP "type" field to a printable string.
564 */
565static const char * 567static const char *
566pr_type(unsigned char t) 568pr_type(unsigned char t)
567{ 569{
@@ -594,12 +596,35 @@ pr_type(unsigned char t)
594 596
595 return ttab[t]; 597 return ttab[t];
596} 598}
599static void
600hexdump(const struct icmp *icp, int len)
601{
602 const unsigned char *p;
603 int i;
604
605 printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
606 len,
607 auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
608 auto_string(xmalloc_sockaddr2dotted_noport(G.to)),
609 icp->icmp_type, pr_type(icp->icmp_type),
610 icp->icmp_code
611 );
612 p = (const void *)icp;
613 for (i = 0; i < len; i++) {
614 if (i % 16 == 0)
615 printf("%04x:", i);
616 if (i % 4 == 0)
617 bb_putchar(' ');
618 printf("%02x", p[i]);
619 if ((i % 16 == 15) && (i + 1 < len))
620 bb_putchar('\n');
621 }
622 bb_putchar('\n');
623}
624#else
625# define hexdump(...) ((void)0)
597#endif 626#endif
598 627
599#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE
600#define packet4_ok(read_len, from, seq) \
601 packet4_ok(read_len, seq)
602#endif
603static int 628static int
604packet4_ok(int read_len, int seq) 629packet4_ok(int read_len, int seq)
605{ 630{
@@ -616,11 +641,9 @@ packet4_ok(int read_len, int seq)
616 641
617 hlen = ip->ip_hl << 2; 642 hlen = ip->ip_hl << 2;
618 if (read_len < hlen + ICMP_MINLEN) { 643 if (read_len < hlen + ICMP_MINLEN) {
619#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
620 if (verbose) 644 if (verbose)
621 printf("packet too short (%d bytes) from %s\n", read_len, 645 printf("packet too short (%d bytes) from %s\n", read_len,
622 inet_ntoa(G.from_lsa->u.sin.sin_addr)); 646 inet_ntoa(G.from_lsa->u.sin.sin_addr));
623#endif
624 return 0; 647 return 0;
625 } 648 }
626 read_len -= hlen; 649 read_len -= hlen;
@@ -677,24 +700,8 @@ packet4_ok(int read_len, int seq)
677 } 700 }
678 } 701 }
679 } 702 }
680#if ENABLE_FEATURE_TRACEROUTE_VERBOSE 703 if (verbose)
681 if (verbose) { 704 hexdump(icp, read_len);
682 int i;
683 uint32_t *lp = (uint32_t *)&icp->icmp_ip;
684
685 printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
686 read_len,
687 /* inet_ntoa(G.from_lsa->u.sin.sin_addr) - two calls of inet_ntoa()
688 * are unsafe (use the same buffer), using this instead:
689 */
690 auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
691 inet_ntoa(ip->ip_dst),
692 type, pr_type(type), icp->icmp_code
693 );
694 for (i = 4; i < read_len; i += sizeof(*lp))
695 printf("%2d: x%8.8x\n", i, *lp++);
696 }
697#endif
698 return 0; 705 return 0;
699} 706}
700 707
@@ -754,34 +761,9 @@ packet6_ok(int read_len, int seq)
754 } 761 }
755 } 762 }
756 } 763 }
757 764 if (verbose)
758# if ENABLE_FEATURE_TRACEROUTE_VERBOSE 765 /* cast is safe since the beginning of icmp4 and icmp6 layouts match */
759 if (verbose) { 766 hexdump((const struct icmp *)icp, read_len);
760 unsigned char *p;
761 int i;
762
763 p = (unsigned char *) (icp + 1);
764
765 printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
766 read_len,
767 auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
768 auto_string(xmalloc_sockaddr2dotted_noport(G.to)),
769 type, pr_type(type), icp->icmp6_code
770 );
771 read_len -= sizeof(struct icmp6_hdr);
772 for (i = 0; i < read_len; i++) {
773 if (i % 16 == 0)
774 printf("%04x:", i);
775 if (i % 4 == 0)
776 bb_putchar(' ');
777 printf("%02x", p[i]);
778 if ((i % 16 == 15) && (i + 1 < read_len))
779 bb_putchar('\n');
780 }
781 bb_putchar('\n');
782 }
783# endif
784
785 return 0; 767 return 0;
786} 768}
787 769
@@ -910,7 +892,7 @@ traceroute_init(int op, char **argv)
910 packlen = sizeof(struct ip) 892 packlen = sizeof(struct ip)
911 + SIZEOF_ICMP_HDR 893 + SIZEOF_ICMP_HDR
912 + sizeof(struct outdata_t); 894 + sizeof(struct outdata_t);
913 port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL */ 895 port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL! */
914 } 896 }
915#if ENABLE_TRACEROUTE6 897#if ENABLE_TRACEROUTE6
916 af = AF_UNSPEC; 898 af = AF_UNSPEC;
@@ -932,23 +914,24 @@ traceroute_init(int op, char **argv)
932#else 914#else
933 dest_lsa = xhost2sockaddr(argv[0], port); 915 dest_lsa = xhost2sockaddr(argv[0], port);
934#endif 916#endif
917//TODO: make sure af == AF_INET[6]? (FEATURE_UNIX_LOCAL=y allows "local:/PATH" to be translated to AF_UNIX)
935 G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); 918 G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len);
936 G.to = xzalloc(dest_lsa->len); 919 G.to = xzalloc(dest_lsa->len);
937 if (argv[1]) 920 if (argv[1])
938 packlen = xatoul_range(argv[1], packlen, 32 * 1024); 921 packlen = xatoul_range(argv[1], packlen, 32 * 1024);
939 922
923 if (af == AF_INET) {
924 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock);
925 /* want recvmsg to report target local address (for -v) */
926 setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO);
927 }
940#if ENABLE_TRACEROUTE6 928#if ENABLE_TRACEROUTE6
941 if (af == AF_INET6) { 929 else {
942 xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); 930 xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
943 /* want recvmsg to report target local address (for -v) */ 931 /* want recvmsg to report target local address (for -v) */
944 setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); 932 setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO);
945 } else
946#endif
947 {
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);
951 } 933 }
934#endif
952 935
953#if TRACEROUTE_SO_DEBUG 936#if TRACEROUTE_SO_DEBUG
954 if (op & OPT_DEBUG) 937 if (op & OPT_DEBUG)
@@ -959,22 +942,22 @@ traceroute_init(int op, char **argv)
959 942
960 { 943 {
961 int snd; 944 int snd;
945 if (af == AF_INET) {
946 if (op & OPT_USE_ICMP)
947 snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
948 else
949 snd = xsocket(AF_INET, SOCK_DGRAM, 0);
950 }
962#if ENABLE_TRACEROUTE6 951#if ENABLE_TRACEROUTE6
963 if (af == AF_INET6) { 952 else {
964 if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) 953 if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
965 bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); 954 bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
966 if (op & OPT_USE_ICMP) 955 if (op & OPT_USE_ICMP)
967 snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 956 snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
968 else 957 else
969 snd = xsocket(AF_INET6, SOCK_DGRAM, 0); 958 snd = xsocket(AF_INET6, SOCK_DGRAM, 0);
970 } else
971#endif
972 {
973 if (op & OPT_USE_ICMP)
974 snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
975 else
976 snd = xsocket(AF_INET, SOCK_DGRAM, 0);
977 } 959 }
960#endif
978 xmove_fd(snd, sndsock); 961 xmove_fd(snd, sndsock);
979 } 962 }
980 963
@@ -1006,7 +989,7 @@ traceroute_init(int op, char **argv)
1006 ident = getpid(); 989 ident = getpid();
1007 990
1008 outdata = (void*)(outudp + 1); 991 outdata = (void*)(outudp + 1);
1009 if (!ENABLE_TRACEROUTE6 || af == AF_INET) { 992 if (af == AF_INET) {
1010 if (op & OPT_USE_ICMP) { 993 if (op & OPT_USE_ICMP) {
1011 outicmp->icmp_type = ICMP_ECHO; 994 outicmp->icmp_type = ICMP_ECHO;
1012 /*outicmp->icmp_code = 0; - set by xzalloc */ 995 /*outicmp->icmp_code = 0; - set by xzalloc */
@@ -1015,7 +998,7 @@ traceroute_init(int op, char **argv)
1015 } 998 }
1016 } 999 }
1017#if ENABLE_TRACEROUTE6 1000#if ENABLE_TRACEROUTE6
1018 if (af == AF_INET6) { 1001 else {
1019 outdata = (void*)(outudp6 + 1); 1002 outdata = (void*)(outudp6 + 1);
1020 if (op & OPT_USE_ICMP) { 1003 if (op & OPT_USE_ICMP) {
1021 outicmp6->icmp_type = ICMP6_ECHO_REQUEST; 1004 outicmp6->icmp_type = ICMP6_ECHO_REQUEST;
@@ -1048,26 +1031,22 @@ traceroute_init(int op, char **argv)
1048 xbind(sndsock, &source_lsa->u.sa, source_lsa->len); 1031 xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
1049 if (ENABLE_FEATURE_CLEAN_UP) 1032 if (ENABLE_FEATURE_CLEAN_UP)
1050 free(source_lsa); 1033 free(source_lsa);
1051 } 1034 } else {
1052#if ENABLE_TRACEROUTE6
1053 else if (af == AF_INET6) {
1054//TODO: why we don't do it for IPv4?
1055 len_and_sockaddr *source_lsa; 1035 len_and_sockaddr *source_lsa;
1056 1036
1057 set_nport(&dest_lsa->u.sa, htons(port)); 1037 set_nport(&dest_lsa->u.sa, htons(port));
1058 /* Connect makes kernel pick source IP and port */ 1038 /* Connect makes kernel pick source IP (and port if UDP) */
1059 xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len); 1039 xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len);
1060 /* Read IP and port */ 1040 /* Read IP and port */
1061 source_lsa = get_sock_lsa(sndsock); 1041 source_lsa = get_sock_lsa(sndsock);
1062 if (source_lsa == NULL) 1042 if (source_lsa == NULL)
1063 bb_simple_error_msg_and_die("can't get probe addr"); 1043 bb_simple_perror_msg_and_die("getsockname");
1064 /* bind our recv socket to this IP (but not port) */ 1044 /* bind our recv ICMP socket to this IP (but not port, ICMP has no ports) */
1065 set_nport(&source_lsa->u.sa, 0); 1045 //set_nport(&source_lsa->u.sa, 0); - paranoia, seems to work without this for both ipv4 and ipv6
1066 xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); 1046 xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
1067 if (ENABLE_FEATURE_CLEAN_UP) 1047 if (ENABLE_FEATURE_CLEAN_UP)
1068 free(source_lsa); 1048 free(source_lsa);
1069 } 1049 }
1070#endif
1071 1050
1072 /* Revert to non-privileged user after opening sockets */ 1051 /* Revert to non-privileged user after opening sockets */
1073 xsetgid(getgid()); 1052 xsetgid(getgid());