aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/traceroute.c61
1 files changed, 37 insertions, 24 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 96f9d3472..85181ab8d 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -398,18 +398,23 @@ static len_and_sockaddr* dup_sockaddr(const len_and_sockaddr *lsa)
398 398
399 399
400static int 400static int
401wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to) 401wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms)
402{ 402{
403 struct pollfd pfd[1]; 403 struct pollfd pfd[1];
404 int read_len = 0; 404 int read_len = 0;
405 405
406 pfd[0].fd = rcvsock; 406 pfd[0].fd = rcvsock;
407 pfd[0].events = POLLIN; 407 pfd[0].events = POLLIN;
408 if (safe_poll(pfd, 1, waittime * 1000) > 0) { 408 if (*left_ms >= 0 && safe_poll(pfd, 1, *left_ms) > 0) {
409 unsigned t;
410
409 read_len = recv_from_to(rcvsock, 411 read_len = recv_from_to(rcvsock,
410 recv_pkt, sizeof(recv_pkt), 412 recv_pkt, sizeof(recv_pkt),
411 /*flags:*/ 0, 413 /*flags:*/ MSG_DONTWAIT,
412 &from_lsa->u.sa, to, from_lsa->len); 414 &from_lsa->u.sa, to, from_lsa->len);
415 t = monotonic_us();
416 *left_ms -= (t - *timestamp_us) / 1000;
417 *timestamp_us = t;
413 } 418 }
414 419
415 return read_len; 420 return read_len;
@@ -730,7 +735,7 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa,
730 type, pr_type(type), icp->icmp6_code); 735 type, pr_type(type), icp->icmp6_code);
731 736
732 read_len -= sizeof(struct icmp6_hdr); 737 read_len -= sizeof(struct icmp6_hdr);
733 for (i = 0; i < read_len ; i++) { 738 for (i = 0; i < read_len; i++) {
734 if (i % 16 == 0) 739 if (i % 16 == 0)
735 printf("%04x:", i); 740 printf("%04x:", i);
736 if (i % 4 == 0) 741 if (i % 4 == 0)
@@ -819,7 +824,6 @@ print_delta_ms(unsigned t1p, unsigned t2p)
819static int 824static int
820common_traceroute_main(int op, char **argv) 825common_traceroute_main(int op, char **argv)
821{ 826{
822 int i;
823 int minpacket; 827 int minpacket;
824 int tos = 0; 828 int tos = 0;
825 int max_ttl = 30; 829 int max_ttl = 30;
@@ -973,6 +977,7 @@ common_traceroute_main(int op, char **argv)
973#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE && defined IP_OPTIONS 977#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE && defined IP_OPTIONS
974 if (lsrr > 0) { 978 if (lsrr > 0) {
975 unsigned char optlist[MAX_IPOPTLEN]; 979 unsigned char optlist[MAX_IPOPTLEN];
980 unsigned size;
976 981
977 /* final hop */ 982 /* final hop */
978 gwlist[lsrr] = dest_lsa->u.sin.sin_addr.s_addr; 983 gwlist[lsrr] = dest_lsa->u.sin.sin_addr.s_addr;
@@ -982,14 +987,14 @@ common_traceroute_main(int op, char **argv)
982 optlist[0] = IPOPT_NOP; 987 optlist[0] = IPOPT_NOP;
983 /* loose source route option */ 988 /* loose source route option */
984 optlist[1] = IPOPT_LSRR; 989 optlist[1] = IPOPT_LSRR;
985 i = lsrr * sizeof(gwlist[0]); 990 size = lsrr * sizeof(gwlist[0]);
986 optlist[2] = i + 3; 991 optlist[2] = size + 3;
987 /* pointer to LSRR addresses */ 992 /* pointer to LSRR addresses */
988 optlist[3] = IPOPT_MINOFF; 993 optlist[3] = IPOPT_MINOFF;
989 memcpy(optlist + 4, gwlist, i); 994 memcpy(optlist + 4, gwlist, size);
990 995
991 if (setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, 996 if (setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
992 (char *)optlist, i + sizeof(gwlist[0])) < 0) { 997 (char *)optlist, size + sizeof(gwlist[0])) < 0) {
993 bb_perror_msg_and_die("IP_OPTIONS"); 998 bb_perror_msg_and_die("IP_OPTIONS");
994 } 999 }
995 } 1000 }
@@ -1103,28 +1108,34 @@ common_traceroute_main(int op, char **argv)
1103 int unreachable = 0; /* counter */ 1108 int unreachable = 0; /* counter */
1104 int gotlastaddr = 0; /* flags */ 1109 int gotlastaddr = 0; /* flags */
1105 int got_there = 0; 1110 int got_there = 0;
1106 int first = 1;
1107 1111
1108 printf("%2d", ttl); 1112 printf("%2d", ttl);
1109 for (probe = 0; probe < nprobes; ++probe) { 1113 for (probe = 0; probe < nprobes; ++probe) {
1110 int read_len; 1114 int read_len;
1111 unsigned t1; 1115 unsigned t1;
1112 unsigned t2; 1116 unsigned t2;
1117 int left_ms;
1113 struct ip *ip; 1118 struct ip *ip;
1114 1119
1115 if (!first && pausemsecs > 0)
1116 usleep(pausemsecs * 1000);
1117 fflush_all(); 1120 fflush_all();
1121 if (probe != 0 && pausemsecs > 0)
1122 usleep(pausemsecs * 1000);
1118 1123
1119 t1 = monotonic_us();
1120 send_probe(++seq, ttl); 1124 send_probe(++seq, ttl);
1125 t2 = t1 = monotonic_us();
1126
1127 left_ms = waittime * 1000;
1128 while ((read_len = wait_for_reply(from_lsa, to, &t2, &left_ms)) != 0) {
1129 int icmp_code;
1130
1131 /* Recv'ed a packet, or read error */
1132 /* t2 = monotonic_us() - set by wait_for_reply */
1121 1133
1122 first = 0; 1134 if (read_len < 0)
1123 while ((read_len = wait_for_reply(from_lsa, to)) != 0) { 1135 continue;
1124 t2 = monotonic_us(); 1136 icmp_code = packet_ok(read_len, from_lsa, to, seq);
1125 i = packet_ok(read_len, from_lsa, to, seq);
1126 /* Skip short packet */ 1137 /* Skip short packet */
1127 if (i == 0) 1138 if (icmp_code == 0)
1128 continue; 1139 continue;
1129 1140
1130 if (!gotlastaddr 1141 if (!gotlastaddr
@@ -1143,10 +1154,10 @@ common_traceroute_main(int op, char **argv)
1143 printf(" (%d)", ip->ip_ttl); 1154 printf(" (%d)", ip->ip_ttl);
1144 1155
1145 /* time exceeded in transit */ 1156 /* time exceeded in transit */
1146 if (i == -1) 1157 if (icmp_code == -1)
1147 break; 1158 break;
1148 i--; 1159 icmp_code--;
1149 switch (i) { 1160 switch (icmp_code) {
1150#if ENABLE_TRACEROUTE6 1161#if ENABLE_TRACEROUTE6
1151 case ICMP6_DST_UNREACH_NOPORT << 8: 1162 case ICMP6_DST_UNREACH_NOPORT << 8:
1152 got_there = 1; 1163 got_there = 1;
@@ -1219,16 +1230,18 @@ common_traceroute_main(int op, char **argv)
1219 ++unreachable; 1230 ++unreachable;
1220 break; 1231 break;
1221 default: 1232 default:
1222 printf(" !<%d>", i); 1233 printf(" !<%d>", icmp_code);
1223 ++unreachable; 1234 ++unreachable;
1224 break; 1235 break;
1225 } 1236 }
1226 break; 1237 break;
1227 } 1238 } /* while (wait and read a packet) */
1239
1228 /* there was no packet at all? */ 1240 /* there was no packet at all? */
1229 if (read_len == 0) 1241 if (read_len == 0)
1230 printf(" *"); 1242 printf(" *");
1231 } 1243 } /* for (nprobes) */
1244
1232 bb_putchar('\n'); 1245 bb_putchar('\n');
1233 if (got_there 1246 if (got_there
1234 || (unreachable > 0 && unreachable >= nprobes - 1) 1247 || (unreachable > 0 && unreachable >= nprobes - 1)