[git commit] traceroute: untangle main loop

Denys Vlasenko vda.linux at googlemail.com
Sat Dec 12 20:44:32 UTC 2020


commit: https://git.busybox.net/busybox/commit/?id=724c7df683b8f3d0c487ce3d3cdcc1f6e762c181
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
common_traceroute_main                              1785    1730     -55

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/traceroute.c | 218 +++++++++++++++++++++++-------------------------
 1 file changed, 106 insertions(+), 112 deletions(-)

diff --git a/networking/traceroute.c b/networking/traceroute.c
index 0fb01ff5b..1e96a73cf 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -463,6 +463,8 @@ wait_for_reply(unsigned *timestamp_us, int *left_ms)
 				recv_pkt, sizeof(recv_pkt),
 				/*flags:*/ MSG_DONTWAIT,
 				&G.from_lsa->u.sa, G.to, G.from_lsa->len);
+		if (read_len < 0)
+			bb_perror_msg_and_die("recv");
 		t = monotonic_us();
 		*left_ms -= (t - *timestamp_us) / 1000;
 		*timestamp_us = t;
@@ -1076,147 +1078,139 @@ common_traceroute_main(int op, char **argv)
 	for (ttl = G.first_ttl; ttl <= G.max_ttl; ++ttl) {
 		int probe;
 		int unreachable = 0; /* counter */
-		int gotlastaddr = 0; /* flags */
 		int got_there = 0;
 
 		printf("%2d", ttl);
 		for (probe = 0; probe < G.nprobes; ++probe) {
-			int read_len;
 			unsigned t1;
 			unsigned t2;
 			int left_ms;
+			int read_len;
+			int icmp_code;
 
 			fflush_all();
 			if (probe != 0)
 				msleep(G.pausemsecs);
 
 			send_probe(++seq, ttl);
-			t2 = t1 = monotonic_us();
 
+			t2 = t1 = monotonic_us();
 			left_ms = waittime * 1000;
-			/* NB: wait_for_reply() fills "G.from_lsa" and "G.to" with
-			 * "where it came from" and "what local address it arrived to"
-			 * addresses.
-			 */
-			while ((read_len = wait_for_reply(&t2, &left_ms)) != 0) {
-				int icmp_code;
-
-				/* Recv'ed a packet, or read error */
-				/* t2 = monotonic_us() - set by wait_for_reply */
-
-				if (read_len < 0)
-					continue;
-				icmp_code = packet_ok(read_len, seq);
-				/* Skip short packet */
-				if (icmp_code == 0)
-					continue;
-
-				if (!gotlastaddr
-				 || (memcmp(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len) != 0)
-				) {
-					print(read_len);
-					memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len);
-					gotlastaddr = 1;
+			for (;;) {
+				/* NB: wait_for_reply() fills "G.from_lsa" and "G.to" with
+				 * "where it came from" and "what local address it arrived to"
+				 * addresses. Sets t2 = monotonic_us(), updates left_ms.
+				 */
+				read_len = wait_for_reply(&t2, &left_ms);
+
+				if (read_len == 0) { /* there was no packet at all? */
+					printf("  *");
+					goto next_probe;
 				}
+				icmp_code = packet_ok(read_len, seq);
+				if (icmp_code != 0)
+					break; /* got a good response */
+				/* unrecognized type/code or too short, back to recv */
+			}
 
-				print_delta_ms(t1, t2);
-
-				if (G.from_lsa->u.sa.sa_family == AF_INET) {
-					if (op & OPT_TTL_FLAG) {
-						struct ip *ip = (struct ip *)recv_pkt;
-						printf(" (%d)", ip->ip_ttl);
-					}
+			if (probe == 0
+			 || (memcmp(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len) != 0)
+			) {
+				print(read_len);
+				memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len);
+			}
+			print_delta_ms(t1, t2);
+			if (G.from_lsa->u.sa.sa_family == AF_INET) {
+				if (op & OPT_TTL_FLAG) {
+					struct ip *ip = (struct ip *)recv_pkt;
+					printf(" (%d)", ip->ip_ttl);
 				}
+			}
 
-				/* Got a "time exceeded in transit" icmp message? */
-				if (icmp_code == -1)
-					break;
+			/* Got a "time exceeded in transit" icmp message? */
+			if (icmp_code == -1)
+				continue;
 
-				icmp_code--;
-				switch (icmp_code) {
+			icmp_code--;
+			switch (icmp_code) {
 #if ENABLE_TRACEROUTE6
-				case ICMP6_DST_UNREACH_NOPORT << 8:
-					got_there = 1;
-					break;
+			case ICMP6_DST_UNREACH_NOPORT << 8:
+				got_there = 1;
+				break;
 #endif
-				case ICMP_UNREACH_PORT: {
-					struct ip *ip = (struct ip *)recv_pkt;
-					if (ip->ip_ttl <= 1)
-						printf(" !");
-					got_there = 1;
-					break;
-				}
-				case ICMP_UNREACH_NET:
+			case ICMP_UNREACH_PORT: {
+				struct ip *ip = (struct ip *)recv_pkt;
+				if (ip->ip_ttl <= 1)
+					printf(" !");
+				got_there = 1;
+				break;
+			}
+			case ICMP_UNREACH_NET:
 #if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET)
-				case ICMP6_DST_UNREACH_NOROUTE << 8:
+			case ICMP6_DST_UNREACH_NOROUTE << 8:
 #endif
-					printf(" !N");
-					++unreachable;
-					break;
-				case ICMP_UNREACH_HOST:
+				printf(" !N");
+				++unreachable;
+				break;
+			case ICMP_UNREACH_HOST:
 #if ENABLE_TRACEROUTE6
-				case ICMP6_DST_UNREACH_ADDR << 8:
+			case ICMP6_DST_UNREACH_ADDR << 8:
 #endif
-					printf(" !H");
-					++unreachable;
-					break;
-				case ICMP_UNREACH_PROTOCOL:
-					printf(" !P");
-					got_there = 1;
-					break;
-				case ICMP_UNREACH_NEEDFRAG:
-					printf(" !F-%d", pmtu);
-					++unreachable;
-					break;
-				case ICMP_UNREACH_SRCFAIL:
+				printf(" !H");
+				++unreachable;
+				break;
+			case ICMP_UNREACH_PROTOCOL:
+				printf(" !P");
+				got_there = 1;
+				break;
+			case ICMP_UNREACH_NEEDFRAG:
+				printf(" !F-%d", pmtu);
+				++unreachable;
+				break;
+			case ICMP_UNREACH_SRCFAIL:
 #if ENABLE_TRACEROUTE6
-				case ICMP6_DST_UNREACH_ADMIN << 8:
+			case ICMP6_DST_UNREACH_ADMIN << 8:
 #endif
-					printf(" !S");
-					++unreachable;
-					break;
-				case ICMP_UNREACH_FILTER_PROHIB:
-				case ICMP_UNREACH_NET_PROHIB:   /* misuse */
-					printf(" !A");
-					++unreachable;
-					break;
-				case ICMP_UNREACH_HOST_PROHIB:
-					printf(" !C");
-					++unreachable;
-					break;
-				case ICMP_UNREACH_HOST_PRECEDENCE:
-					printf(" !V");
-					++unreachable;
-					break;
-				case ICMP_UNREACH_PRECEDENCE_CUTOFF:
-					printf(" !C");
-					++unreachable;
-					break;
-				case ICMP_UNREACH_NET_UNKNOWN:
-				case ICMP_UNREACH_HOST_UNKNOWN:
-					printf(" !U");
-					++unreachable;
-					break;
-				case ICMP_UNREACH_ISOLATED:
-					printf(" !I");
-					++unreachable;
-					break;
-				case ICMP_UNREACH_TOSNET:
-				case ICMP_UNREACH_TOSHOST:
-					printf(" !T");
-					++unreachable;
-					break;
-				default:
-					printf(" !<%d>", icmp_code);
-					++unreachable;
-					break;
-				}
+				printf(" !S");
+				++unreachable;
 				break;
-			} /* while (wait and read a packet) */
-
-			/* there was no packet at all? */
-			if (read_len == 0)
-				printf("  *");
+			case ICMP_UNREACH_FILTER_PROHIB:
+			case ICMP_UNREACH_NET_PROHIB:   /* misuse */
+				printf(" !A");
+				++unreachable;
+				break;
+			case ICMP_UNREACH_HOST_PROHIB:
+				printf(" !C");
+				++unreachable;
+				break;
+			case ICMP_UNREACH_HOST_PRECEDENCE:
+				printf(" !V");
+				++unreachable;
+				break;
+			case ICMP_UNREACH_PRECEDENCE_CUTOFF:
+				printf(" !C");
+				++unreachable;
+				break;
+			case ICMP_UNREACH_NET_UNKNOWN:
+			case ICMP_UNREACH_HOST_UNKNOWN:
+				printf(" !U");
+				++unreachable;
+				break;
+			case ICMP_UNREACH_ISOLATED:
+				printf(" !I");
+				++unreachable;
+				break;
+			case ICMP_UNREACH_TOSNET:
+			case ICMP_UNREACH_TOSHOST:
+				printf(" !T");
+				++unreachable;
+				break;
+			default:
+				printf(" !<%d>", icmp_code);
+				++unreachable;
+				break;
+			}
+ next_probe: ;
 		} /* for (nprobes) */
 
 		bb_putchar('\n');


More information about the busybox-cvs mailing list