Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/networking/ping.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/networking/ping.c
r3232 r3621 29 29 #include <netinet/ip_icmp.h> 30 30 #include "libbb.h" 31 #include "common_bufsiz.h" 31 32 32 33 #ifdef __BIONIC__ … … 90 91 //usage:# define ping_full_usage "\n\n" 91 92 //usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" 93 //usage: IF_PING6( 92 94 //usage: "\n -4,-6 Force IP or IPv6 name resolution" 95 //usage: ) 93 96 //usage: "\n -c CNT Send only CNT pings" 94 97 //usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" … … 99 102 //usage: "\n -w SEC Seconds until ping exits (default:infinite)" 100 103 //usage: "\n (can exit earlier with -c CNT)" 101 //usage: "\n -q Quiet, only display soutput at start"104 //usage: "\n -q Quiet, only display output at start" 102 105 //usage: "\n and when finished" 106 //usage: "\n -p Pattern to use for payload" 103 107 //usage: 104 108 //usage:# define ping6_trivial_usage … … 109 113 //usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" 110 114 //usage: "\n -I IFACE/IP Use interface or IP address as source" 111 //usage: "\n -q Quiet, only display soutput at start"115 //usage: "\n -q Quiet, only display output at start" 112 116 //usage: "\n and when finished" 117 //usage: "\n -p Pattern to use for payload" 113 118 //usage: 114 119 //usage:#endif … … 148 153 MAXWAIT = 10, 149 154 PINGINTERVAL = 1, /* 1 second */ 155 pingsock = 0, 150 156 }; 157 158 static void 159 #if ENABLE_PING6 160 create_icmp_socket(len_and_sockaddr *lsa) 161 #else 162 create_icmp_socket(void) 163 #define create_icmp_socket(lsa) create_icmp_socket() 164 #endif 165 { 166 int sock; 167 #if ENABLE_PING6 168 if (lsa->u.sa.sa_family == AF_INET6) 169 sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 170 else 171 #endif 172 sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */ 173 if (sock < 0) { 174 if (errno == EPERM) 175 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); 176 bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); 177 } 178 179 xmove_fd(sock, pingsock); 180 } 151 181 152 182 #if !ENABLE_FEATURE_FANCY_PING … … 158 188 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; 159 189 } FIX_ALIASING; 160 #define G (*(struct globals*) &bb_common_bufsiz1)161 #define INIT_G() do { } while (0)190 #define G (*(struct globals*)bb_common_bufsiz1) 191 #define INIT_G() do { setup_common_bufsiz(); } while (0) 162 192 163 193 static void noresp(int ign UNUSED_PARAM) … … 170 200 { 171 201 struct icmp *pkt; 172 int pingsock, c; 173 174 pingsock = create_icmp_socket(); 202 int c; 175 203 176 204 pkt = (struct icmp *) G.packet; 177 memset(pkt, 0, sizeof(G.packet));205 /*memset(pkt, 0, sizeof(G.packet)); already is */ 178 206 pkt->icmp_type = ICMP_ECHO; 179 207 pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); … … 183 211 /* listen for replies */ 184 212 while (1) { 213 #if 0 185 214 struct sockaddr_in from; 186 215 socklen_t fromlen = sizeof(from); … … 188 217 c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, 189 218 (struct sockaddr *) &from, &fromlen); 219 #else 220 c = recv(pingsock, G.packet, sizeof(G.packet), 0); 221 #endif 190 222 if (c < 0) { 191 223 if (errno != EINTR) … … 209 241 { 210 242 struct icmp6_hdr *pkt; 211 int pingsock,c;243 int c; 212 244 int sockopt; 213 245 214 pingsock = create_icmp6_socket();215 216 246 pkt = (struct icmp6_hdr *) G.packet; 217 memset(pkt, 0, sizeof(G.packet));247 /*memset(pkt, 0, sizeof(G.packet)); already is */ 218 248 pkt->icmp6_type = ICMP6_ECHO_REQUEST; 219 249 220 250 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); 221 setsockopt (pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));251 setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt); 222 252 223 253 xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len); … … 225 255 /* listen for replies */ 226 256 while (1) { 257 #if 0 227 258 struct sockaddr_in6 from; 228 259 socklen_t fromlen = sizeof(from); … … 230 261 c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, 231 262 (struct sockaddr *) &from, &fromlen); 263 #else 264 c = recv(pingsock, G.packet, sizeof(G.packet), 0); 265 #endif 232 266 if (c < 0) { 233 267 if (errno != EINTR) … … 235 269 continue; 236 270 } 237 if (c >= ICMP_MINLEN) { /* icmp6_hdr */ 238 pkt = (struct icmp6_hdr *) G.packet; 271 if (c >= ICMP_MINLEN) { /* icmp6_hdr */ 239 272 if (pkt->icmp6_type == ICMP6_ECHO_REPLY) 240 273 break; … … 284 317 alarm(5); /* give the host 5000ms to respond */ 285 318 319 create_icmp_socket(lsa); 286 320 #if ENABLE_PING6 287 321 if (lsa->u.sa.sa_family == AF_INET6) … … 300 334 /* Full(er) version */ 301 335 302 #define OPT_STRING ("qvc:s:t:w:W:I: 4" IF_PING6("6"))336 #define OPT_STRING ("qvc:s:t:w:W:I:np:4" IF_PING6("6")) 303 337 enum { 304 338 OPT_QUIET = 1 << 0, … … 310 344 OPT_W = 1 << 6, 311 345 OPT_I = 1 << 7, 312 OPT_IPV4 = 1 << 8, 313 OPT_IPV6 = (1 << 9) * ENABLE_PING6, 346 /*OPT_n = 1 << 8, - ignored */ 347 OPT_p = 1 << 9, 348 OPT_IPV4 = 1 << 10, 349 OPT_IPV6 = (1 << 11) * ENABLE_PING6, 314 350 }; 315 351 316 352 317 353 struct globals { 318 int pingsock;319 354 int if_index; 320 355 char *str_I; … … 325 360 unsigned long ntransmitted, nreceived, nrepeats; 326 361 uint16_t myid; 362 uint8_t pattern; 327 363 unsigned tmin, tmax; /* in us */ 328 364 unsigned long long tsum; /* in us, sum of all times */ … … 342 378 #endif 343 379 } pingaddr; 344 char rcvd_tbl[MAX_DUP_CHK / 8];380 unsigned char rcvd_tbl[MAX_DUP_CHK / 8]; 345 381 } FIX_ALIASING; 346 #define G (*(struct globals*)&bb_common_bufsiz1) 347 #define pingsock (G.pingsock ) 382 #define G (*(struct globals*)bb_common_bufsiz1) 348 383 #define if_index (G.if_index ) 349 384 #define source_lsa (G.source_lsa ) 350 385 #define str_I (G.str_I ) 351 386 #define datalen (G.datalen ) 352 #define ntransmitted (G.ntransmitted)353 #define nreceived (G.nreceived )354 #define nrepeats (G.nrepeats )355 387 #define pingcount (G.pingcount ) 356 388 #define opt_ttl (G.opt_ttl ) … … 366 398 #define pingaddr (G.pingaddr ) 367 399 #define rcvd_tbl (G.rcvd_tbl ) 368 void BUG_ping_globals_too_big(void);369 400 #define INIT_G() do { \ 370 if (sizeof(G) > COMMON_BUFSIZE) \ 371 BUG_ping_globals_too_big(); \ 372 pingsock = -1; \ 401 setup_common_bufsiz(); \ 402 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \ 373 403 datalen = DEFDATALEN; \ 374 404 timeout = MAXWAIT; \ … … 377 407 378 408 379 #define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ 380 #define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ 381 #define SET(bit) (A(bit) |= B(bit)) 382 #define CLR(bit) (A(bit) &= (~B(bit))) 383 #define TST(bit) (A(bit) & B(bit)) 384 385 /**************************************************************************/ 409 #define BYTE(bit) rcvd_tbl[(bit)>>3] 410 #define MASK(bit) (1 << ((bit) & 7)) 411 #define SET(bit) (BYTE(bit) |= MASK(bit)) 412 #define CLR(bit) (BYTE(bit) &= (~MASK(bit))) 413 #define TST(bit) (BYTE(bit) & MASK(bit)) 386 414 387 415 static void print_stats_and_exit(int junk) NORETURN; 388 416 static void print_stats_and_exit(int junk UNUSED_PARAM) 389 417 { 418 unsigned long ul; 419 unsigned long nrecv; 420 390 421 signal(SIGINT, SIG_IGN); 391 422 392 printf("\n--- %s ping statistics ---\n", hostname); 393 printf("%lu packets transmitted, ", ntransmitted); 394 printf("%lu packets received, ", nreceived); 395 if (nrepeats) 396 printf("%lu duplicates, ", nrepeats); 397 if (ntransmitted) 398 ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted; 399 printf("%lu%% packet loss\n", ntransmitted); 423 nrecv = G.nreceived; 424 printf("\n--- %s ping statistics ---\n" 425 "%lu packets transmitted, " 426 "%lu packets received, ", 427 hostname, G.ntransmitted, nrecv 428 ); 429 if (G.nrepeats) 430 printf("%lu duplicates, ", G.nrepeats); 431 ul = G.ntransmitted; 432 if (ul != 0) 433 ul = (ul - nrecv) * 100 / ul; 434 printf("%lu%% packet loss\n", ul); 400 435 if (tmin != UINT_MAX) { 401 unsigned tavg = tsum / (nrec eived +nrepeats);436 unsigned tavg = tsum / (nrecv + G.nrepeats); 402 437 printf("round-trip min/avg/max = %u.%03u/%u.%03u/%u.%03u ms\n", 403 438 tmin / 1000, tmin % 1000, … … 406 441 } 407 442 /* if condition is true, exit with 1 -- 'failure' */ 408 exit(nrec eived == 0 || (deadline && nreceived< pingcount));443 exit(nrecv == 0 || (deadline && nrecv < pingcount)); 409 444 } 410 445 … … 413 448 int sz; 414 449 415 CLR((uint16_t) ntransmitted % MAX_DUP_CHK);416 ntransmitted++;450 CLR((uint16_t)G.ntransmitted % MAX_DUP_CHK); 451 G.ntransmitted++; 417 452 418 453 size_pkt += datalen; … … 424 459 bb_error_msg_and_die(bb_msg_write_error); 425 460 426 if (pingcount == 0 || deadline || ntransmitted < pingcount) {461 if (pingcount == 0 || deadline || G.ntransmitted < pingcount) { 427 462 /* Didn't send all pings yet - schedule next in 1s */ 428 463 signal(SIGALRM, sp); … … 440 475 unsigned expire = timeout; 441 476 442 if ( nreceived) {477 if (G.nreceived) { 443 478 /* approx. 2*tmax, in seconds (2 RTT) */ 444 479 expire = tmax / (512*1024); … … 455 490 struct icmp *pkt = G.snd_packet; 456 491 457 //memset(pkt, 0, datalen + ICMP_MINLEN + 4); - G.snd_packet was xzalloced492 memset(pkt, G.pattern, datalen + ICMP_MINLEN + 4); 458 493 pkt->icmp_type = ICMP_ECHO; 459 494 /*pkt->icmp_code = 0;*/ 460 495 pkt->icmp_cksum = 0; /* cksum is calculated with this field set to 0 */ 461 pkt->icmp_seq = htons( ntransmitted); /* don't ++ here, it can be a macro */496 pkt->icmp_seq = htons(G.ntransmitted); /* don't ++ here, it can be a macro */ 462 497 pkt->icmp_id = myid; 463 498 … … 478 513 struct icmp6_hdr *pkt = G.snd_packet; 479 514 480 //memset(pkt, 0, datalen + sizeof(struct icmp6_hdr) + 4);515 memset(pkt, G.pattern, datalen + sizeof(struct icmp6_hdr) + 4); 481 516 pkt->icmp6_type = ICMP6_ECHO_REQUEST; 482 517 /*pkt->icmp6_code = 0;*/ 483 518 /*pkt->icmp6_cksum = 0;*/ 484 pkt->icmp6_seq = htons( ntransmitted); /* don't ++ here, it can be a macro */519 pkt->icmp6_seq = htons(G.ntransmitted); /* don't ++ here, it can be a macro */ 485 520 pkt->icmp6_id = myid; 486 521 487 522 /*if (datalen >= 4)*/ 488 *( uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us();523 *(bb__aliased_uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us(); 489 524 490 525 //TODO? pkt->icmp_cksum = inet_cksum(...); … … 546 581 uint16_t recv_seq, int ttl) 547 582 { 583 unsigned char *b, m; 548 584 const char *dupmsg = " (DUP!)"; 549 585 unsigned triptime = triptime; /* for gcc */ 550 551 ++nreceived;552 586 553 587 if (tp) { … … 562 596 } 563 597 564 if (TST(recv_seq % MAX_DUP_CHK)) { 565 ++nrepeats; 566 --nreceived; 598 b = &BYTE(recv_seq % MAX_DUP_CHK); 599 m = MASK(recv_seq % MAX_DUP_CHK); 600 /*if TST(recv_seq % MAX_DUP_CHK):*/ 601 if (*b & m) { 602 ++G.nrepeats; 567 603 } else { 568 SET(recv_seq % MAX_DUP_CHK); 604 /*SET(recv_seq % MAX_DUP_CHK):*/ 605 *b |= m; 606 ++G.nreceived; 569 607 dupmsg += 7; 570 608 } … … 649 687 int sockopt; 650 688 651 pingsock = create_icmp_socket();652 689 pingaddr.sin = lsa->u.sin; 653 690 if (source_lsa) { … … 657 694 xbind(pingsock, &source_lsa->u.sa, source_lsa->len); 658 695 } 659 if (str_I)660 setsockopt_bindtodevice(pingsock, str_I);661 696 662 697 /* enable broadcast pings */ … … 666 701 * broadcast ping etc) */ 667 702 sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */ 668 setsockopt (pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));703 setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt); 669 704 670 705 if (opt_ttl != 0) { 671 setsockopt (pingsock, IPPROTO_IP, IP_TTL, &opt_ttl, sizeof(opt_ttl));706 setsockopt_int(pingsock, IPPROTO_IP, IP_TTL, opt_ttl); 672 707 /* above doesnt affect packets sent to bcast IP, so... */ 673 setsockopt (pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl));708 setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl); 674 709 } 675 710 … … 693 728 } 694 729 unpack4(G.rcv_packet, c, &from); 695 if (pingcount && nreceived >= pingcount)730 if (pingcount && G.nreceived >= pingcount) 696 731 break; 697 732 } 698 733 } 699 734 #if ENABLE_PING6 700 extern int BUG_bad_offsetof_icmp6_cksum(void);701 735 static void ping6(len_and_sockaddr *lsa) 702 736 { … … 707 741 char control_buf[CMSG_SPACE(36)]; 708 742 709 pingsock = create_icmp6_socket();710 743 pingaddr.sin6 = lsa->u.sin6; 711 /* untested whether "-I addr" really works for IPv6: */712 744 if (source_lsa) 713 745 xbind(pingsock, &source_lsa->u.sa, source_lsa->len); 714 if (str_I)715 setsockopt_bindtodevice(pingsock, str_I);716 746 717 747 #ifdef ICMP6_FILTER … … 726 756 if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, 727 757 sizeof(filt)) < 0) 728 bb_error_msg_and_die("setsockopt( ICMP6_FILTER)");758 bb_error_msg_and_die("setsockopt(%s)", "ICMP6_FILTER"); 729 759 } 730 760 #endif /*ICMP6_FILTER*/ … … 736 766 * broadcast ping etc) */ 737 767 sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */ 738 setsockopt (pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));768 setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt); 739 769 740 770 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); 741 if (offsetof(struct icmp6_hdr, icmp6_cksum) != 2) 742 BUG_bad_offsetof_icmp6_cksum(); 743 setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt)); 771 BUILD_BUG_ON(offsetof(struct icmp6_hdr, icmp6_cksum) != 2); 772 setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt); 744 773 745 774 /* request ttl info to be returned in ancillary data */ 746 setsockopt (pingsock, SOL_IPV6, IPV6_HOPLIMIT, &const_int_1, sizeof(const_int_1));775 setsockopt_1(pingsock, SOL_IPV6, IPV6_HOPLIMIT); 747 776 748 777 if (if_index) … … 785 814 } 786 815 unpack6(G.rcv_packet, c, &from, hoplimit); 787 if (pingcount && nreceived >= pingcount)816 if (pingcount && G.nreceived >= pingcount) 788 817 break; 789 818 } … … 799 828 } 800 829 printf(": %d data bytes\n", datalen); 830 831 create_icmp_socket(lsa); 832 /* untested whether "-I addr" really works for IPv6: */ 833 if (str_I) 834 setsockopt_bindtodevice(pingsock, str_I); 801 835 802 836 G.sizeof_rcv_packet = datalen + MAXIPLEN + MAXICMPLEN; … … 819 853 { 820 854 len_and_sockaddr *lsa; 821 char *str_s ;855 char *str_s, *str_p; 822 856 823 857 INIT_G(); … … 825 859 /* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */ 826 860 opt_complementary = "=1:q--v:v--q:c+:t+:w+:W+"; 827 opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I );861 opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I, &str_p); 828 862 if (opt & OPT_s) 829 863 datalen = xatou16(str_s); // -s … … 836 870 } 837 871 } 872 if (opt & OPT_p) 873 G.pattern = xstrtou_range(str_p, 16, 0, 255); 874 838 875 myid = (uint16_t) getpid(); 839 876 hostname = argv[optind];
Note:
See TracChangeset
for help on using the changeset viewer.