aboutsummaryrefslogtreecommitdiff
path: root/networking/traceroute.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-09-28 18:39:06 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-09-28 18:44:48 +0200
commit1c32e49bdf74dfe47cae108d06702996ead052f0 (patch)
tree129680cd72ef41bb9a64a3ca0edd2634cf430d1c /networking/traceroute.c
parent61fcc8c78174f92fbdad0a7f86b5086619b05ed9 (diff)
downloadbusybox-w32-1c32e49bdf74dfe47cae108d06702996ead052f0.tar.gz
busybox-w32-1c32e49bdf74dfe47cae108d06702996ead052f0.tar.bz2
busybox-w32-1c32e49bdf74dfe47cae108d06702996ead052f0.zip
traceroute: cleanup and fixes for packet size calculations
Remove FEATURE_TRACEROUTE_SOURCE_ROUTE: it's off by default, and source routing is not used in real world. Tested that "traceroute -n ::1 100" and "traceroute -n 127.0.0.1 100" both send 100 byte IP packets (this matches what traceroute on Fedora Rawhide is doing). function old new delta common_traceroute_main 3731 3738 +7 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to '')
-rw-r--r--networking/traceroute.c124
1 files changed, 38 insertions, 86 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c
index e43a36dc7..b9a9ca4bb 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -212,8 +212,7 @@
212 212
213//usage:#define traceroute_trivial_usage 213//usage:#define traceroute_trivial_usage
214//usage: "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n" 214//usage: "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
215//usage: " [-t TOS] [-w WAIT_SEC]" 215//usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n"
216//usage: IF_FEATURE_TRACEROUTE_SOURCE_ROUTE(" [-g GATEWAY]")" [-s SRC_IP] [-i IFACE]\n"
217//usage: " [-z PAUSE_MSEC] HOST [BYTES]" 216//usage: " [-z PAUSE_MSEC] HOST [BYTES]"
218//usage:#define traceroute_full_usage "\n\n" 217//usage:#define traceroute_full_usage "\n\n"
219//usage: "Trace the route to HOST\n" 218//usage: "Trace the route to HOST\n"
@@ -294,7 +293,6 @@
294 293
295#define OPT_STRING \ 294#define OPT_STRING \
296 "FIlnrdvxt:i:m:p:q:s:w:z:f:" \ 295 "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
297 IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:*") \
298 "4" IF_TRACEROUTE6("6") 296 "4" IF_TRACEROUTE6("6")
299enum { 297enum {
300 OPT_DONT_FRAGMNT = (1 << 0), /* F */ 298 OPT_DONT_FRAGMNT = (1 << 0), /* F */
@@ -314,9 +312,8 @@ enum {
314 OPT_WAITTIME = (1 << 14), /* w */ 312 OPT_WAITTIME = (1 << 14), /* w */
315 OPT_PAUSE_MS = (1 << 15), /* z */ 313 OPT_PAUSE_MS = (1 << 15), /* z */
316 OPT_FIRST_TTL = (1 << 16), /* f */ 314 OPT_FIRST_TTL = (1 << 16), /* f */
317 OPT_SOURCE_ROUTE = (1 << 17) * ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE, /* g */ 315 OPT_IPV4 = (1 << 17), /* 4 */
318 OPT_IPV4 = (1 << (17+ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE)), /* 4 */ 316 OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */
319 OPT_IPV6 = (1 << (18+ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE)) * ENABLE_TRACEROUTE6, /* 6 */
320}; 317};
321#define verbose (option_mask32 & OPT_VERBOSE) 318#define verbose (option_mask32 & OPT_VERBOSE)
322 319
@@ -343,26 +340,18 @@ struct outdata6_t {
343#endif 340#endif
344 341
345struct globals { 342struct globals {
343 /* Pointer to entire malloced IP packet, "packlen" bytes long: */
346 struct ip *outip; 344 struct ip *outip;
345 /* Pointer to ICMP or UDP payload (not header): */
347 struct outdata_t *outdata; 346 struct outdata_t *outdata;
347
348 len_and_sockaddr *dest_lsa; 348 len_and_sockaddr *dest_lsa;
349 int packlen; /* total length of packet */ 349 int packlen; /* total length of packet */
350 int pmtu; /* Path MTU Discovery (RFC1191) */ 350 int pmtu; /* Path MTU Discovery (RFC1191) */
351 uint32_t ident; 351 uint32_t ident;
352 uint16_t port; // 32768 + 666; /* start udp dest port # for probe packets */ 352 uint16_t port; // 33434; /* start udp dest port # for probe packets */
353 int waittime; // 5; /* time to wait for response (in seconds) */ 353 int waittime; // 5; /* time to wait for response (in seconds) */
354#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
355 int optlen; /* length of ip options */
356#else
357#define optlen 0
358#endif
359 unsigned char recv_pkt[512]; /* last inbound (icmp) packet */ 354 unsigned char recv_pkt[512]; /* last inbound (icmp) packet */
360#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
361 /* Maximum number of gateways (include room for one noop) */
362#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(uint32_t)))
363 /* loose source route gateway list (including room for final destination) */
364 uint32_t gwlist[NGATEWAYS + 1];
365#endif
366}; 355};
367 356
368#define G (*ptr_to_globals) 357#define G (*ptr_to_globals)
@@ -374,14 +363,11 @@ struct globals {
374#define ident (G.ident ) 363#define ident (G.ident )
375#define port (G.port ) 364#define port (G.port )
376#define waittime (G.waittime ) 365#define waittime (G.waittime )
377#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
378# define optlen (G.optlen )
379#endif
380#define recv_pkt (G.recv_pkt ) 366#define recv_pkt (G.recv_pkt )
381#define gwlist (G.gwlist ) 367#define gwlist (G.gwlist )
382#define INIT_G() do { \ 368#define INIT_G() do { \
383 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 369 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
384 port = 32768 + 666; \ 370 port = 33434; \
385 waittime = 5; \ 371 waittime = 5; \
386} while (0) 372} while (0)
387 373
@@ -421,7 +407,7 @@ send_probe(int seq, int ttl)
421 /* Payload */ 407 /* Payload */
422#if ENABLE_TRACEROUTE6 408#if ENABLE_TRACEROUTE6
423 if (dest_lsa->u.sa.sa_family == AF_INET6) { 409 if (dest_lsa->u.sa.sa_family == AF_INET6) {
424 struct outdata6_t *pkt = (struct outdata6_t *) outip; 410 struct outdata6_t *pkt = (struct outdata6_t *) outdata;
425 pkt->ident6 = htonl(ident); 411 pkt->ident6 = htonl(ident);
426 pkt->seq6 = htonl(seq); 412 pkt->seq6 = htonl(seq);
427 /*gettimeofday(&pkt->tv, &tz);*/ 413 /*gettimeofday(&pkt->tv, &tz);*/
@@ -438,8 +424,10 @@ send_probe(int seq, int ttl)
438 424
439 /* Always calculate checksum for icmp packets */ 425 /* Always calculate checksum for icmp packets */
440 outicmp->icmp_cksum = 0; 426 outicmp->icmp_cksum = 0;
441 outicmp->icmp_cksum = inet_cksum((uint16_t *)outicmp, 427 outicmp->icmp_cksum = inet_cksum(
442 packlen - (sizeof(*outip) + optlen)); 428 (uint16_t *)outicmp,
429 ((char*)outip + packlen) - (char*)outicmp
430 );
443 if (outicmp->icmp_cksum == 0) 431 if (outicmp->icmp_cksum == 0)
444 outicmp->icmp_cksum = 0xffff; 432 outicmp->icmp_cksum = 0xffff;
445 } 433 }
@@ -471,13 +459,12 @@ send_probe(int seq, int ttl)
471 } 459 }
472#endif 460#endif
473 461
462 out = outdata;
474#if ENABLE_TRACEROUTE6 463#if ENABLE_TRACEROUTE6
475 if (dest_lsa->u.sa.sa_family == AF_INET6) { 464 if (dest_lsa->u.sa.sa_family == AF_INET6) {
476 res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); 465 res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl);
477 if (res != 0) 466 if (res != 0)
478 bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl); 467 bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl);
479 out = outip;
480 len = packlen;
481 } else 468 } else
482#endif 469#endif
483 { 470 {
@@ -486,15 +473,14 @@ send_probe(int seq, int ttl)
486 if (res != 0) 473 if (res != 0)
487 bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); 474 bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl);
488#endif 475#endif
489 out = outicmp; 476 if (option_mask32 & OPT_USE_ICMP)
490 len = packlen - sizeof(*outip); 477 out = outicmp;
491 if (!(option_mask32 & OPT_USE_ICMP)) {
492 out = outdata;
493 len -= sizeof(*outudp);
494 set_nport(&dest_lsa->u.sa, htons(port + seq));
495 }
496 } 478 }
497 479
480 if (!(option_mask32 & OPT_USE_ICMP)) {
481 set_nport(&dest_lsa->u.sa, htons(port + seq));
482 }
483 len = ((char*)outip + packlen) - (char*)out;
498 res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len); 484 res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len);
499 if (res != len) 485 if (res != len)
500 bb_error_msg("sent %d octets, ret=%d", len, res); 486 bb_error_msg("sent %d octets, ret=%d", len, res);
@@ -801,10 +787,6 @@ common_traceroute_main(int op, char **argv)
801 char *pausemsecs_str; 787 char *pausemsecs_str;
802 char *first_ttl_str; 788 char *first_ttl_str;
803 char *dest_str; 789 char *dest_str;
804#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
805 llist_t *source_route_list = NULL;
806 int lsrr = 0;
807#endif
808#if ENABLE_TRACEROUTE6 790#if ENABLE_TRACEROUTE6
809 sa_family_t af; 791 sa_family_t af;
810#else 792#else
@@ -823,9 +805,6 @@ common_traceroute_main(int op, char **argv)
823 op |= getopt32(argv, OPT_STRING 805 op |= getopt32(argv, OPT_STRING
824 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str 806 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str
825 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str 807 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str
826#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
827 , &source_route_list
828#endif
829 ); 808 );
830 argv += optind; 809 argv += optind;
831 810
@@ -858,26 +837,14 @@ common_traceroute_main(int op, char **argv)
858 if (op & OPT_FIRST_TTL) 837 if (op & OPT_FIRST_TTL)
859 first_ttl = xatou_range(first_ttl_str, 1, max_ttl); 838 first_ttl = xatou_range(first_ttl_str, 1, max_ttl);
860 839
861#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
862 if (source_route_list) {
863 while (source_route_list) {
864 len_and_sockaddr *lsa;
865
866 if (lsrr >= NGATEWAYS)
867 bb_error_msg_and_die("no more than %d gateways", NGATEWAYS);
868 lsa = xhost_and_af2sockaddr(llist_pop(&source_route_list), 0, AF_INET);
869 gwlist[lsrr] = lsa->u.sin.sin_addr.s_addr;
870 free(lsa);
871 ++lsrr;
872 }
873 optlen = (lsrr + 1) * sizeof(gwlist[0]);
874 }
875#endif
876
877 /* Process destination and optional packet size */ 840 /* Process destination and optional packet size */
878 minpacket = sizeof(*outip) + SIZEOF_ICMP_HDR + sizeof(*outdata) + optlen; 841 minpacket = sizeof(struct ip)
842 + SIZEOF_ICMP_HDR
843 + sizeof(struct outdata_t);
879 if (!(op & OPT_USE_ICMP)) 844 if (!(op & OPT_USE_ICMP))
880 minpacket += sizeof(*outudp) - SIZEOF_ICMP_HDR; 845 minpacket = sizeof(struct ip)
846 + sizeof(struct udphdr)
847 + sizeof(struct outdata_t);
881#if ENABLE_TRACEROUTE6 848#if ENABLE_TRACEROUTE6
882 af = AF_UNSPEC; 849 af = AF_UNSPEC;
883 if (op & OPT_IPV4) 850 if (op & OPT_IPV4)
@@ -887,7 +854,9 @@ common_traceroute_main(int op, char **argv)
887 dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); 854 dest_lsa = xhost_and_af2sockaddr(argv[0], port, af);
888 af = dest_lsa->u.sa.sa_family; 855 af = dest_lsa->u.sa.sa_family;
889 if (af == AF_INET6) 856 if (af == AF_INET6)
890 minpacket = sizeof(struct outdata6_t); 857 minpacket = sizeof(struct ip6_hdr)
858 + sizeof(struct udphdr)
859 + sizeof(struct outdata6_t);
891#else 860#else
892 dest_lsa = xhost2sockaddr(argv[0], port); 861 dest_lsa = xhost2sockaddr(argv[0], port);
893#endif 862#endif
@@ -932,31 +901,6 @@ common_traceroute_main(int op, char **argv)
932 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock); 901 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock);
933 else 902 else
934 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); 903 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock);
935#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE && defined IP_OPTIONS
936 if (lsrr > 0) {
937 unsigned char optlist[MAX_IPOPTLEN];
938 unsigned size;
939
940 /* final hop */
941 gwlist[lsrr] = dest_lsa->u.sin.sin_addr.s_addr;
942 ++lsrr;
943
944 /* force 4 byte alignment */
945 optlist[0] = IPOPT_NOP;
946 /* loose source route option */
947 optlist[1] = IPOPT_LSRR;
948 size = lsrr * sizeof(gwlist[0]);
949 optlist[2] = size + 3;
950 /* pointer to LSRR addresses */
951 optlist[3] = IPOPT_MINOFF;
952 memcpy(optlist + 4, gwlist, size);
953
954 if (setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
955 (char *)optlist, size + sizeof(gwlist[0])) < 0) {
956 bb_perror_msg_and_die("IP_OPTIONS");
957 }
958 }
959#endif
960 } 904 }
961 905
962#ifdef SO_SNDBUF 906#ifdef SO_SNDBUF
@@ -984,7 +928,7 @@ common_traceroute_main(int op, char **argv)
984 928
985 ident = getpid(); 929 ident = getpid();
986 930
987 if (af == AF_INET) { 931 if (!ENABLE_TRACEROUTE6 || af == AF_INET) {
988 if (op & OPT_USE_ICMP) { 932 if (op & OPT_USE_ICMP) {
989 ident |= 0x8000; 933 ident |= 0x8000;
990 outicmp->icmp_type = ICMP_ECHO; 934 outicmp->icmp_type = ICMP_ECHO;
@@ -994,6 +938,14 @@ common_traceroute_main(int op, char **argv)
994 outdata = (struct outdata_t *)(outudp + 1); 938 outdata = (struct outdata_t *)(outudp + 1);
995 } 939 }
996 } 940 }
941#if ENABLE_TRACEROUTE6
942 if (af == AF_INET6) {
943 outdata = (void*)((char*)outip
944 + sizeof(struct ip6_hdr)
945 + sizeof(struct udphdr)
946 );
947 }
948#endif
997 949
998 if (op & OPT_DEVICE) /* hmm, do we need error check? */ 950 if (op & OPT_DEVICE) /* hmm, do we need error check? */
999 setsockopt_bindtodevice(sndsock, device); 951 setsockopt_bindtodevice(sndsock, device);