diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2020-12-12 21:09:21 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-12-12 21:09:21 +0100 |
commit | e76f03b267aed3c7c9a247ef4b27e1bb1c56e024 (patch) | |
tree | 39407a48884c155794f5780f68651d73e8ebf29c | |
parent | df5c5394b081d5b6a374a5025082c88fc05d0951 (diff) | |
download | busybox-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.c | 145 |
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 | ||
363 | enum { | 367 | enum { |
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 | */ | ||
565 | static const char * | 567 | static const char * |
566 | pr_type(unsigned char t) | 568 | pr_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 | } |
599 | static void | ||
600 | hexdump(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 | ||
603 | static int | 628 | static int |
604 | packet4_ok(int read_len, int seq) | 629 | packet4_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()); |