1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <net/if.h>
29#include <netinet/ip_icmp.h>
30#include "libbb.h"
31
32#if ENABLE_PING6
33#include <netinet/icmp6.h>
34
35
36#ifdef IPV6_2292HOPLIMIT
37#undef IPV6_HOPLIMIT
38#define IPV6_HOPLIMIT IPV6_2292HOPLIMIT
39#endif
40#endif
41
42enum {
43 DEFDATALEN = 56,
44 MAXIPLEN = 60,
45 MAXICMPLEN = 76,
46 MAXPACKET = 65468,
47 MAX_DUP_CHK = (8 * 128),
48 MAXWAIT = 10,
49 PINGINTERVAL = 1,
50};
51
52
53
54static int in_cksum(unsigned short *buf, int sz)
55{
56 int nleft = sz;
57 int sum = 0;
58 unsigned short *w = buf;
59 unsigned short ans = 0;
60
61 while (nleft > 1) {
62 sum += *w++;
63 nleft -= 2;
64 }
65
66 if (nleft == 1) {
67 *(unsigned char *) (&ans) = *(unsigned char *) w;
68 sum += ans;
69 }
70
71 sum = (sum >> 16) + (sum & 0xFFFF);
72 sum += (sum >> 16);
73 ans = ~sum;
74 return ans;
75}
76
77#if !ENABLE_FEATURE_FANCY_PING
78
79
80
81static char *hostname;
82
83static void noresp(int ign UNUSED_PARAM)
84{
85 printf("No response from %s\n", hostname);
86 exit(EXIT_FAILURE);
87}
88
89static void ping4(len_and_sockaddr *lsa)
90{
91 struct sockaddr_in pingaddr;
92 struct icmp *pkt;
93 int pingsock, c;
94 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
95
96 pingsock = create_icmp_socket();
97 pingaddr = lsa->u.sin;
98
99 pkt = (struct icmp *) packet;
100 memset(pkt, 0, sizeof(packet));
101 pkt->icmp_type = ICMP_ECHO;
102 pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
103
104 c = xsendto(pingsock, packet, DEFDATALEN + ICMP_MINLEN,
105 (struct sockaddr *) &pingaddr, sizeof(pingaddr));
106
107
108 while (1) {
109 struct sockaddr_in from;
110 socklen_t fromlen = sizeof(from);
111
112 c = recvfrom(pingsock, packet, sizeof(packet), 0,
113 (struct sockaddr *) &from, &fromlen);
114 if (c < 0) {
115 if (errno != EINTR)
116 bb_perror_msg("recvfrom");
117 continue;
118 }
119 if (c >= 76) {
120 struct iphdr *iphdr = (struct iphdr *) packet;
121
122 pkt = (struct icmp *) (packet + (iphdr->ihl << 2));
123 if (pkt->icmp_type == ICMP_ECHOREPLY)
124 break;
125 }
126 }
127 if (ENABLE_FEATURE_CLEAN_UP)
128 close(pingsock);
129}
130
131#if ENABLE_PING6
132static void ping6(len_and_sockaddr *lsa)
133{
134 struct sockaddr_in6 pingaddr;
135 struct icmp6_hdr *pkt;
136 int pingsock, c;
137 int sockopt;
138 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
139
140 pingsock = create_icmp6_socket();
141 pingaddr = lsa->u.sin6;
142
143 pkt = (struct icmp6_hdr *) packet;
144 memset(pkt, 0, sizeof(packet));
145 pkt->icmp6_type = ICMP6_ECHO_REQUEST;
146
147 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
148 setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
149
150 c = xsendto(pingsock, packet, DEFDATALEN + sizeof (struct icmp6_hdr),
151 (struct sockaddr *) &pingaddr, sizeof(pingaddr));
152
153
154 while (1) {
155 struct sockaddr_in6 from;
156 socklen_t fromlen = sizeof(from);
157
158 c = recvfrom(pingsock, packet, sizeof(packet), 0,
159 (struct sockaddr *) &from, &fromlen);
160 if (c < 0) {
161 if (errno != EINTR)
162 bb_perror_msg("recvfrom");
163 continue;
164 }
165 if (c >= 8) {
166 pkt = (struct icmp6_hdr *) packet;
167 if (pkt->icmp6_type == ICMP6_ECHO_REPLY)
168 break;
169 }
170 }
171 if (ENABLE_FEATURE_CLEAN_UP)
172 close(pingsock);
173}
174#endif
175
176int ping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
177int ping_main(int argc UNUSED_PARAM, char **argv)
178{
179 len_and_sockaddr *lsa;
180#if ENABLE_PING6
181 sa_family_t af = AF_UNSPEC;
182
183 while ((++argv)[0] && argv[0][0] == '-') {
184 if (argv[0][1] == '4') {
185 af = AF_INET;
186 continue;
187 }
188 if (argv[0][1] == '6') {
189 af = AF_INET6;
190 continue;
191 }
192 bb_show_usage();
193 }
194#else
195 argv++;
196#endif
197
198 hostname = *argv;
199 if (!hostname)
200 bb_show_usage();
201
202#if ENABLE_PING6
203 lsa = xhost_and_af2sockaddr(hostname, 0, af);
204#else
205 lsa = xhost_and_af2sockaddr(hostname, 0, AF_INET);
206#endif
207
208 signal(SIGALRM, noresp);
209 alarm(5);
210
211#if ENABLE_PING6
212 if (lsa->u.sa.sa_family == AF_INET6)
213 ping6(lsa);
214 else
215#endif
216 ping4(lsa);
217 printf("%s is alive!\n", hostname);
218 return EXIT_SUCCESS;
219}
220
221
222#else
223
224
225
226
227#define OPT_STRING ("qvc:s:w:W:I:4" IF_PING6("6"))
228enum {
229 OPT_QUIET = 1 << 0,
230 OPT_VERBOSE = 1 << 1,
231 OPT_c = 1 << 2,
232 OPT_s = 1 << 3,
233 OPT_w = 1 << 4,
234 OPT_W = 1 << 5,
235 OPT_I = 1 << 6,
236 OPT_IPV4 = 1 << 7,
237 OPT_IPV6 = (1 << 8) * ENABLE_PING6,
238};
239
240
241struct globals {
242 int pingsock;
243 int if_index;
244 char *str_I;
245 len_and_sockaddr *source_lsa;
246 unsigned datalen;
247 unsigned pingcount;
248 unsigned long ntransmitted, nreceived, nrepeats;
249 uint16_t myid;
250 unsigned tmin, tmax;
251 unsigned long long tsum;
252 unsigned deadline;
253 unsigned timeout;
254 unsigned total_secs;
255 const char *hostname;
256 const char *dotted;
257 union {
258 struct sockaddr sa;
259 struct sockaddr_in sin;
260#if ENABLE_PING6
261 struct sockaddr_in6 sin6;
262#endif
263 } pingaddr;
264 char rcvd_tbl[MAX_DUP_CHK / 8];
265};
266#define G (*(struct globals*)&bb_common_bufsiz1)
267#define pingsock (G.pingsock )
268#define if_index (G.if_index )
269#define source_lsa (G.source_lsa )
270#define str_I (G.str_I )
271#define datalen (G.datalen )
272#define ntransmitted (G.ntransmitted)
273#define nreceived (G.nreceived )
274#define nrepeats (G.nrepeats )
275#define pingcount (G.pingcount )
276#define myid (G.myid )
277#define tmin (G.tmin )
278#define tmax (G.tmax )
279#define tsum (G.tsum )
280#define deadline (G.deadline )
281#define timeout (G.timeout )
282#define total_secs (G.total_secs )
283#define hostname (G.hostname )
284#define dotted (G.dotted )
285#define pingaddr (G.pingaddr )
286#define rcvd_tbl (G.rcvd_tbl )
287void BUG_ping_globals_too_big(void);
288#define INIT_G() do { \
289 if (sizeof(G) > COMMON_BUFSIZE) \
290 BUG_ping_globals_too_big(); \
291 pingsock = -1; \
292 datalen = DEFDATALEN; \
293 timeout = MAXWAIT; \
294 tmin = UINT_MAX; \
295} while (0)
296
297
298#define A(bit) rcvd_tbl[(bit)>>3]
299#define B(bit) (1 << ((bit) & 0x07))
300#define SET(bit) (A(bit) |= B(bit))
301#define CLR(bit) (A(bit) &= (~B(bit)))
302#define TST(bit) (A(bit) & B(bit))
303
304
305
306static void print_stats_and_exit(int junk) NORETURN;
307static void print_stats_and_exit(int junk UNUSED_PARAM)
308{
309 signal(SIGINT, SIG_IGN);
310
311 printf("\n--- %s ping statistics ---\n", hostname);
312 printf("%lu packets transmitted, ", ntransmitted);
313 printf("%lu packets received, ", nreceived);
314 if (nrepeats)
315 printf("%lu duplicates, ", nrepeats);
316 if (ntransmitted)
317 ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted;
318 printf("%lu%% packet loss\n", ntransmitted);
319 if (tmin != UINT_MAX) {
320 unsigned tavg = tsum / (nreceived + nrepeats);
321 printf("round-trip min/avg/max = %u.%03u/%u.%03u/%u.%03u ms\n",
322 tmin / 1000, tmin % 1000,
323 tavg / 1000, tavg % 1000,
324 tmax / 1000, tmax % 1000);
325 }
326
327 exit(nreceived == 0 || (deadline && nreceived < pingcount));
328}
329
330static void sendping_tail(void (*sp)(int), const void *pkt, int size_pkt)
331{
332 int sz;
333
334 CLR((uint16_t)ntransmitted % MAX_DUP_CHK);
335 ntransmitted++;
336
337
338
339 sz = xsendto(pingsock, pkt, size_pkt, &pingaddr.sa, sizeof(pingaddr));
340 if (sz != size_pkt)
341 bb_error_msg_and_die(bb_msg_write_error);
342
343 if (pingcount == 0 || deadline || ntransmitted < pingcount) {
344
345 signal(SIGALRM, sp);
346 if (deadline) {
347 total_secs += PINGINTERVAL;
348 if (total_secs >= deadline)
349 signal(SIGALRM, print_stats_and_exit);
350 }
351 alarm(PINGINTERVAL);
352 } else {
353
354
355
356
357 unsigned expire = timeout;
358
359 if (nreceived) {
360
361 expire = tmax / (512*1024);
362 if (expire == 0)
363 expire = 1;
364 }
365 signal(SIGALRM, print_stats_and_exit);
366 alarm(expire);
367 }
368}
369
370static void sendping4(int junk UNUSED_PARAM)
371{
372
373
374 struct icmp *pkt = alloca(datalen + ICMP_MINLEN + 4);
375
376 memset(pkt, 0, datalen + ICMP_MINLEN + 4);
377 pkt->icmp_type = ICMP_ECHO;
378
379
380 pkt->icmp_seq = htons(ntransmitted);
381 pkt->icmp_id = myid;
382
383
384
385 *(uint32_t*)&pkt->icmp_dun = monotonic_us();
386
387 pkt->icmp_cksum = in_cksum((unsigned short *) pkt, datalen + ICMP_MINLEN);
388
389 sendping_tail(sendping4, pkt, datalen + ICMP_MINLEN);
390}
391#if ENABLE_PING6
392static void sendping6(int junk UNUSED_PARAM)
393{
394 struct icmp6_hdr *pkt = alloca(datalen + sizeof(struct icmp6_hdr) + 4);
395
396 memset(pkt, 0, datalen + sizeof(struct icmp6_hdr) + 4);
397 pkt->icmp6_type = ICMP6_ECHO_REQUEST;
398
399
400 pkt->icmp6_seq = htons(ntransmitted);
401 pkt->icmp6_id = myid;
402
403
404 *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us();
405
406 sendping_tail(sendping6, pkt, datalen + sizeof(struct icmp6_hdr));
407}
408#endif
409
410static const char *icmp_type_name(int id)
411{
412 switch (id) {
413 case ICMP_ECHOREPLY: return "Echo Reply";
414 case ICMP_DEST_UNREACH: return "Destination Unreachable";
415 case ICMP_SOURCE_QUENCH: return "Source Quench";
416 case ICMP_REDIRECT: return "Redirect (change route)";
417 case ICMP_ECHO: return "Echo Request";
418 case ICMP_TIME_EXCEEDED: return "Time Exceeded";
419 case ICMP_PARAMETERPROB: return "Parameter Problem";
420 case ICMP_TIMESTAMP: return "Timestamp Request";
421 case ICMP_TIMESTAMPREPLY: return "Timestamp Reply";
422 case ICMP_INFO_REQUEST: return "Information Request";
423 case ICMP_INFO_REPLY: return "Information Reply";
424 case ICMP_ADDRESS: return "Address Mask Request";
425 case ICMP_ADDRESSREPLY: return "Address Mask Reply";
426 default: return "unknown ICMP type";
427 }
428}
429#if ENABLE_PING6
430
431
432#ifndef MLD_LISTENER_QUERY
433# define MLD_LISTENER_QUERY ICMP6_MEMBERSHIP_QUERY
434#endif
435#ifndef MLD_LISTENER_REPORT
436# define MLD_LISTENER_REPORT ICMP6_MEMBERSHIP_REPORT
437#endif
438#ifndef MLD_LISTENER_REDUCTION
439# define MLD_LISTENER_REDUCTION ICMP6_MEMBERSHIP_REDUCTION
440#endif
441static const char *icmp6_type_name(int id)
442{
443 switch (id) {
444 case ICMP6_DST_UNREACH: return "Destination Unreachable";
445 case ICMP6_PACKET_TOO_BIG: return "Packet too big";
446 case ICMP6_TIME_EXCEEDED: return "Time Exceeded";
447 case ICMP6_PARAM_PROB: return "Parameter Problem";
448 case ICMP6_ECHO_REPLY: return "Echo Reply";
449 case ICMP6_ECHO_REQUEST: return "Echo Request";
450 case MLD_LISTENER_QUERY: return "Listener Query";
451 case MLD_LISTENER_REPORT: return "Listener Report";
452 case MLD_LISTENER_REDUCTION: return "Listener Reduction";
453 default: return "unknown ICMP type";
454 }
455}
456#endif
457
458static void unpack_tail(int sz, uint32_t *tp,
459 const char *from_str,
460 uint16_t recv_seq, int ttl)
461{
462 const char *dupmsg = " (DUP!)";
463 unsigned triptime = triptime;
464
465 ++nreceived;
466
467 if (tp) {
468
469
470 triptime = (int32_t) ((uint32_t)monotonic_us() - *tp);
471 tsum += triptime;
472 if (triptime < tmin)
473 tmin = triptime;
474 if (triptime > tmax)
475 tmax = triptime;
476 }
477
478 if (TST(recv_seq % MAX_DUP_CHK)) {
479 ++nrepeats;
480 --nreceived;
481 } else {
482 SET(recv_seq % MAX_DUP_CHK);
483 dupmsg += 7;
484 }
485
486 if (option_mask32 & OPT_QUIET)
487 return;
488
489 printf("%d bytes from %s: seq=%u ttl=%d", sz,
490 from_str, recv_seq, ttl);
491 if (tp)
492 printf(" time=%u.%03u ms", triptime / 1000, triptime % 1000);
493 puts(dupmsg);
494 fflush(stdout);
495}
496static void unpack4(char *buf, int sz, struct sockaddr_in *from)
497{
498 struct icmp *icmppkt;
499 struct iphdr *iphdr;
500 int hlen;
501
502
503 if (sz < (datalen + ICMP_MINLEN))
504 return;
505
506
507 iphdr = (struct iphdr *) buf;
508 hlen = iphdr->ihl << 2;
509 sz -= hlen;
510 icmppkt = (struct icmp *) (buf + hlen);
511 if (icmppkt->icmp_id != myid)
512 return;
513
514 if (icmppkt->icmp_type == ICMP_ECHOREPLY) {
515 uint16_t recv_seq = ntohs(icmppkt->icmp_seq);
516 uint32_t *tp = NULL;
517
518 if (sz >= ICMP_MINLEN + sizeof(uint32_t))
519 tp = (uint32_t *) icmppkt->icmp_data;
520 unpack_tail(sz, tp,
521 inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
522 recv_seq, iphdr->ttl);
523 } else if (icmppkt->icmp_type != ICMP_ECHO) {
524 bb_error_msg("warning: got ICMP %d (%s)",
525 icmppkt->icmp_type,
526 icmp_type_name(icmppkt->icmp_type));
527 }
528}
529#if ENABLE_PING6
530static void unpack6(char *packet, int sz, int hoplimit)
531{
532 struct icmp6_hdr *icmppkt;
533 char buf[INET6_ADDRSTRLEN];
534
535
536 if (sz < (datalen + sizeof(struct icmp6_hdr)))
537 return;
538
539 icmppkt = (struct icmp6_hdr *) packet;
540 if (icmppkt->icmp6_id != myid)
541 return;
542
543 if (icmppkt->icmp6_type == ICMP6_ECHO_REPLY) {
544 uint16_t recv_seq = ntohs(icmppkt->icmp6_seq);
545 uint32_t *tp = NULL;
546
547 if (sz >= sizeof(struct icmp6_hdr) + sizeof(uint32_t))
548 tp = (uint32_t *) &icmppkt->icmp6_data8[4];
549 unpack_tail(sz, tp,
550 inet_ntop(AF_INET6, &pingaddr.sin6.sin6_addr,
551 buf, sizeof(buf)),
552 recv_seq, hoplimit);
553 } else if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST) {
554 bb_error_msg("warning: got ICMP %d (%s)",
555 icmppkt->icmp6_type,
556 icmp6_type_name(icmppkt->icmp6_type));
557 }
558}
559#endif
560
561static void ping4(len_and_sockaddr *lsa)
562{
563 char packet[datalen + MAXIPLEN + MAXICMPLEN];
564 int sockopt;
565
566 pingsock = create_icmp_socket();
567 pingaddr.sin = lsa->u.sin;
568 if (source_lsa) {
569 if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF,
570 &source_lsa->u.sa, source_lsa->len))
571 bb_error_msg_and_die("can't set multicast source interface");
572 xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
573 }
574 if (str_I)
575 setsockopt_bindtodevice(pingsock, str_I);
576
577
578 setsockopt_broadcast(pingsock);
579
580
581
582 sockopt = (datalen * 2) + 7 * 1024;
583 setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
584
585 signal(SIGINT, print_stats_and_exit);
586
587
588 sendping4(0);
589
590
591 while (1) {
592 struct sockaddr_in from;
593 socklen_t fromlen = (socklen_t) sizeof(from);
594 int c;
595
596 c = recvfrom(pingsock, packet, sizeof(packet), 0,
597 (struct sockaddr *) &from, &fromlen);
598 if (c < 0) {
599 if (errno != EINTR)
600 bb_perror_msg("recvfrom");
601 continue;
602 }
603 unpack4(packet, c, &from);
604 if (pingcount && nreceived >= pingcount)
605 break;
606 }
607}
608#if ENABLE_PING6
609extern int BUG_bad_offsetof_icmp6_cksum(void);
610static void ping6(len_and_sockaddr *lsa)
611{
612 char packet[datalen + MAXIPLEN + MAXICMPLEN];
613 int sockopt;
614 struct msghdr msg;
615 struct sockaddr_in6 from;
616 struct iovec iov;
617 char control_buf[CMSG_SPACE(36)];
618
619 pingsock = create_icmp6_socket();
620 pingaddr.sin6 = lsa->u.sin6;
621
622 if (source_lsa)
623 xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
624 if (str_I)
625 setsockopt_bindtodevice(pingsock, str_I);
626
627#ifdef ICMP6_FILTER
628 {
629 struct icmp6_filter filt;
630 if (!(option_mask32 & OPT_VERBOSE)) {
631 ICMP6_FILTER_SETBLOCKALL(&filt);
632 ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
633 } else {
634 ICMP6_FILTER_SETPASSALL(&filt);
635 }
636 if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
637 sizeof(filt)) < 0)
638 bb_error_msg_and_die("setsockopt(ICMP6_FILTER)");
639 }
640#endif
641
642
643 setsockopt_broadcast(pingsock);
644
645
646
647 sockopt = (datalen * 2) + 7 * 1024;
648 setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
649
650 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
651 if (offsetof(struct icmp6_hdr, icmp6_cksum) != 2)
652 BUG_bad_offsetof_icmp6_cksum();
653 setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
654
655
656 setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, &const_int_1, sizeof(const_int_1));
657
658 if (if_index)
659 pingaddr.sin6.sin6_scope_id = if_index;
660
661 signal(SIGINT, print_stats_and_exit);
662
663
664 sendping6(0);
665
666
667 msg.msg_name = &from;
668 msg.msg_namelen = sizeof(from);
669 msg.msg_iov = &iov;
670 msg.msg_iovlen = 1;
671 msg.msg_control = control_buf;
672 iov.iov_base = packet;
673 iov.iov_len = sizeof(packet);
674 while (1) {
675 int c;
676 struct cmsghdr *mp;
677 int hoplimit = -1;
678 msg.msg_controllen = sizeof(control_buf);
679
680 c = recvmsg(pingsock, &msg, 0);
681 if (c < 0) {
682 if (errno != EINTR)
683 bb_perror_msg("recvfrom");
684 continue;
685 }
686 for (mp = CMSG_FIRSTHDR(&msg); mp; mp = CMSG_NXTHDR(&msg, mp)) {
687 if (mp->cmsg_level == SOL_IPV6
688 && mp->cmsg_type == IPV6_HOPLIMIT
689
690
691 ) {
692 hoplimit = *(int*)CMSG_DATA(mp);
693 }
694 }
695 unpack6(packet, c, hoplimit);
696 if (pingcount && nreceived >= pingcount)
697 break;
698 }
699}
700#endif
701
702static void ping(len_and_sockaddr *lsa)
703{
704 printf("PING %s (%s)", hostname, dotted);
705 if (source_lsa) {
706 printf(" from %s",
707 xmalloc_sockaddr2dotted_noport(&source_lsa->u.sa));
708 }
709 printf(": %d data bytes\n", datalen);
710
711#if ENABLE_PING6
712 if (lsa->u.sa.sa_family == AF_INET6)
713 ping6(lsa);
714 else
715#endif
716 ping4(lsa);
717}
718
719int ping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
720int ping_main(int argc UNUSED_PARAM, char **argv)
721{
722 len_and_sockaddr *lsa;
723 char *str_s;
724 int opt;
725
726 INIT_G();
727
728
729 opt_complementary = "=1:q--v:v--q:c+:w+:W+";
730 opt = getopt32(argv, OPT_STRING, &pingcount, &str_s, &deadline, &timeout, &str_I);
731 if (opt & OPT_s)
732 datalen = xatou16(str_s);
733 if (opt & OPT_I) {
734 if_index = if_nametoindex(str_I);
735 if (!if_index) {
736
737 source_lsa = xdotted2sockaddr(str_I, 0);
738 str_I = NULL;
739 }
740 }
741 myid = (uint16_t) getpid();
742 hostname = argv[optind];
743#if ENABLE_PING6
744 {
745 sa_family_t af = AF_UNSPEC;
746 if (opt & OPT_IPV4)
747 af = AF_INET;
748 if (opt & OPT_IPV6)
749 af = AF_INET6;
750 lsa = xhost_and_af2sockaddr(hostname, 0, af);
751 }
752#else
753 lsa = xhost_and_af2sockaddr(hostname, 0, AF_INET);
754#endif
755
756 if (source_lsa && source_lsa->u.sa.sa_family != lsa->u.sa.sa_family)
757
758 source_lsa = NULL;
759
760 dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
761 ping(lsa);
762 print_stats_and_exit(EXIT_SUCCESS);
763
764}
765#endif
766
767
768#if ENABLE_PING6
769int ping6_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
770int ping6_main(int argc UNUSED_PARAM, char **argv)
771{
772 argv[0] = (char*)"-6";
773 return ping_main(0 ,
774 argv - 1);
775}
776#endif
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813