1 |
/* Copyright (C) 1998, 2001 Free Software Foundation, Inc. |
/* Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc. |
2 |
|
|
3 |
This file is part of GNU Inetutils. |
This file is part of GNU Inetutils. |
4 |
|
|
16 |
along with GNU Inetutils; see the file COPYING. If not, write to |
along with GNU Inetutils; see the file COPYING. If not, write to |
17 |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 |
Boston, MA 02111-1307, USA. */ |
Boston, MA 02111-1307, USA. */ |
19 |
|
|
20 |
#ifdef HAVE_CONFIG_H |
#ifdef HAVE_CONFIG_H |
21 |
# include <config.h> |
# include <config.h> |
22 |
#endif |
#endif |
49 |
size_t |
size_t |
50 |
_ping_packetsize (PING *p) |
_ping_packetsize (PING *p) |
51 |
{ |
{ |
52 |
switch (p->ping_type) |
if (p->ping_type == ICMP_TIMESTAMP |
53 |
{ |
|| p->ping_type == ICMP_TIMESTAMPREPLY) |
54 |
case ICMP_TIMESTAMP: |
return 20; |
55 |
case ICMP_TIMESTAMPREPLY: |
return 8 + p->ping_datalen; |
|
return 20; |
|
|
|
|
|
default: |
|
|
return 8 + p->ping_datalen; |
|
|
} |
|
|
return 8; /* to keep compiler happy */ |
|
56 |
} |
} |
57 |
|
|
58 |
PING * |
PING * |
63 |
PING *p; |
PING *p; |
64 |
|
|
65 |
/* Initialize raw ICMP socket */ |
/* Initialize raw ICMP socket */ |
66 |
if (!(proto = getprotobyname ("icmp"))) { |
proto = getprotobyname ("icmp"); |
67 |
fprintf (stderr, "ping: unknown protocol icmp.\n"); |
if (!proto) |
68 |
return NULL; |
{ |
69 |
} |
fprintf (stderr, "ping: unknown protocol icmp.\n"); |
70 |
if ((fd = socket (AF_INET, SOCK_RAW, proto->p_proto)) < 0) { |
return NULL; |
71 |
if (errno == EPERM) { |
} |
72 |
fprintf (stderr, "ping: ping must run as root\n"); |
|
73 |
|
fd = socket (AF_INET, SOCK_RAW, proto->p_proto); |
74 |
|
if (fd < 0) |
75 |
|
{ |
76 |
|
if (errno == EPERM) |
77 |
|
fprintf (stderr, "ping: ping must run as root\n"); |
78 |
|
return NULL; |
79 |
} |
} |
|
return NULL; |
|
|
} |
|
80 |
|
|
81 |
/* Allocate PING structure and initialize it to default values */ |
/* Allocate PING structure and initialize it to default values */ |
82 |
if (!(p = malloc (sizeof (*p)))) |
p = malloc (sizeof (*p)); |
83 |
|
if (!p) |
84 |
{ |
{ |
85 |
close (fd); |
close (fd); |
86 |
return p; |
return p; |
173 |
{ |
{ |
174 |
case ICMP_ECHO: |
case ICMP_ECHO: |
175 |
icmp_echo_encode (p->ping_buffer, buflen, p->ping_ident, |
icmp_echo_encode (p->ping_buffer, buflen, p->ping_ident, |
176 |
p->ping_num_xmit); |
p->ping_num_xmit); |
177 |
break; |
break; |
178 |
|
|
179 |
case ICMP_TIMESTAMP: |
case ICMP_TIMESTAMP: |
180 |
icmp_timestamp_encode (p->ping_buffer, buflen, p->ping_ident, |
icmp_timestamp_encode (p->ping_buffer, buflen, p->ping_ident, |
181 |
p->ping_num_xmit); |
p->ping_num_xmit); |
182 |
break; |
break; |
183 |
|
|
184 |
case ICMP_ADDRESS: |
case ICMP_ADDRESS: |
185 |
icmp_address_encode (p->ping_buffer, buflen, p->ping_ident, |
icmp_address_encode (p->ping_buffer, buflen, p->ping_ident, |
186 |
p->ping_num_xmit); |
p->ping_num_xmit); |
187 |
break; |
break; |
188 |
|
|
189 |
default: |
default: |
190 |
icmp_generic_encode (p->ping_buffer, buflen, p->ping_type, p->ping_ident, |
icmp_generic_encode (p->ping_buffer, buflen, p->ping_type, p->ping_ident, |
191 |
p->ping_num_xmit); |
p->ping_num_xmit); |
192 |
break; |
break; |
193 |
} |
} |
194 |
|
|
195 |
i = sendto (p->ping_fd, (char *)p->ping_buffer, buflen, 0, |
i = sendto (p->ping_fd, (char *)p->ping_buffer, buflen, 0, |
196 |
(struct sockaddr*) &p->ping_dest, |
(struct sockaddr*) &p->ping_dest, |
197 |
sizeof (struct sockaddr_in)); |
sizeof (struct sockaddr_in)); |
198 |
if (i < 0) |
if (i < 0) |
199 |
{ |
perror ("ping: sendto"); |
|
perror ("ping: sendto"); |
|
|
} |
|
200 |
else |
else |
201 |
{ |
{ |
202 |
p->ping_num_xmit++; |
p->ping_num_xmit++; |
203 |
if (i != buflen) |
if (i != buflen) |
204 |
printf ("ping: wrote %s %d chars, ret=%d\n", |
printf ("ping: wrote %s %d chars, ret=%d\n", |
205 |
p->ping_hostname, buflen, i); |
p->ping_hostname, buflen, i); |
206 |
} |
} |
|
|
|
|
|
|
207 |
return 0; |
return 0; |
208 |
} |
} |
209 |
|
|
212 |
{ |
{ |
213 |
struct ip *orig_ip = &icmp->icmp_ip; |
struct ip *orig_ip = &icmp->icmp_ip; |
214 |
icmphdr_t *orig_icmp = (icmphdr_t *)(orig_ip + 1); |
icmphdr_t *orig_icmp = (icmphdr_t *)(orig_ip + 1); |
215 |
|
|
216 |
return orig_ip->ip_dst.s_addr == p->ping_dest.sin_addr.s_addr |
return (orig_ip->ip_dst.s_addr == p->ping_dest.sin_addr.s_addr |
217 |
&& orig_ip->ip_p == IPPROTO_ICMP |
&& orig_ip->ip_p == IPPROTO_ICMP |
218 |
&& orig_icmp->icmp_type == ICMP_ECHO |
&& orig_icmp->icmp_type == ICMP_ECHO |
219 |
&& orig_icmp->icmp_id == p->ping_ident; |
&& orig_icmp->icmp_id == p->ping_ident); |
220 |
} |
} |
221 |
|
|
222 |
int |
int |
228 |
struct ip *ip; |
struct ip *ip; |
229 |
int dupflag; |
int dupflag; |
230 |
|
|
231 |
if ((n = recvfrom (p->ping_fd, |
n = recvfrom (p->ping_fd, |
232 |
(char *)p->ping_buffer, _PING_BUFLEN (p), 0, |
(char *)p->ping_buffer, _PING_BUFLEN (p), 0, |
233 |
(struct sockaddr *)&p->ping_from, &fromlen)) < 0) |
(struct sockaddr *)&p->ping_from, &fromlen); |
234 |
|
if (n < 0) |
235 |
return -1; |
return -1; |
236 |
|
|
237 |
if ((rc = icmp_generic_decode (p->ping_buffer, n, &ip, &icmp)) < 0) |
rc = icmp_generic_decode (p->ping_buffer, n, &ip, &icmp); |
238 |
|
if (rc < 0) |
239 |
{ |
{ |
240 |
/*FIXME: conditional*/ |
/*FIXME: conditional*/ |
241 |
fprintf (stderr,"packet too short (%d bytes) from %s\n", n, |
fprintf (stderr, "packet too short (%d bytes) from %s\n", n, |
242 |
inet_ntoa (p->ping_from.sin_addr)); |
inet_ntoa (p->ping_from.sin_addr)); |
243 |
return -1; |
return -1; |
244 |
} |
} |
334 |
struct sockaddr_in *s_in = &ping->ping_dest; |
struct sockaddr_in *s_in = &ping->ping_dest; |
335 |
s_in->sin_family = AF_INET; |
s_in->sin_family = AF_INET; |
336 |
if (inet_aton (host, &s_in->sin_addr)) |
if (inet_aton (host, &s_in->sin_addr)) |
337 |
{ |
ping->ping_hostname = strdup (host); |
|
ping->ping_hostname = strdup (host); |
|
|
} |
|
338 |
else |
else |
339 |
{ |
{ |
340 |
struct hostent *hp = gethostbyname (host); |
struct hostent *hp = gethostbyname (host); |
351 |
return 0; |
return 0; |
352 |
} |
} |
353 |
|
|
354 |
|
|