aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-12-12 16:38:43 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-12-12 18:09:45 +0100
commit3978adc4458eccfcd3720a6ec1199b255156e344 (patch)
tree955421d7fda3cc2a5b3c78de75ef3968d2a7a6d1
parentef2366cdca45941f943f4970ac57a4008181fca9 (diff)
downloadbusybox-w32-3978adc4458eccfcd3720a6ec1199b255156e344.tar.gz
busybox-w32-3978adc4458eccfcd3720a6ec1199b255156e344.tar.bz2
busybox-w32-3978adc4458eccfcd3720a6ec1199b255156e344.zip
traceroute: fix traceroute6 -I (icmp mode)
function old new delta common_traceroute_main 3530 3544 +14 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/traceroute.c206
1 files changed, 135 insertions, 71 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 7dde10524..ddde922bf 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -414,9 +414,32 @@ struct globals {
414 waittime = 5; \ 414 waittime = 5; \
415} while (0) 415} while (0)
416 416
417#define outicmp ((struct icmp *)(outip + 1)) 417#define outudp ((struct udphdr *)(outip + 1))
418#define outudp ((struct udphdr *)(outip + 1)) 418#define outudp6 ((struct udphdr *)(((struct ip6_hdr*)outip) + 1))
419 419#define outicmp ((struct icmp *)(outip + 1))
420#define outicmp6 ((struct icmp *)(((struct ip6_hdr*)outip) + 1))
421/* NB: for icmp echo, IPv4 and IPv6 fields are the same size and offset:
422 * struct icmp:
423 * uint8_t icmp_type;
424 * uint8_t icmp_code;
425 * uint16_t icmp_cksum;
426 * uint16_t icmp_id;
427 * uint16_t icmp_seq;
428 * struct icmp6_hdr:
429 * uint8_t icmp6_type;
430 * uint8_t icmp6_code;
431 * uint16_t icmp6_cksum;
432 * uint16_t icmp6_id;
433 * uint16_t icmp6_seq;
434 * therefore both outicmp and outicmp6 are pointers to *IPv4* icmp struct.
435 * SIZEOF_ICMP_HDR == 8 is the same for both, as well.
436 * However, values of these pointers are not the same (since IPv6 IP header is larger),
437 * and icmp_type constants are not the same:
438 * #define ICMP_ECHO 8
439 * #define ICMP_ECHOREPLY 0
440 * #define ICMP6_ECHO_REQUEST 128
441 * #define ICMP6_ECHO_REPLY 129
442 */
420 443
421static int 444static int
422wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms) 445wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms)
@@ -446,14 +469,16 @@ send_probe(int seq, int ttl)
446{ 469{
447 int len, res; 470 int len, res;
448 void *out; 471 void *out;
472 struct icmp *icp;
449 473
450 /* Payload */ 474 /* Payload */
451#if ENABLE_TRACEROUTE6 475#if ENABLE_TRACEROUTE6
452 if (dest_lsa->u.sa.sa_family == AF_INET6) { 476 if (dest_lsa->u.sa.sa_family == AF_INET6) {
453 struct outdata6_t *pkt = (struct outdata6_t *) outdata; 477 struct outdata6_t *pkt = (void *) outdata;
454 pkt->ident6 = htonl(ident); 478 pkt->ident6 = htonl(ident);
455 pkt->seq6 = htonl(seq); 479 pkt->seq6 = htonl(seq);
456 /*gettimeofday(&pkt->tv, &tz);*/ 480 /*gettimeofday(&pkt->tv, &tz);*/
481 icp = outicmp6;
457 } else 482 } else
458#endif 483#endif
459 { 484 {
@@ -461,19 +486,23 @@ send_probe(int seq, int ttl)
461 outdata->ttl = ttl; 486 outdata->ttl = ttl;
462// UNUSED: was storing gettimeofday's result there, but never ever checked it 487// UNUSED: was storing gettimeofday's result there, but never ever checked it
463 /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ 488 /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/
464 489 icp = outicmp;
465 if (option_mask32 & OPT_USE_ICMP) { 490 }
466 outicmp->icmp_seq = htons(seq); 491 out = outdata;
467 492 if (option_mask32 & OPT_USE_ICMP) {
468 /* Always calculate checksum for icmp packets */ 493 out = icp;
469 outicmp->icmp_cksum = 0; 494 /*icp->icmp_type = ICMP[6]_ECHO; - already set */
470 outicmp->icmp_cksum = inet_cksum( 495 /*icp->icmp_code = 0; - already set */
471 outicmp, 496 /*icp->icmp_id = ident; - already set */
472 ((char*)outip + packlen) - (char*)outicmp 497 icp->icmp_seq = htons(seq);
473 ); 498 /* Always calculate checksum for icmp packets */
474 if (outicmp->icmp_cksum == 0) 499 icp->icmp_cksum = 0;
475 outicmp->icmp_cksum = 0xffff; 500 icp->icmp_cksum = inet_cksum(
476 } 501 icp,
502 ((char*)outip + packlen) - (char*)icp
503 );
504 if (icp->icmp_cksum == 0)
505 icp->icmp_cksum = 0xffff;
477 } 506 }
478 507
479//BUG! verbose is (x & OPT_VERBOSE), not a counter! 508//BUG! verbose is (x & OPT_VERBOSE), not a counter!
@@ -502,7 +531,6 @@ send_probe(int seq, int ttl)
502 } 531 }
503#endif 532#endif
504 533
505 out = outdata;
506#if ENABLE_TRACEROUTE6 534#if ENABLE_TRACEROUTE6
507 if (dest_lsa->u.sa.sa_family == AF_INET6) { 535 if (dest_lsa->u.sa.sa_family == AF_INET6) {
508 res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); 536 res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl);
@@ -516,8 +544,6 @@ send_probe(int seq, int ttl)
516 if (res != 0) 544 if (res != 0)
517 bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); 545 bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl);
518#endif 546#endif
519 if (option_mask32 & OPT_USE_ICMP)
520 out = outicmp;
521 } 547 }
522 548
523 if (!(option_mask32 & OPT_USE_ICMP)) { 549 if (!(option_mask32 & OPT_USE_ICMP)) {
@@ -579,7 +605,12 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq)
579 int hlen; 605 int hlen;
580 const struct ip *ip; 606 const struct ip *ip;
581 607
608 /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket
609 * return the entire IP packet (IOW: they do not strip IP header).
610 * This differs from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) sockets!?
611 */
582 ip = (struct ip *) recv_pkt; 612 ip = (struct ip *) recv_pkt;
613
583 hlen = ip->ip_hl << 2; 614 hlen = ip->ip_hl << 2;
584 if (read_len < hlen + ICMP_MINLEN) { 615 if (read_len < hlen + ICMP_MINLEN) {
585#if ENABLE_FEATURE_TRACEROUTE_VERBOSE 616#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
@@ -598,9 +629,20 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq)
598 if (code == ICMP_UNREACH_NEEDFRAG) 629 if (code == ICMP_UNREACH_NEEDFRAG)
599 pmtu = ntohs(icp->icmp_nextmtu); 630 pmtu = ntohs(icp->icmp_nextmtu);
600 631
632 if ((option_mask32 & OPT_USE_ICMP)
633 && type == ICMP_ECHOREPLY
634 && icp->icmp_id == htons(ident)
635 && icp->icmp_seq == htons(seq)
636 ) {
637 /* In UDP mode, when we reach the machine, we (usually)
638 * would get "port unreachable" - in ICMP we got "echo reply".
639 * Simulate "port unreachable" for caller:
640 */
641 return ICMP_UNREACH_PORT+1;
642 }
643
601 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) 644 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS)
602 || type == ICMP_UNREACH 645 || type == ICMP_UNREACH
603 || type == ICMP_ECHOREPLY
604 ) { 646 ) {
605 const struct ip *hip; 647 const struct ip *hip;
606 const struct udphdr *up; 648 const struct udphdr *up;
@@ -610,14 +652,6 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq)
610 if (option_mask32 & OPT_USE_ICMP) { 652 if (option_mask32 & OPT_USE_ICMP) {
611 struct icmp *hicmp; 653 struct icmp *hicmp;
612 654
613 /* XXX */
614 if (type == ICMP_ECHOREPLY
615 && icp->icmp_id == htons(ident)
616 && icp->icmp_seq == htons(seq)
617 ) {
618 return ICMP_UNREACH_PORT+1;
619 }
620
621 hicmp = (struct icmp *)((unsigned char *)hip + hlen); 655 hicmp = (struct icmp *)((unsigned char *)hip + hlen);
622 if (hlen + SIZEOF_ICMP_HDR <= read_len 656 if (hlen + SIZEOF_ICMP_HDR <= read_len
623 && hip->ip_p == IPPROTO_ICMP 657 && hip->ip_p == IPPROTO_ICMP
@@ -648,6 +682,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq)
648 printf("\n%d bytes from %s to " 682 printf("\n%d bytes from %s to "
649 "%s: icmp type %d (%s) code %d\n", 683 "%s: icmp type %d (%s) code %d\n",
650 read_len, inet_ntoa(from->sin_addr), 684 read_len, inet_ntoa(from->sin_addr),
685//BUG: inet_ntoa() returns static buf! x2 is NONO!
651 inet_ntoa(ip->ip_dst), 686 inet_ntoa(ip->ip_dst),
652 type, pr_type(type), icp->icmp_code); 687 type, pr_type(type), icp->icmp_code);
653 for (i = 4; i < read_len; i += sizeof(*lp)) 688 for (i = 4; i < read_len; i += sizeof(*lp))
@@ -673,11 +708,27 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa,
673 if (from_lsa->u.sa.sa_family == AF_INET) 708 if (from_lsa->u.sa.sa_family == AF_INET)
674 return packet4_ok(read_len, &from_lsa->u.sin, seq); 709 return packet4_ok(read_len, &from_lsa->u.sin, seq);
675 710
711 /* NB: reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) socket
712 * return only ICMP packet (IOW: they strip IPv6 header).
713 * This differs from (AF_INET, SOCK_RAW, IPPROTO_ICMP) sockets!?
714 */
676 icp = (struct icmp6_hdr *) recv_pkt; 715 icp = (struct icmp6_hdr *) recv_pkt;
677 716
678 type = icp->icmp6_type; 717 type = icp->icmp6_type;
679 code = icp->icmp6_code; 718 code = icp->icmp6_code;
680 719
720 if ((option_mask32 & OPT_USE_ICMP)
721 && type == ICMP6_ECHO_REPLY
722 && icp->icmp6_id == htons(ident)
723 && icp->icmp6_seq == htons(seq)
724 ) {
725 /* In UDP mode, when we reach the machine, we (usually)
726 * would get "port unreachable" - in ICMP we got "echo reply".
727 * Simulate "port unreachable" for caller:
728 */
729 return (ICMP6_DST_UNREACH_NOPORT << 8) + 1;
730 }
731
681 if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) 732 if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
682 || type == ICMP6_DST_UNREACH 733 || type == ICMP6_DST_UNREACH
683 ) { 734 ) {
@@ -787,8 +838,13 @@ print(int read_len, const struct sockaddr *from, const struct sockaddr *to)
787 if (verbose) { 838 if (verbose) {
788 char *ina = xmalloc_sockaddr2dotted_noport(to); 839 char *ina = xmalloc_sockaddr2dotted_noport(to);
789#if ENABLE_TRACEROUTE6 840#if ENABLE_TRACEROUTE6
841 /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket
842 * return the entire IP packet (IOW: they do not strip IP header).
843 * Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6
844 * header and return only ICMP6 packet. Weird.
845 */
790 if (to->sa_family == AF_INET6) { 846 if (to->sa_family == AF_INET6) {
791 read_len -= sizeof(struct ip6_hdr); 847 /* read_len -= sizeof(struct ip6_hdr); - WRONG! */
792 } else 848 } else
793#endif 849#endif
794 { 850 {
@@ -844,6 +900,9 @@ common_traceroute_main(int op, char **argv)
844 struct sockaddr *lastaddr; 900 struct sockaddr *lastaddr;
845 struct sockaddr *to; 901 struct sockaddr *to;
846 902
903 /* Ensure the socket fds won't be 0, 1 or 2 */
904 bb_sanitize_stdio();
905
847 INIT_G(); 906 INIT_G();
848 907
849 op |= getopt32(argv, "^" 908 op |= getopt32(argv, "^"
@@ -885,12 +944,14 @@ common_traceroute_main(int op, char **argv)
885 944
886 /* Process destination and optional packet size */ 945 /* Process destination and optional packet size */
887 minpacket = sizeof(struct ip) 946 minpacket = sizeof(struct ip)
888 + SIZEOF_ICMP_HDR 947 + sizeof(struct udphdr)
889 + sizeof(struct outdata_t); 948 + sizeof(struct outdata_t);
890 if (!(op & OPT_USE_ICMP)) 949 if (op & OPT_USE_ICMP) {
891 minpacket = sizeof(struct ip) 950 minpacket = sizeof(struct ip)
892 + sizeof(struct udphdr) 951 + SIZEOF_ICMP_HDR
893 + sizeof(struct outdata_t); 952 + sizeof(struct outdata_t);
953 port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL */
954 }
894#if ENABLE_TRACEROUTE6 955#if ENABLE_TRACEROUTE6
895 af = AF_UNSPEC; 956 af = AF_UNSPEC;
896 if (op & OPT_IPV4) 957 if (op & OPT_IPV4)
@@ -899,10 +960,15 @@ common_traceroute_main(int op, char **argv)
899 af = AF_INET6; 960 af = AF_INET6;
900 dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); 961 dest_lsa = xhost_and_af2sockaddr(argv[0], port, af);
901 af = dest_lsa->u.sa.sa_family; 962 af = dest_lsa->u.sa.sa_family;
902 if (af == AF_INET6) 963 if (af == AF_INET6) {
903 minpacket = sizeof(struct ip6_hdr) 964 minpacket = sizeof(struct ip6_hdr)
904 + sizeof(struct udphdr) 965 + sizeof(struct udphdr)
905 + sizeof(struct outdata6_t); 966 + sizeof(struct outdata6_t);
967 if (op & OPT_USE_ICMP)
968 minpacket = sizeof(struct ip6_hdr)
969 + SIZEOF_ICMP_HDR
970 + sizeof(struct outdata6_t);
971 }
906#else 972#else
907 dest_lsa = xhost2sockaddr(argv[0], port); 973 dest_lsa = xhost2sockaddr(argv[0], port);
908#endif 974#endif
@@ -910,13 +976,10 @@ common_traceroute_main(int op, char **argv)
910 if (argv[1]) 976 if (argv[1])
911 packlen = xatoul_range(argv[1], minpacket, 32 * 1024); 977 packlen = xatoul_range(argv[1], minpacket, 32 * 1024);
912 978
913 /* Ensure the socket fds won't be 0, 1 or 2 */
914 bb_sanitize_stdio();
915
916#if ENABLE_TRACEROUTE6 979#if ENABLE_TRACEROUTE6
917 if (af == AF_INET6) { 980 if (af == AF_INET6) {
918 xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); 981 xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
919 setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); 982 setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); //why?
920 } else 983 } else
921#endif 984#endif
922 { 985 {
@@ -934,7 +997,10 @@ common_traceroute_main(int op, char **argv)
934 if (af == AF_INET6) { 997 if (af == AF_INET6) {
935 if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) 998 if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
936 bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); 999 bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
937 xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock); 1000 if (op & OPT_USE_ICMP)
1001 xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), sndsock);
1002 else
1003 xmove_fd(xsocket(AF_INET6, SOCK_DGRAM, 0), sndsock);
938 } else 1004 } else
939#endif 1005#endif
940 { 1006 {
@@ -943,6 +1009,7 @@ common_traceroute_main(int op, char **argv)
943 else 1009 else
944 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); 1010 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock);
945 } 1011 }
1012//TODO xmove_fd to here!
946 1013
947#ifdef SO_SNDBUF 1014#ifdef SO_SNDBUF
948 if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) { 1015 if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) {
@@ -970,21 +1037,25 @@ common_traceroute_main(int op, char **argv)
970 ident = getpid(); 1037 ident = getpid();
971 1038
972 if (!ENABLE_TRACEROUTE6 || af == AF_INET) { 1039 if (!ENABLE_TRACEROUTE6 || af == AF_INET) {
1040 outdata = (void*)(outudp + 1);
973 if (op & OPT_USE_ICMP) { 1041 if (op & OPT_USE_ICMP) {
974 ident |= 0x8000; 1042 ident |= 0x8000;
975 outicmp->icmp_type = ICMP_ECHO; 1043 outicmp->icmp_type = ICMP_ECHO;
1044 /*outicmp->icmp_code = 0; - set by xzalloc */
976 outicmp->icmp_id = htons(ident); 1045 outicmp->icmp_id = htons(ident);
977 outdata = (struct outdata_t *)((char *)outicmp + SIZEOF_ICMP_HDR); 1046 outdata = (void*)((char *)outicmp + SIZEOF_ICMP_HDR);
978 } else {
979 outdata = (struct outdata_t *)(outudp + 1);
980 } 1047 }
981 } 1048 }
982#if ENABLE_TRACEROUTE6 1049#if ENABLE_TRACEROUTE6
983 if (af == AF_INET6) { 1050 if (af == AF_INET6) {
984 outdata = (void*)((char*)outip 1051 outdata = (void*)(outudp6 + 1);
985 + sizeof(struct ip6_hdr) 1052 if (op & OPT_USE_ICMP) {
986 + sizeof(struct udphdr) 1053 ident |= 0x8000;
987 ); 1054 outicmp6->icmp_type = ICMP6_ECHO_REQUEST;
1055 /*outicmp->icmp_code = 0; - set by xzalloc */
1056 outicmp6->icmp_id = htons(ident);
1057 outdata = (void*)((char *)outicmp6 + SIZEOF_ICMP_HDR);
1058 }
988 } 1059 }
989#endif 1060#endif
990 1061
@@ -1013,26 +1084,16 @@ common_traceroute_main(int op, char **argv)
1013//TODO: why we don't do it for IPv4? 1084//TODO: why we don't do it for IPv4?
1014 len_and_sockaddr *source_lsa; 1085 len_and_sockaddr *source_lsa;
1015 1086
1016 int probe_fd = xsocket(af, SOCK_DGRAM, 0);
1017 if (op & OPT_DEVICE)
1018 setsockopt_bindtodevice(probe_fd, device);
1019 set_nport(&dest_lsa->u.sa, htons(1025));
1020 /* dummy connect. makes kernel pick source IP (and port) */
1021 xconnect(probe_fd, &dest_lsa->u.sa, dest_lsa->len);
1022 set_nport(&dest_lsa->u.sa, htons(port)); 1087 set_nport(&dest_lsa->u.sa, htons(port));
1023 1088 /* Connect makes kernel pick source IP and port */
1024 /* read IP and port */ 1089 xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len);
1025 source_lsa = get_sock_lsa(probe_fd); 1090 /* Read IP and port */
1091 source_lsa = get_sock_lsa(sndsock);
1026 if (source_lsa == NULL) 1092 if (source_lsa == NULL)
1027 bb_simple_error_msg_and_die("can't get probe addr"); 1093 bb_simple_error_msg_and_die("can't get probe addr");
1028 1094 /* bind our recv socket to this IP (but not port) */
1029 close(probe_fd);
1030
1031 /* bind our sockets to this IP (but not port) */
1032 set_nport(&source_lsa->u.sa, 0); 1095 set_nport(&source_lsa->u.sa, 0);
1033 xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
1034 xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); 1096 xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
1035
1036 free(source_lsa); 1097 free(source_lsa);
1037 } 1098 }
1038#endif 1099#endif
@@ -1067,10 +1128,9 @@ common_traceroute_main(int op, char **argv)
1067 unsigned t1; 1128 unsigned t1;
1068 unsigned t2; 1129 unsigned t2;
1069 int left_ms; 1130 int left_ms;
1070 struct ip *ip;
1071 1131
1072 fflush_all(); 1132 fflush_all();
1073 if (probe != 0 && pausemsecs > 0) 1133 if (probe != 0)
1074 msleep(pausemsecs); 1134 msleep(pausemsecs);
1075 1135
1076 send_probe(++seq, ttl); 1136 send_probe(++seq, ttl);
@@ -1099,15 +1159,18 @@ common_traceroute_main(int op, char **argv)
1099 } 1159 }
1100 1160
1101 print_delta_ms(t1, t2); 1161 print_delta_ms(t1, t2);
1102 ip = (struct ip *)recv_pkt;
1103 1162
1104 if (from_lsa->u.sa.sa_family == AF_INET) 1163 if (from_lsa->u.sa.sa_family == AF_INET) {
1105 if (op & OPT_TTL_FLAG) 1164 if (op & OPT_TTL_FLAG) {
1165 struct ip *ip = (struct ip *)recv_pkt;
1106 printf(" (%d)", ip->ip_ttl); 1166 printf(" (%d)", ip->ip_ttl);
1167 }
1168 }
1107 1169
1108 /* time exceeded in transit */ 1170 /* Got a "time exceeded in transit" icmp message? */
1109 if (icmp_code == -1) 1171 if (icmp_code == -1)
1110 break; 1172 break;
1173
1111 icmp_code--; 1174 icmp_code--;
1112 switch (icmp_code) { 1175 switch (icmp_code) {
1113#if ENABLE_TRACEROUTE6 1176#if ENABLE_TRACEROUTE6
@@ -1115,12 +1178,13 @@ common_traceroute_main(int op, char **argv)
1115 got_there = 1; 1178 got_there = 1;
1116 break; 1179 break;
1117#endif 1180#endif
1118 case ICMP_UNREACH_PORT: 1181 case ICMP_UNREACH_PORT: {
1182 struct ip *ip = (struct ip *)recv_pkt;
1119 if (ip->ip_ttl <= 1) 1183 if (ip->ip_ttl <= 1)
1120 printf(" !"); 1184 printf(" !");
1121 got_there = 1; 1185 got_there = 1;
1122 break; 1186 break;
1123 1187 }
1124 case ICMP_UNREACH_NET: 1188 case ICMP_UNREACH_NET:
1125#if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET) 1189#if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET)
1126 case ICMP6_DST_UNREACH_NOROUTE << 8: 1190 case ICMP6_DST_UNREACH_NOROUTE << 8: