Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/networking/traceroute.c
- Timestamp:
- Nov 4, 2007, 3:16:40 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.5/mindi-busybox/networking/traceroute.c
r902 r1765 197 197 */ 198 198 199 #undef CONFIG_FEATURE_TRACEROUTE_VERBOSE 199 #define TRACEROUTE_SO_DEBUG 0 200 201 /* TODO: undefs were uncommented - ??! we have config system for that! */ 202 /* probably ok to remove altogether */ 203 //#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE 200 204 //#define CONFIG_FEATURE_TRACEROUTE_VERBOSE 201 #undef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG /* not in documentation man */ 202 #undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 205 //#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 203 206 //#define CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 204 #undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP207 //#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP 205 208 //#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP 206 209 207 #include <errno.h>208 #include <stdio.h>209 #include <stdlib.h>210 #include <string.h>211 #include <unistd.h>212 #include <fcntl.h>213 #include <netdb.h>214 #include <endian.h>215 #include <getopt.h>216 217 #include <sys/param.h>218 #include <sys/file.h>219 #include <sys/ioctl.h>220 #include <sys/socket.h>221 #include <sys/select.h>222 #include "inet_common.h"223 210 224 211 #include <net/if.h> 212 #include <arpa/inet.h> 225 213 #include <netinet/in.h> 226 #include <arpa/inet.h>227 214 #include <netinet/udp.h> 228 215 #include <netinet/ip.h> 229 216 #include <netinet/ip_icmp.h> 230 217 231 #include "busybox.h" 218 #include "libbb.h" 219 #include "inet_common.h" 232 220 233 221 … … 236 224 * Per RFC 791, September 1981. 237 225 */ 238 #define IPVERSION 4 226 #define IPVERSION 4 227 228 #ifndef IPPROTO_ICMP 229 /* Grrrr.... */ 230 #define IPPROTO_ICMP 1 231 #endif 232 #ifndef IPPROTO_IP 233 #define IPPROTO_IP 0 234 #endif 239 235 240 236 /* … … 252 248 * UDP kernel structures and variables. 253 249 */ 254 struct 250 struct udpiphdr { 255 251 struct ipovly ui_i; /* overlaid ip structure */ 256 252 struct udphdr ui_u; /* udp header */ … … 273 269 char *name; 274 270 int n; 275 u _int32_t *addrs;271 uint32_t *addrs; 276 272 }; 277 273 … … 280 276 unsigned char seq; /* sequence number of this packet */ 281 277 unsigned char ttl; /* ttl packet left with */ 282 struct timeval tv ATTRIBUTE_PACKED; /* time packet left */ 278 // UNUSED. Retaining to have the same packet size. 279 struct timeval tv_UNUSED ATTRIBUTE_PACKED; /* time packet left */ 283 280 }; 284 281 285 282 struct IFADDRLIST { 286 u _int32_t addr;283 uint32_t addr; 287 284 char device[sizeof(struct ifreq)]; 288 285 }; 289 286 290 291 static const char route[] = "/proc/net/route";292 293 /* last inbound (icmp) packet */294 static unsigned char packet[512] ATTRIBUTE_ALIGNED(32);295 287 296 288 static struct ip *outip; /* last output (udp) packet */ … … 298 290 static struct outdata *outdata; /* last output (udp) packet */ 299 291 300 #if def CONFIG_FEATURE_TRACEROUTE_USE_ICMP292 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 301 293 static struct icmp *outicmp; /* last output (icmp) packet */ 302 #endif303 304 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE305 /* Maximum number of gateways (include room for one noop) */306 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))307 /* loose source route gateway list (including room for final destination) */308 static u_int32_t gwlist[NGATEWAYS + 1];309 294 #endif 310 295 … … 312 297 static int sndsock; /* send (udp/icmp) socket file descriptor */ 313 298 314 static struct sockaddr_storage whereto; /* Who to try to reach */315 static struct sockaddr_storage wherefrom; /* Who we are */316 299 static int packlen; /* total length of packet */ 317 300 static int minpacket; /* min ip packet size */ … … 321 304 static char *hostname; 322 305 323 static u _short ident;324 static u _short port = 32768 + 666; /* start udp dest port # for probe packets */306 static uint16_t ident; 307 static uint16_t port = 32768 + 666; /* start udp dest port # for probe packets */ 325 308 326 309 static int waittime = 5; /* time to wait for response (in seconds) */ 327 static int nflag; /* print addresses numerically */328 310 static int doipcksum = 1; /* calculate ip checksums by default */ 329 311 330 #if def CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE312 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 331 313 static int optlen; /* length of ip options */ 332 314 #else … … 334 316 #endif 335 317 336 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP 337 static int useicmp; /* use icmp echo instead of udp packets */ 338 #endif 339 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE 340 static int verbose; 341 #endif 318 319 /* Keep in sync with getopt32 call! */ 320 #define OPT_DONT_FRAGMNT (1<<0) /* F */ 321 #define OPT_USE_ICMP (1<<1) /* I */ 322 #define OPT_TTL_FLAG (1<<2) /* l */ 323 #define OPT_ADDR_NUM (1<<3) /* n */ 324 #define OPT_BYPASS_ROUTE (1<<4) /* r */ 325 #define OPT_DEBUG (1<<5) /* d */ 326 #define OPT_VERBOSE (1<<6) /* v */ 327 #define OPT_IP_CHKSUM (1<<7) /* x */ 328 #define OPT_TOS (1<<8) /* t */ 329 #define OPT_DEVICE (1<<9) /* i */ 330 #define OPT_MAX_TTL (1<<10) /* m */ 331 #define OPT_PORT (1<<11) /* p */ 332 #define OPT_NPROBES (1<<12) /* q */ 333 #define OPT_SOURCE (1<<13) /* s */ 334 #define OPT_WAITTIME (1<<14) /* w */ 335 #define OPT_PAUSE_MS (1<<15) /* z */ 336 #define OPT_FIRST_TTL (1<<16) /* f */ 337 338 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 339 /* use icmp echo instead of udp packets */ 340 #define useicmp (option_mask32 & OPT_USE_ICMP) 341 #endif 342 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE 343 #define verbose (option_mask32 & OPT_VERBOSE) 344 #endif 345 #define nflag (option_mask32 & OPT_ADDR_NUM) 346 347 348 struct globals { 349 /* last inbound (icmp) packet */ 350 unsigned char packet[512]; 351 struct sockaddr_storage whereto; /* Who to try to reach */ 352 struct sockaddr_storage wherefrom; /* Who we are */ 353 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 354 /* Maximum number of gateways (include room for one noop) */ 355 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(uint32_t))) 356 /* loose source route gateway list (including room for final destination) */ 357 uint32_t gwlist[NGATEWAYS + 1]; 358 #endif 359 }; 360 361 #define G (*ptr_to_globals) 362 363 #define packet (G.packet ) 364 #define whereto (G.whereto ) 365 #define wherefrom (G.wherefrom) 366 #define gwlist (G.gwlist ) 367 342 368 343 369 /* … … 347 373 ifaddrlist(struct IFADDRLIST **ipaddrp) 348 374 { 375 enum { IFREQ_BUFSIZE = (32 * 1024) / sizeof(struct ifreq) }; 376 349 377 int fd, nipaddr; 350 378 #ifdef HAVE_SOCKADDR_SA_LEN … … 355 383 struct IFADDRLIST *al; 356 384 struct ifconf ifc; 357 struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr; 385 struct ifreq ifr; 386 /* Was on stack, but 32k is a bit too much: */ 387 struct ifreq *ibuf = xmalloc(IFREQ_BUFSIZE * sizeof(ibuf[0])); 358 388 struct IFADDRLIST *st_ifaddrlist; 359 389 360 fd = bb_xsocket(AF_INET, SOCK_DGRAM, 0);361 362 ifc.ifc_len = sizeof(ibuf);390 fd = xsocket(AF_INET, SOCK_DGRAM, 0); 391 392 ifc.ifc_len = IFREQ_BUFSIZE * sizeof(ibuf[0]); 363 393 ifc.ifc_buf = (caddr_t)ibuf; 364 394 365 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || 366 ifc.ifc_len < sizeof(struct ifreq)) { 395 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 396 || ifc.ifc_len < sizeof(struct ifreq) 397 ) { 367 398 if (errno == EINVAL) 368 399 bb_error_msg_and_die( 369 "SIOCGIFCONF: ifreq struct too small (%d bytes)", 370 (int)sizeof(ibuf)); 371 else 372 bb_perror_msg_and_die("SIOCGIFCONF"); 400 "SIOCGIFCONF: ifreq struct too small (%u bytes)", 401 (unsigned)(IFREQ_BUFSIZE * sizeof(ibuf[0]))); 402 bb_perror_msg_and_die("SIOCGIFCONF"); 373 403 } 374 404 ifrp = ibuf; … … 376 406 377 407 nipaddr = 1 + (ifc.ifc_len / sizeof(struct ifreq)); 378 st_ifaddrlist = x calloc(nipaddr,sizeof(struct IFADDRLIST));408 st_ifaddrlist = xzalloc(nipaddr * sizeof(struct IFADDRLIST)); 379 409 al = st_ifaddrlist; 380 410 nipaddr = 0; … … 416 446 continue; 417 447 #endif 418 i f (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0)419 bb_perror_msg_and_die("SIOCGIFADDR: %s", al->device);448 ioctl_or_perror_and_die(fd, SIOCGIFADDR, (char *)&ifr, 449 "SIOCGIFADDR: %s", al->device); 420 450 421 451 addr_sin = (struct sockaddr_in *)&ifr.ifr_addr; … … 424 454 ++nipaddr; 425 455 } 426 if(nipaddr == 0) 427 bb_error_msg_and_die ("Can't find any network interfaces"); 428 (void)close(fd); 429 456 if (nipaddr == 0) 457 bb_error_msg_and_die("can't find any network interfaces"); 458 459 free(ibuf); 460 close(fd); 430 461 *ipaddrp = st_ifaddrlist; 431 462 return nipaddr; … … 434 465 435 466 static void 436 setsin(struct sockaddr_in *addr_sin, u _int32_t addr)467 setsin(struct sockaddr_in *addr_sin, uint32_t addr) 437 468 { 438 469 memset(addr_sin, 0, sizeof(*addr_sin)); … … 453 484 int i, n; 454 485 FILE *f; 455 u _int32_t mask;456 u _int32_t dest, tmask;486 uint32_t mask; 487 uint32_t dest, tmask; 457 488 struct IFADDRLIST *al; 458 489 char buf[256], tdevice[256], device[256]; 459 490 460 f = bb_xfopen(route, "r");491 f = xfopen("/proc/net/route", "r"); 461 492 462 493 /* Find the appropriate interface */ … … 468 499 if (n == 1 && strncmp(buf, "Iface", 5) == 0) 469 500 continue; 470 if ((i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x", 471 tdevice, &dest, &tmask)) != 3) 472 bb_error_msg_and_die ("junk in buffer"); 473 if ((to->sin_addr.s_addr & tmask) == dest && 474 (tmask > mask || mask == 0)) { 501 i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x", 502 tdevice, &dest, &tmask); 503 if (i != 3) 504 bb_error_msg_and_die("junk in buffer"); 505 if ((to->sin_addr.s_addr & tmask) == dest 506 && (tmask > mask || mask == 0) 507 ) { 475 508 mask = tmask; 476 509 strcpy(device, tdevice); … … 480 513 481 514 if (device[0] == '\0') 482 bb_error_msg_and_die ("Can't find interface");515 bb_error_msg_and_die("can't find interface"); 483 516 484 517 /* Get the interface address list */ … … 490 523 break; 491 524 if (i <= 0) 492 bb_error_msg_and_die(" Can't find interface %s", device);525 bb_error_msg_and_die("can't find interface %s", device); 493 526 494 527 setsin(from, al->addr); … … 502 535 */ 503 536 504 /* String to value with optional min and max. Handles decimal and hex. */505 537 static int 506 str2val(const char *str, const char *what, int mi, int ma) 507 { 508 const char *cp; 509 int val; 510 char *ep; 511 512 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { 513 cp = str + 2; 514 val = (int)strtol(cp, &ep, 16); 515 } else 516 val = (int)strtol(str, &ep, 10); 517 if (*ep != '\0') { 518 bb_error_msg_and_die("\"%s\" bad value for %s \n", str, what); 519 } 520 if (val < mi && mi >= 0) { 521 if (mi == 0) 522 bb_error_msg_and_die("%s must be >= %d\n", what, mi); 523 else 524 bb_error_msg_and_die("%s must be > %d\n", what, mi - 1); 525 } 526 if (val > ma && ma >= 0) 527 bb_error_msg_and_die("%s must be <= %d\n", what, ma); 528 return val; 529 } 530 531 532 /* 533 * Subtract 2 timeval structs: out = out - in. 534 * Out is assumed to be >= in. 535 */ 536 static inline void 537 tvsub(struct timeval *out, struct timeval *in) 538 { 539 540 if ((out->tv_usec -= in->tv_usec) < 0) { 541 --out->tv_sec; 542 out->tv_usec += 1000000; 543 } 544 out->tv_sec -= in->tv_sec; 545 } 546 547 static int 548 wait_for_reply(int sock, struct sockaddr_in *fromp, const struct timeval *tp) 538 wait_for_reply(int sock, struct sockaddr_in *fromp) 549 539 { 550 540 fd_set fds; 551 struct timeval now, wait; 552 struct timezone tz; 541 struct timeval tvwait; 553 542 int cc = 0; 554 543 socklen_t fromlen = sizeof(*fromp); … … 557 546 FD_SET(sock, &fds); 558 547 559 wait.tv_sec = tp->tv_sec + waittime; 560 wait.tv_usec = tp->tv_usec; 561 (void)gettimeofday(&now, &tz); 562 tvsub(&wait, &now); 563 564 if (select(sock + 1, &fds, NULL, NULL, &wait) > 0) 548 tvwait.tv_sec = waittime; 549 tvwait.tv_usec = 0; 550 551 if (select(sock + 1, &fds, NULL, NULL, &tvwait) > 0) 565 552 cc = recvfrom(sock, (char *)packet, sizeof(packet), 0, 566 553 (struct sockaddr *)fromp, &fromlen); … … 572 559 * Checksum routine for Internet Protocol family headers (C Version) 573 560 */ 574 static u _short575 in_cksum(u _short *addr, int len)561 static uint16_t 562 in_cksum(uint16_t *addr, int len) 576 563 { 577 564 int nleft = len; 578 u _short *w = addr;579 u _short answer;565 uint16_t *w = addr; 566 uint16_t answer; 580 567 int sum = 0; 581 568 … … 606 593 607 594 static void 608 send_probe(int seq, int ttl , struct timeval *tp)595 send_probe(int seq, int ttl) 609 596 { 610 597 int cc; … … 622 609 if (doipcksum) { 623 610 outip->ip_sum = 624 in_cksum((u _short *)outip, sizeof(*outip) + optlen);611 in_cksum((uint16_t *)outip, sizeof(*outip) + optlen); 625 612 if (outip->ip_sum == 0) 626 613 outip->ip_sum = 0xffff; … … 630 617 outdata->seq = seq; 631 618 outdata->ttl = ttl; 632 memcpy(&outdata->tv, tp, sizeof(outdata->tv)); 633 634 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP 619 // UNUSED: was storing gettimeofday's result there, but never ever checked it 620 /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ 621 622 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 635 623 if (useicmp) 636 624 outicmp->icmp_seq = htons(seq); … … 639 627 outudp->dest = htons(port + seq); 640 628 641 #if def CONFIG_FEATURE_TRACEROUTE_USE_ICMP629 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 642 630 if (useicmp) { 643 631 /* Always calculate checksum for icmp packets */ 644 632 outicmp->icmp_cksum = 0; 645 outicmp->icmp_cksum = in_cksum((u _short *)outicmp,633 outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp, 646 634 packlen - (sizeof(*outip) + optlen)); 647 635 if (outicmp->icmp_cksum == 0) … … 649 637 } else 650 638 #endif 651 639 if (doipcksum) { 652 640 /* Checksum (we must save and restore ip header) */ 653 641 tip = *outip; … … 661 649 ui->ui_len = outudp->len; 662 650 outudp->check = 0; 663 outudp->check = in_cksum((u _short *)ui, packlen);651 outudp->check = in_cksum((uint16_t *)ui, packlen); 664 652 if (outudp->check == 0) 665 653 outudp->check = 0xffff; … … 667 655 } 668 656 669 #if def CONFIG_FEATURE_TRACEROUTE_VERBOSE657 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE 670 658 /* XXX undocumented debugging hack */ 671 659 if (verbose > 1) { 672 const u _short *sp;660 const uint16_t *sp; 673 661 int nshorts, i; 674 662 675 sp = (u _short *)outip;676 nshorts = (u _int)packlen / sizeof(u_short);663 sp = (uint16_t *)outip; 664 nshorts = (unsigned)packlen / sizeof(uint16_t); 677 665 i = 0; 678 666 printf("[ %d bytes", packlen); … … 699 687 #endif 700 688 701 cc = sendto(sndsock, (char *)outip, 702 packlen, 0, (struct sockaddr *)&whereto, sizeof(whereto)); 703 if (cc < 0 || cc != packlen) { 704 if (cc < 0) 705 bb_perror_msg_and_die("sendto"); 706 printf("%s: wrote %s %d chars, ret=%d\n", 707 bb_applet_name, hostname, packlen, cc); 708 (void)fflush(stdout); 709 } 710 } 711 712 static inline double 713 deltaT(struct timeval *t1p, struct timeval *t2p) 714 { 715 double dt; 716 717 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 718 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 719 return dt; 720 } 721 722 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE 689 cc = xsendto(sndsock, (char *)outip, 690 packlen, (struct sockaddr *)&whereto, sizeof(whereto)); 691 if (cc != packlen) { 692 bb_info_msg("wrote %s %d chars, ret=%d", hostname, packlen, cc); 693 } 694 } 695 696 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE 723 697 /* 724 698 * Convert an ICMP "type" field to a printable string. … … 727 701 pr_type(unsigned char t) 728 702 { 729 static const char * 703 static const char *const ttab[] = { 730 704 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", 731 705 "Source Quench", "Redirect", "ICMP 6", "ICMP 7", … … 753 727 hlen = ip->ip_hl << 2; 754 728 if (cc < hlen + ICMP_MINLEN) { 755 #if def CONFIG_FEATURE_TRACEROUTE_VERBOSE729 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE 756 730 if (verbose) 757 731 printf("packet too short (%d bytes) from %s\n", cc, … … 777 751 hip = &icp->icmp_ip; 778 752 hlen = hip->ip_hl << 2; 779 #if def CONFIG_FEATURE_TRACEROUTE_USE_ICMP753 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 780 754 if (useicmp) { 781 755 struct icmp *hicmp; … … 796 770 } else 797 771 #endif 798 772 { 799 773 up = (struct udphdr *)((unsigned char *)hip + hlen); 800 774 /* XXX 8 is a magic number */ … … 806 780 } 807 781 } 808 #if def CONFIG_FEATURE_TRACEROUTE_VERBOSE782 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE 809 783 if (verbose) { 810 784 int i; 811 u _int32_t *lp = (u_int32_t *)&icp->icmp_ip;785 uint32_t *lp = (uint32_t *)&icp->icmp_ip; 812 786 813 787 printf("\n%d bytes from %s to " … … 815 789 cc, inet_ntoa(from->sin_addr), 816 790 inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); 817 for (i = 4; i < cc 791 for (i = 4; i < cc; i += sizeof(*lp)) 818 792 printf("%2d: x%8.8x\n", i, *lp++); 819 793 } … … 829 803 */ 830 804 static inline void 831 inetname(struct sockaddr_in *from) 832 { 833 const char *n = NULL; 805 print_inetname(struct sockaddr_in *from) 806 { 834 807 const char *ina; 835 char name[257]; 836 837 if (!nflag && from->sin_addr.s_addr != INADDR_ANY) { 838 if(INET_rresolve(name, sizeof(name), from, 0x4000, 0xffffffff) >= 0) 839 n = name; 840 } 808 841 809 ina = inet_ntoa(from->sin_addr); 842 810 if (nflag) 843 811 printf(" %s", ina); 844 else 812 else { 813 char *n = NULL; 814 if (from->sin_addr.s_addr != INADDR_ANY) 815 n = xmalloc_sockaddr2host_noport((struct sockaddr*)from); 845 816 printf(" %s (%s)", (n ? n : ina), ina); 817 free(n); 818 } 846 819 } 847 820 … … 856 829 cc -= hlen; 857 830 858 inetname(from);859 #if def CONFIG_FEATURE_TRACEROUTE_VERBOSE831 print_inetname(from); 832 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE 860 833 if (verbose) 861 printf(" %d bytes to %s", cc, inet_ntoa 834 printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst)); 862 835 #endif 863 836 } … … 871 844 struct hostinfo *hi; 872 845 char **p; 873 u _int32_t addr, *ap;874 875 hi = x calloc(1,sizeof(*hi));846 uint32_t addr, *ap; 847 848 hi = xzalloc(sizeof(*hi)); 876 849 addr = inet_addr(host); 877 if ( (int32_t)addr != -1) {878 hi->name = bb_xstrdup(host);850 if (addr != 0xffffffff) { 851 hi->name = xstrdup(host); 879 852 hi->n = 1; 880 hi->addrs = x calloc(1,sizeof(hi->addrs[0]));853 hi->addrs = xzalloc(sizeof(hi->addrs[0])); 881 854 hi->addrs[0] = addr; 882 855 return hi; … … 886 859 if (hp->h_addrtype != AF_INET || hp->h_length != 4) 887 860 bb_perror_msg_and_die("bad host %s", host); 888 hi->name = bb_xstrdup(hp->h_name);861 hi->name = xstrdup(hp->h_name); 889 862 for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p) 890 863 continue; 891 864 hi->n = n; 892 hi->addrs = x calloc(n,sizeof(hi->addrs[0]));865 hi->addrs = xzalloc(n * sizeof(hi->addrs[0])); 893 866 for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p) 894 867 memcpy(ap, *p, sizeof(*ap)); … … 900 873 { 901 874 free(hi->name); 902 hi->name = NULL; 903 free((char *)hi->addrs); 904 free((char *)hi); 905 } 906 907 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 875 free(hi->addrs); 876 free(hi); 877 } 878 879 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 908 880 static void 909 getaddr(u _int32_t *ap, const char *host)881 getaddr(uint32_t *ap, const char *host) 910 882 { 911 883 struct hostinfo *hi; … … 917 889 #endif 918 890 919 920 int 921 traceroute_main(int argc, char *argv[]) 891 static void 892 print_delta_ms(unsigned t1p, unsigned t2p) 893 { 894 unsigned tt = t2p - t1p; 895 printf(" %u.%03u ms", tt/1000, tt%1000); 896 } 897 898 int traceroute_main(int argc, char **argv); 899 int traceroute_main(int argc, char **argv) 922 900 { 923 901 int code, n; 924 char *cp;925 902 unsigned char *outp; 926 u _int32_t *ap;927 struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;928 struct sockaddr_in *to = (struct sockaddr_in *)&whereto;903 uint32_t *ap; 904 struct sockaddr_in *from; 905 struct sockaddr_in *to; 929 906 struct hostinfo *hi; 930 int on = 1;931 struct protoent *pe;932 907 int ttl, probe, i; 933 908 int seq = 0; 934 909 int tos = 0; 935 char *tos_str = NULL; 936 char *source = NULL; 937 unsigned long op; 938 939 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 910 char *tos_str; 911 char *source; 912 unsigned op; 913 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 940 914 int lsrr = 0; 941 915 #endif 942 u _short off = 0;916 uint16_t off = 0; 943 917 struct IFADDRLIST *al; 944 char *device = NULL;918 char *device; 945 919 int max_ttl = 30; 946 char *max_ttl_str = NULL;947 char *port_str = NULL;920 char *max_ttl_str; 921 char *port_str; 948 922 int nprobes = 3; 949 char *nprobes_str = NULL;950 char *waittime_str = NULL;951 u _intpausemsecs = 0;952 char *pausemsecs_str = NULL;923 char *nprobes_str; 924 char *waittime_str; 925 unsigned pausemsecs = 0; 926 char *pausemsecs_str; 953 927 int first_ttl = 1; 954 char *first_ttl_str = NULL; 955 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 956 llist_t *sourse_route_list = NULL; 957 #endif 958 959 opterr = 0; 960 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 961 bb_opt_complementally = "x-x:g::"; 928 char *first_ttl_str; 929 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 930 llist_t *source_route_list = NULL; 931 #endif 932 933 PTR_TO_GLOBALS = xzalloc(sizeof(G)); 934 from = (struct sockaddr_in *)&wherefrom; 935 to = (struct sockaddr_in *)&whereto; 936 937 //opterr = 0; 938 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 939 opt_complementary = "x-x:g::"; 962 940 #else 963 bb_opt_complementally = "x-x"; 964 #endif 965 966 op = bb_getopt_ulflags(argc, argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:" 967 #define USAGE_OP_DONT_FRAGMNT (1<<0) /* F */ 968 #define USAGE_OP_USE_ICMP (1<<1) /* I */ 969 #define USAGE_OP_TTL_FLAG (1<<2) /* l */ 970 #define USAGE_OP_ADDR_NUM (1<<3) /* n */ 971 #define USAGE_OP_BYPASS_ROUTE (1<<4) /* r */ 972 #define USAGE_OP_DEBUG (1<<5) /* d */ 973 #define USAGE_OP_VERBOSE (1<<6) /* v */ 974 #define USAGE_OP_IP_CHKSUM (1<<7) /* x */ 975 976 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 941 opt_complementary = "x-x"; 942 #endif 943 944 op = getopt32(argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:" 945 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 977 946 "g:" 978 947 #endif 979 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str,980 &source, &waittime_str, &pausemsecs_str, &first_ttl_str981 #if def CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE982 , &sourse_route_list948 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str 949 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str 950 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 951 , &source_route_list 983 952 #endif 984 953 ); 985 954 986 if (op & USAGE_OP_DONT_FRAGMNT)955 if (op & OPT_DONT_FRAGMNT) 987 956 off = IP_DF; 988 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP 989 useicmp = op & USAGE_OP_USE_ICMP; 990 #endif 991 nflag = op & USAGE_OP_ADDR_NUM; 992 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE 993 verbose = op & USAGE_OP_VERBOSE; 994 #endif 995 if(op & USAGE_OP_IP_CHKSUM) { 957 if (op & OPT_IP_CHKSUM) { 996 958 doipcksum = 0; 997 bb_error_msg("Warning: ip checksums disabled"); 998 } 999 if (tos_str) 1000 tos = str2val(tos_str, "tos", 0, 255); 1001 if(max_ttl_str) 1002 max_ttl = str2val(max_ttl_str, "max ttl", 1, 255); 1003 if(port_str) 1004 port = (u_short)str2val(port_str, "port", 1, (1 << 16) - 1); 1005 if(nprobes_str) 1006 nprobes = str2val(nprobes_str, "nprobes", 1, -1); 1007 if(source) { 1008 /* 1009 * set the ip source address of the outbound 1010 * probe (e.g., on a multi-homed host). 1011 */ 1012 if (getuid()) bb_error_msg_and_die("-s %s: Permission denied", source); 1013 } 1014 if(waittime_str) 1015 waittime = str2val(waittime_str, "wait time", 2, 24 * 60 * 60); 1016 if(pausemsecs_str) 1017 pausemsecs = str2val(pausemsecs_str, "pause msecs", 0, 60 * 60 * 1000); 1018 if(first_ttl_str) 1019 first_ttl = str2val(first_ttl_str, "first ttl", 1, 255); 1020 1021 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 1022 if(sourse_route_list) { 959 bb_error_msg("warning: ip checksums disabled"); 960 } 961 if (op & OPT_TOS) 962 tos = xatou_range(tos_str, 0, 255); 963 if (op & OPT_MAX_TTL) 964 max_ttl = xatou_range(max_ttl_str, 1, 255); 965 if (op & OPT_PORT) 966 port = xatou16(port_str); 967 if (op & OPT_NPROBES) 968 nprobes = xatou_range(nprobes_str, 1, INT_MAX); 969 if (op & OPT_SOURCE) { 970 /* 971 * set the ip source address of the outbound 972 * probe (e.g., on a multi-homed host). 973 */ 974 if (getuid()) 975 bb_error_msg_and_die("-s %s: permission denied", source); 976 } 977 if (op & OPT_WAITTIME) 978 waittime = xatou_range(waittime_str, 2, 24 * 60 * 60); 979 if (op & OPT_PAUSE_MS) 980 pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); 981 if (op & OPT_FIRST_TTL) 982 first_ttl = xatou_range(first_ttl_str, 1, 255); 983 984 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 985 if (source_route_list) { 1023 986 llist_t *l_sr; 1024 987 1025 for(l_sr = sourse_route_list; l_sr; ) { 988 l_sr = source_route_list; 989 while (l_sr) { 1026 990 if (lsrr >= NGATEWAYS) 1027 bb_error_msg_and_die(" No more than %d gateways", NGATEWAYS);991 bb_error_msg_and_die("no more than %d gateways", NGATEWAYS); 1028 992 getaddr(gwlist + lsrr, l_sr->data); 1029 993 ++lsrr; 1030 994 l_sr = l_sr->link; 1031 free(sour se_route_list);1032 sour se_route_list = l_sr;995 free(source_route_list); 996 source_route_list = l_sr; 1033 997 } 1034 998 optlen = (lsrr + 1) * sizeof(gwlist[0]); … … 1044 1008 minpacket = sizeof(*outip) + sizeof(*outdata) + optlen; 1045 1009 1046 #if def CONFIG_FEATURE_TRACEROUTE_USE_ICMP1010 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 1047 1011 if (useicmp) 1048 1012 minpacket += 8; /* XXX magic number */ … … 1056 1020 1057 1021 case 2: 1058 packlen = str2val(argv[optind + 1], 1059 "packet length", minpacket, maxpacket); 1022 packlen = xatoul_range(argv[optind + 1], minpacket, maxpacket); 1060 1023 /* Fall through */ 1061 1024 … … 1065 1028 setsin(to, hi->addrs[0]); 1066 1029 if (hi->n > 1) 1067 bb_error_msg( 1068 "Warning: %s has multiple addresses; using %s", 1030 bb_error_msg("warning: %s has multiple addresses; using %s", 1069 1031 hostname, inet_ntoa(to->sin_addr)); 1070 1032 hostname = hi->name; … … 1077 1039 } 1078 1040 1079 cp = "icmp"; 1080 if ((pe = getprotobyname(cp)) == NULL) 1081 bb_perror_msg_and_die("unknown protocol %s", cp); 1082 1083 /* Insure the socket fds won't be 0, 1 or 2 */ 1084 do n = bb_xopen(bb_dev_null, O_RDONLY); while (n < 2); 1085 if (n > 2) 1086 close(n); 1087 1088 s = bb_xsocket(AF_INET, SOCK_RAW, pe->p_proto); 1089 1090 #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG 1091 if (op & USAGE_OP_DEBUG) 1092 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, 1093 sizeof(on)); 1094 #endif 1095 if (op & USAGE_OP_BYPASS_ROUTE) 1096 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, 1097 sizeof(on)); 1098 1099 sndsock = bb_xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW); 1100 1101 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE 1041 /* Ensure the socket fds won't be 0, 1 or 2 */ 1042 bb_sanitize_stdio(); 1043 1044 s = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 1045 1046 #if TRACEROUTE_SO_DEBUG 1047 if (op & OPT_DEBUG) 1048 setsockopt(s, SOL_SOCKET, SO_DEBUG, 1049 &const_int_1, sizeof(const_int_1)); 1050 #endif 1051 if (op & OPT_BYPASS_ROUTE) 1052 setsockopt(s, SOL_SOCKET, SO_DONTROUTE, 1053 &const_int_1, sizeof(const_int_1)); 1054 1055 sndsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW); 1056 1057 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 1102 1058 #if defined(IP_OPTIONS) 1103 1059 if (lsrr > 0) { 1104 1060 unsigned char optlist[MAX_IPOPTLEN]; 1105 1106 cp = "ip";1107 if ((pe = getprotobyname(cp)) == NULL)1108 bb_perror_msg_and_die("unknown protocol");1109 1061 1110 1062 /* final hop */ … … 1122 1074 memcpy(optlist + 4, gwlist, i); 1123 1075 1124 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,1076 if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, 1125 1077 (char *)optlist, i + sizeof(gwlist[0]))) < 0) { 1126 1078 bb_perror_msg_and_die("IP_OPTIONS"); 1127 1079 } 1128 1080 } 1129 1081 #endif /* IP_OPTIONS */ … … 1131 1083 1132 1084 #ifdef SO_SNDBUF 1133 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen, 1134 sizeof(packlen)) < 0) { 1085 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) { 1135 1086 bb_perror_msg_and_die("SO_SNDBUF"); 1136 1087 } 1137 1088 #endif 1138 1089 #ifdef IP_HDRINCL 1139 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, 1140 sizeof(on)) < 0 && errno != ENOPROTOOPT) { 1090 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, &const_int_1, sizeof(const_int_1)) < 0 1091 && errno != ENOPROTOOPT 1092 ) { 1141 1093 bb_perror_msg_and_die("IP_HDRINCL"); 1142 1094 } 1143 1095 #else 1144 1096 #ifdef IP_TOS 1145 if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS, 1146 (char *)&tos, sizeof(tos)) < 0) { 1097 if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) { 1147 1098 bb_perror_msg_and_die("setsockopt tos %d", tos); 1148 1099 } 1149 1100 #endif 1150 1101 #endif 1151 #if def CONFIG_FEATURE_TRACEROUTE_SO_DEBUG1152 if (op & USAGE_OP_DEBUG)1153 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,1154 sizeof(on));1155 #endif 1156 if (op & USAGE_OP_BYPASS_ROUTE)1157 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,1158 sizeof(on));1102 #if TRACEROUTE_SO_DEBUG 1103 if (op & OPT_DEBUG) 1104 setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 1105 &const_int_1, sizeof(const_int_1)); 1106 #endif 1107 if (op & OPT_BYPASS_ROUTE) 1108 setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 1109 &const_int_1, sizeof(const_int_1)); 1159 1110 1160 1111 /* Revert to non-privileged user after opening sockets */ … … 1162 1113 xsetuid(getuid()); 1163 1114 1164 outip = (struct ip *)xcalloc(1, (unsigned)packlen);1115 outip = xzalloc(packlen); 1165 1116 1166 1117 outip->ip_v = IPVERSION; … … 1174 1125 outip->ip_hl = (outp - (unsigned char *)outip) >> 2; 1175 1126 ident = (getpid() & 0xffff) | 0x8000; 1176 #if def CONFIG_FEATURE_TRACEROUTE_USE_ICMP1127 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 1177 1128 if (useicmp) { 1178 1129 outip->ip_p = IPPROTO_ICMP; 1179 1180 1130 outicmp = (struct icmp *)outp; 1181 1131 outicmp->icmp_type = ICMP_ECHO; 1182 1132 outicmp->icmp_id = htons(ident); 1183 1184 1133 outdata = (struct outdata *)(outp + 8); /* XXX magic number */ 1185 1134 } else 1186 1135 #endif 1187 1136 { 1188 1137 outip->ip_p = IPPROTO_UDP; 1189 1190 1138 outudp = (struct udphdr *)outp; 1191 1139 outudp->source = htons(ident); 1192 outudp->len = 1193 htons((u_short)(packlen - (sizeof(*outip) + optlen))); 1140 outudp->len = htons((uint16_t)(packlen - (sizeof(*outip) + optlen))); 1194 1141 outdata = (struct outdata *)(outudp + 1); 1195 1142 } … … 1199 1146 1200 1147 /* Look for a specific device */ 1201 if ( device != NULL) {1148 if (op & OPT_DEVICE) { 1202 1149 for (i = n; i > 0; --i, ++al) 1203 1150 if (strcmp(device, al->device) == 0) 1204 break; 1205 if (i <= 0) { 1206 bb_error_msg_and_die("Can't find interface %s", device); 1207 } 1208 } 1151 goto found_dev; 1152 bb_error_msg_and_die("can't find interface %s", device); 1153 } 1154 found_dev: 1209 1155 1210 1156 /* Determine our source address */ 1211 if ( source == NULL) {1157 if (!(op & OPT_SOURCE)) { 1212 1158 /* 1213 1159 * If a device was specified, use the interface address. 1214 1160 * Otherwise, try to determine our source address. 1215 1161 */ 1216 if ( device != NULL)1162 if (op & OPT_DEVICE) 1217 1163 setsin(from, al->addr); 1218 1164 findsaddr(to, from); … … 1227 1173 * there are more than one). 1228 1174 */ 1229 if ( device != NULL) {1175 if (op & OPT_DEVICE) { 1230 1176 for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) 1231 1177 if (*ap == al->addr) 1232 break; 1233 if (i <= 0) { 1234 bb_error_msg_and_die( 1235 "%s is not on interface %s", 1236 source, device); 1237 } 1178 goto found_dev2; 1179 bb_error_msg_and_die("%s is not on interface %s", 1180 source, device); 1181 found_dev2: 1238 1182 setsin(from, *ap); 1239 1183 } else { … … 1241 1185 if (hi->n > 1) 1242 1186 bb_error_msg( 1243 " Warning: %s has multiple addresses; using %s",1187 "warning: %s has multiple addresses; using %s", 1244 1188 source, inet_ntoa(from->sin_addr)); 1245 1189 } … … 1249 1193 outip->ip_src = from->sin_addr; 1250 1194 #ifndef IP_HDRINCL 1251 bb_xbind(sndsock, (struct sockaddr *)from, sizeof(*from));1252 #endif 1253 1254 fprintf(stderr,"traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr));1255 if ( source)1256 fprintf(stderr," from %s", source);1257 fprintf(stderr,", %d hops max, %d byte packets\n", max_ttl, packlen);1258 (void)fflush(stderr);1195 xbind(sndsock, (struct sockaddr *)from, sizeof(*from)); 1196 #endif 1197 1198 printf("traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr)); 1199 if (op & OPT_SOURCE) 1200 printf(" from %s", source); 1201 printf(", %d hops max, %d byte packets\n", max_ttl, packlen); 1202 fflush(stdout); 1259 1203 1260 1204 for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { 1261 u _int32_t lastaddr = 0;1205 uint32_t lastaddr = 0; 1262 1206 int gotlastaddr = 0; 1263 1207 int got_there = 0; … … 1268 1212 for (probe = 0; probe < nprobes; ++probe) { 1269 1213 int cc; 1270 struct timeval t1, t2;1271 struct timezone tz;1214 unsigned t1; 1215 unsigned t2; 1272 1216 struct ip *ip; 1273 1217 1274 1218 if (sentfirst && pausemsecs > 0) 1275 1219 usleep(pausemsecs * 1000); 1276 (void)gettimeofday(&t1, &tz);1277 send_probe(++seq, ttl , &t1);1220 t1 = monotonic_us(); 1221 send_probe(++seq, ttl); 1278 1222 ++sentfirst; 1279 while ((cc = wait_for_reply(s, from , &t1)) != 0) {1280 (void)gettimeofday(&t2, &tz);1223 while ((cc = wait_for_reply(s, from)) != 0) { 1224 t2 = monotonic_us(); 1281 1225 i = packet_ok(packet, cc, from, seq); 1282 1226 /* Skip short packet */ … … 1289 1233 ++gotlastaddr; 1290 1234 } 1291 print f(" %.3f ms", deltaT(&t1, &t2));1235 print_delta_ms(t1, t2); 1292 1236 ip = (struct ip *)packet; 1293 if (op & USAGE_OP_TTL_FLAG)1237 if (op & OPT_TTL_FLAG) 1294 1238 printf(" (%d)", ip->ip_ttl); 1295 1239 if (i == -2) {
Note:
See TracChangeset
for help on using the changeset viewer.