aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-12-12 21:44:32 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-12-12 21:44:32 +0100
commit724c7df683b8f3d0c487ce3d3cdcc1f6e762c181 (patch)
tree2d63c3ebaec9c46d87d75f2501be7cbf93087359
parente76f03b267aed3c7c9a247ef4b27e1bb1c56e024 (diff)
downloadbusybox-w32-724c7df683b8f3d0c487ce3d3cdcc1f6e762c181.tar.gz
busybox-w32-724c7df683b8f3d0c487ce3d3cdcc1f6e762c181.tar.bz2
busybox-w32-724c7df683b8f3d0c487ce3d3cdcc1f6e762c181.zip
traceroute: untangle main loop
function old new delta common_traceroute_main 1785 1730 -55 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/traceroute.c218
1 files 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)
463 recv_pkt, sizeof(recv_pkt), 463 recv_pkt, sizeof(recv_pkt),
464 /*flags:*/ MSG_DONTWAIT, 464 /*flags:*/ MSG_DONTWAIT,
465 &G.from_lsa->u.sa, G.to, G.from_lsa->len); 465 &G.from_lsa->u.sa, G.to, G.from_lsa->len);
466 if (read_len < 0)
467 bb_perror_msg_and_die("recv");
466 t = monotonic_us(); 468 t = monotonic_us();
467 *left_ms -= (t - *timestamp_us) / 1000; 469 *left_ms -= (t - *timestamp_us) / 1000;
468 *timestamp_us = t; 470 *timestamp_us = t;
@@ -1076,147 +1078,139 @@ common_traceroute_main(int op, char **argv)
1076 for (ttl = G.first_ttl; ttl <= G.max_ttl; ++ttl) { 1078 for (ttl = G.first_ttl; ttl <= G.max_ttl; ++ttl) {
1077 int probe; 1079 int probe;
1078 int unreachable = 0; /* counter */ 1080 int unreachable = 0; /* counter */
1079 int gotlastaddr = 0; /* flags */
1080 int got_there = 0; 1081 int got_there = 0;
1081 1082
1082 printf("%2d", ttl); 1083 printf("%2d", ttl);
1083 for (probe = 0; probe < G.nprobes; ++probe) { 1084 for (probe = 0; probe < G.nprobes; ++probe) {
1084 int read_len;
1085 unsigned t1; 1085 unsigned t1;
1086 unsigned t2; 1086 unsigned t2;
1087 int left_ms; 1087 int left_ms;
1088 int read_len;
1089 int icmp_code;
1088 1090
1089 fflush_all(); 1091 fflush_all();
1090 if (probe != 0) 1092 if (probe != 0)
1091 msleep(G.pausemsecs); 1093 msleep(G.pausemsecs);
1092 1094
1093 send_probe(++seq, ttl); 1095 send_probe(++seq, ttl);
1094 t2 = t1 = monotonic_us();
1095 1096
1097 t2 = t1 = monotonic_us();
1096 left_ms = waittime * 1000; 1098 left_ms = waittime * 1000;
1097 /* NB: wait_for_reply() fills "G.from_lsa" and "G.to" with 1099 for (;;) {
1098 * "where it came from" and "what local address it arrived to" 1100 /* NB: wait_for_reply() fills "G.from_lsa" and "G.to" with
1099 * addresses. 1101 * "where it came from" and "what local address it arrived to"
1100 */ 1102 * addresses. Sets t2 = monotonic_us(), updates left_ms.
1101 while ((read_len = wait_for_reply(&t2, &left_ms)) != 0) { 1103 */
1102 int icmp_code; 1104 read_len = wait_for_reply(&t2, &left_ms);
1103 1105
1104 /* Recv'ed a packet, or read error */ 1106 if (read_len == 0) { /* there was no packet at all? */
1105 /* t2 = monotonic_us() - set by wait_for_reply */ 1107 printf(" *");
1106 1108 goto next_probe;
1107 if (read_len < 0)
1108 continue;
1109 icmp_code = packet_ok(read_len, seq);
1110 /* Skip short packet */
1111 if (icmp_code == 0)
1112 continue;
1113
1114 if (!gotlastaddr
1115 || (memcmp(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len) != 0)
1116 ) {
1117 print(read_len);
1118 memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len);
1119 gotlastaddr = 1;
1120 } 1109 }
1110 icmp_code = packet_ok(read_len, seq);
1111 if (icmp_code != 0)
1112 break; /* got a good response */
1113 /* unrecognized type/code or too short, back to recv */
1114 }
1121 1115
1122 print_delta_ms(t1, t2); 1116 if (probe == 0
1123 1117 || (memcmp(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len) != 0)
1124 if (G.from_lsa->u.sa.sa_family == AF_INET) { 1118 ) {
1125 if (op & OPT_TTL_FLAG) { 1119 print(read_len);
1126 struct ip *ip = (struct ip *)recv_pkt; 1120 memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len);
1127 printf(" (%d)", ip->ip_ttl); 1121 }
1128 } 1122 print_delta_ms(t1, t2);
1123 if (G.from_lsa->u.sa.sa_family == AF_INET) {
1124 if (op & OPT_TTL_FLAG) {
1125 struct ip *ip = (struct ip *)recv_pkt;
1126 printf(" (%d)", ip->ip_ttl);
1129 } 1127 }
1128 }
1130 1129
1131 /* Got a "time exceeded in transit" icmp message? */ 1130 /* Got a "time exceeded in transit" icmp message? */
1132 if (icmp_code == -1) 1131 if (icmp_code == -1)
1133 break; 1132 continue;
1134 1133
1135 icmp_code--; 1134 icmp_code--;
1136 switch (icmp_code) { 1135 switch (icmp_code) {
1137#if ENABLE_TRACEROUTE6 1136#if ENABLE_TRACEROUTE6
1138 case ICMP6_DST_UNREACH_NOPORT << 8: 1137 case ICMP6_DST_UNREACH_NOPORT << 8:
1139 got_there = 1; 1138 got_there = 1;
1140 break; 1139 break;
1141#endif 1140#endif
1142 case ICMP_UNREACH_PORT: { 1141 case ICMP_UNREACH_PORT: {
1143 struct ip *ip = (struct ip *)recv_pkt; 1142 struct ip *ip = (struct ip *)recv_pkt;
1144 if (ip->ip_ttl <= 1) 1143 if (ip->ip_ttl <= 1)
1145 printf(" !"); 1144 printf(" !");
1146 got_there = 1; 1145 got_there = 1;
1147 break; 1146 break;
1148 } 1147 }
1149 case ICMP_UNREACH_NET: 1148 case ICMP_UNREACH_NET:
1150#if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET) 1149#if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET)
1151 case ICMP6_DST_UNREACH_NOROUTE << 8: 1150 case ICMP6_DST_UNREACH_NOROUTE << 8:
1152#endif 1151#endif
1153 printf(" !N"); 1152 printf(" !N");
1154 ++unreachable; 1153 ++unreachable;
1155 break; 1154 break;
1156 case ICMP_UNREACH_HOST: 1155 case ICMP_UNREACH_HOST:
1157#if ENABLE_TRACEROUTE6 1156#if ENABLE_TRACEROUTE6
1158 case ICMP6_DST_UNREACH_ADDR << 8: 1157 case ICMP6_DST_UNREACH_ADDR << 8:
1159#endif 1158#endif
1160 printf(" !H"); 1159 printf(" !H");
1161 ++unreachable; 1160 ++unreachable;
1162 break; 1161 break;
1163 case ICMP_UNREACH_PROTOCOL: 1162 case ICMP_UNREACH_PROTOCOL:
1164 printf(" !P"); 1163 printf(" !P");
1165 got_there = 1; 1164 got_there = 1;
1166 break; 1165 break;
1167 case ICMP_UNREACH_NEEDFRAG: 1166 case ICMP_UNREACH_NEEDFRAG:
1168 printf(" !F-%d", pmtu); 1167 printf(" !F-%d", pmtu);
1169 ++unreachable; 1168 ++unreachable;
1170 break; 1169 break;
1171 case ICMP_UNREACH_SRCFAIL: 1170 case ICMP_UNREACH_SRCFAIL:
1172#if ENABLE_TRACEROUTE6 1171#if ENABLE_TRACEROUTE6
1173 case ICMP6_DST_UNREACH_ADMIN << 8: 1172 case ICMP6_DST_UNREACH_ADMIN << 8:
1174#endif 1173#endif
1175 printf(" !S"); 1174 printf(" !S");
1176 ++unreachable; 1175 ++unreachable;
1177 break;
1178 case ICMP_UNREACH_FILTER_PROHIB:
1179 case ICMP_UNREACH_NET_PROHIB: /* misuse */
1180 printf(" !A");
1181 ++unreachable;
1182 break;
1183 case ICMP_UNREACH_HOST_PROHIB:
1184 printf(" !C");
1185 ++unreachable;
1186 break;
1187 case ICMP_UNREACH_HOST_PRECEDENCE:
1188 printf(" !V");
1189 ++unreachable;
1190 break;
1191 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1192 printf(" !C");
1193 ++unreachable;
1194 break;
1195 case ICMP_UNREACH_NET_UNKNOWN:
1196 case ICMP_UNREACH_HOST_UNKNOWN:
1197 printf(" !U");
1198 ++unreachable;
1199 break;
1200 case ICMP_UNREACH_ISOLATED:
1201 printf(" !I");
1202 ++unreachable;
1203 break;
1204 case ICMP_UNREACH_TOSNET:
1205 case ICMP_UNREACH_TOSHOST:
1206 printf(" !T");
1207 ++unreachable;
1208 break;
1209 default:
1210 printf(" !<%d>", icmp_code);
1211 ++unreachable;
1212 break;
1213 }
1214 break; 1176 break;
1215 } /* while (wait and read a packet) */ 1177 case ICMP_UNREACH_FILTER_PROHIB:
1216 1178 case ICMP_UNREACH_NET_PROHIB: /* misuse */
1217 /* there was no packet at all? */ 1179 printf(" !A");
1218 if (read_len == 0) 1180 ++unreachable;
1219 printf(" *"); 1181 break;
1182 case ICMP_UNREACH_HOST_PROHIB:
1183 printf(" !C");
1184 ++unreachable;
1185 break;
1186 case ICMP_UNREACH_HOST_PRECEDENCE:
1187 printf(" !V");
1188 ++unreachable;
1189 break;
1190 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1191 printf(" !C");
1192 ++unreachable;
1193 break;
1194 case ICMP_UNREACH_NET_UNKNOWN:
1195 case ICMP_UNREACH_HOST_UNKNOWN:
1196 printf(" !U");
1197 ++unreachable;
1198 break;
1199 case ICMP_UNREACH_ISOLATED:
1200 printf(" !I");
1201 ++unreachable;
1202 break;
1203 case ICMP_UNREACH_TOSNET:
1204 case ICMP_UNREACH_TOSHOST:
1205 printf(" !T");
1206 ++unreachable;
1207 break;
1208 default:
1209 printf(" !<%d>", icmp_code);
1210 ++unreachable;
1211 break;
1212 }
1213 next_probe: ;
1220 } /* for (nprobes) */ 1214 } /* for (nprobes) */
1221 1215
1222 bb_putchar('\n'); 1216 bb_putchar('\n');