1495
|
1 /* ping.c - check network connectivity
|
|
2 *
|
|
3 * Copyright 2014 Rob Landley <rob@landley.net>
|
|
4 *
|
|
5 * Not in SUSv4.
|
|
6
|
|
7 USE_PING(NEWTOY(ping, "<1>1t#<0>255c#<0s#<0>65535I:W#<0w#<0q46[-46]", TOYFLAG_ROOTONLY|TOYFLAG_USR|TOYFLAG_BIN))
|
|
8
|
|
9 config PING
|
|
10 bool "ping"
|
|
11 default n
|
|
12 help
|
|
13 usage: ping [OPTIONS] HOST
|
|
14
|
|
15 Check network connectivity by sending packets to a host and reporting
|
|
16 its response.
|
|
17
|
|
18 Send ICMP ECHO_REQUEST packets to ipv4 or ipv6 addresses and prints each
|
|
19 echo it receives back, with round trip time.
|
|
20
|
|
21 Options:
|
|
22 -4, -6 Force IPv4 or IPv6
|
|
23 -c CNT Send CNT many packets
|
|
24 -I IFACE/IP Source interface or address
|
|
25 -q Quiet, only displays output at start and when finished
|
|
26 -s SIZE Packet SIZE in bytes (default 56)
|
|
27 -t TTL Set Time (number of hops) To Live
|
|
28 -W SEC Seconds to wait for response after all packets sent (default 10)
|
|
29 -w SEC Exit after this many seconds
|
|
30 */
|
|
31
|
|
32 #define FOR_ping
|
|
33 #include "toys.h"
|
|
34
|
|
35 #include <ifaddrs.h>
|
|
36
|
|
37 GLOBALS(
|
|
38 long wait_exit;
|
|
39 long wait_resp;
|
|
40 char *iface;
|
|
41 long size;
|
|
42 long count;
|
|
43 long ttl;
|
|
44
|
|
45 int sock;
|
|
46 )
|
|
47
|
|
48 void ping_main(void)
|
|
49 {
|
|
50 int family, protocol;
|
|
51 union {
|
|
52 struct in_addr in;
|
|
53 struct in6_addr in6;
|
|
54 } src_addr;
|
|
55 char *host = 0;
|
|
56
|
|
57 // Determine IPv4 vs IPv6 type
|
|
58
|
|
59 if(!(toys.optflags & (FLAG_4|FLAG_6))) {
|
|
60 // todo getaddrinfo instead?
|
|
61 if (inet_pton(AF_INET6, toys.optargs[0], (void*)&src_addr))
|
|
62 toys.optflags |= FLAG_6;
|
|
63 }
|
|
64
|
|
65 if (toys.optflags & FLAG_6) {
|
|
66 family = AF_INET6;
|
|
67 protocol = IPPROTO_ICMPV6;
|
|
68 } else {
|
|
69 family = AF_INET;
|
|
70 protocol = IPPROTO_ICMP;
|
|
71 }
|
|
72
|
|
73 if (!(toys.optflags & FLAG_s)) TT.size = 56; // 64-PHDR_LEN
|
|
74
|
|
75 if (TT.iface) {
|
|
76 memset(&src_addr, 0, sizeof(src_addr));
|
|
77
|
|
78 // IP address?
|
|
79 if (!inet_pton(family, TT.iface, &src_addr)) {
|
|
80 struct ifaddrs *ifsave, *ifa = 0;
|
|
81
|
|
82 // Interface name?
|
|
83 if (!getifaddrs(&ifsave)) {
|
|
84 for (ifa = ifsave; ifa; ifa = ifa->ifa_next) {
|
|
85 if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != family) continue;
|
|
86 if (!strcmp(ifa->ifa_name, TT.iface)) {
|
|
87 if (family == AF_INET)
|
|
88 memcpy(&src_addr,
|
|
89 &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
|
|
90 sizeof(struct in_addr));
|
|
91 else memcpy(&src_addr,
|
|
92 &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
|
|
93 sizeof(struct in6_addr));
|
|
94 break;
|
|
95 }
|
|
96 }
|
|
97 freeifaddrs(ifsave);
|
|
98 }
|
|
99 if (!ifa)
|
|
100 error_exit("no v%d addr for -I %s", 4+2*(family==AF_INET6), TT.iface);
|
|
101 }
|
|
102 inet_ntop(family, &src_addr, toybuf, sizeof(toybuf));
|
|
103 host = xstrdup(toybuf);
|
|
104 }
|
|
105
|
|
106 printf("host=%s\n", host);
|
|
107
|
|
108 // Open raw socket
|
|
109 TT.sock = xsocket(family, SOCK_RAW, protocol);
|
|
110 }
|