39 |
#include <netdb.h> |
#include <netdb.h> |
40 |
#include <unistd.h> |
#include <unistd.h> |
41 |
#include <stdlib.h> |
#include <stdlib.h> |
42 |
|
#include <stdbool.h> |
43 |
#include <string.h> |
#include <string.h> |
44 |
#include <stdio.h> |
#include <stdio.h> |
45 |
#include <ctype.h> |
#include <ctype.h> |
102 |
static void init_data_buffer (u_char *pat, int len); |
static void init_data_buffer (u_char *pat, int len); |
103 |
static int send_echo (PING *ping); |
static int send_echo (PING *ping); |
104 |
|
|
|
static size_t |
|
|
ping_cvt_number (const char *optarg, size_t maxval, int allow_zero) |
|
|
{ |
|
|
char *p; |
|
|
size_t n; |
|
|
|
|
|
n = strtoul (optarg, &p, 0); |
|
|
if (*p) |
|
|
{ |
|
|
fprintf (stderr, "Invalid value (`%s' near `%s')\n", optarg, p); |
|
|
exit (1); |
|
|
} |
|
|
if (n == 0 && !allow_zero) |
|
|
{ |
|
|
fprintf (stderr, "Option value too small: %s\n", optarg); |
|
|
exit (1); |
|
|
} |
|
|
if (maxval && n > maxval) |
|
|
{ |
|
|
fprintf (stderr, "Option value too big: %s\n", optarg); |
|
|
exit (1); |
|
|
} |
|
|
return n; |
|
|
} |
|
|
|
|
105 |
int |
int |
106 |
main (int argc, char **argv) |
main (int argc, char **argv) |
107 |
{ |
{ |
111 |
u_char pattern[16]; |
u_char pattern[16]; |
112 |
int pattern_len = 16; |
int pattern_len = 16; |
113 |
u_char *patptr = NULL; |
u_char *patptr = NULL; |
114 |
int is_root = getuid () == 0; |
bool is_root = false; |
115 |
|
|
116 |
if ((ping = ping_init (ICMP_ECHO, getpid ())) == NULL) |
int count = 0; |
117 |
{ |
int socket_type = 0; |
118 |
fprintf (stderr, "can't init ping: %s\n", strerror (errno)); |
int interval = 0; |
119 |
exit (1); |
|
120 |
} |
if (getuid () == 0) |
121 |
ping_set_sockopt (ping, SO_BROADCAST, (char *)&one, sizeof (one)); |
is_root = true; |
|
|
|
|
/* Reset root privileges */ |
|
|
setuid (getuid ()); |
|
122 |
|
|
123 |
/* Parse command line */ |
/* Parse command line */ |
124 |
while ((c = getopt_long (argc, argv, short_options, long_options, NULL)) |
while ((c = getopt_long (argc, argv, short_options, long_options, NULL)) |
147 |
break; |
break; |
148 |
|
|
149 |
case 'c': |
case 'c': |
150 |
ping_set_count (ping, ping_cvt_number (optarg, 0, 0)); |
count = atoi (optarg); |
151 |
|
if (count <= 0) |
152 |
|
error (1, 0, "invalid count: %i", count); |
153 |
break; |
break; |
154 |
|
|
155 |
case 'd': |
case 'd': |
156 |
ping_set_sockopt (ping, SO_DEBUG, &one, sizeof (one)); |
socket_type = SO_DEBUG; |
157 |
break; |
break; |
158 |
|
|
159 |
case 'r': |
case 'r': |
160 |
ping_set_sockopt (ping, SO_DONTROUTE, &one, sizeof (one)); |
socket_type = SO_DONTROUTE; |
161 |
break; |
break; |
162 |
|
|
163 |
case 'i': |
case 'i': |
164 |
options |= OPT_INTERVAL; |
options |= OPT_INTERVAL; |
165 |
ping_set_interval (ping, ping_cvt_number (optarg, 0, 0)); |
if (interval <= 0) |
166 |
|
error (1, 0, "invalid interval: %i", interval); |
167 |
break; |
break; |
168 |
|
|
169 |
case 'p': |
case 'p': |
172 |
break; |
break; |
173 |
|
|
174 |
case 's': |
case 's': |
175 |
data_length = ping_cvt_number (optarg, PING_MAX_DATALEN, 1); |
data_length = atoi (optarg); |
176 |
|
if (data_length < 1 || data_length > PING_MAX_DATALEN) |
177 |
|
error (1, 0, "invalid data length: %i", data_length); |
178 |
break; |
break; |
179 |
|
|
180 |
case 'n': |
case 'n': |
194 |
break; |
break; |
195 |
|
|
196 |
case 'l': |
case 'l': |
197 |
if (!is_root) |
if (is_root == false) |
198 |
{ |
{ |
199 |
fprintf (stderr, "ping: option not allowed: --preload\n"); |
fprintf (stderr, "ping: option not allowed: --preload\n"); |
200 |
exit (1); |
exit (1); |
208 |
break; |
break; |
209 |
|
|
210 |
case 'f': |
case 'f': |
211 |
if (!is_root) |
if (is_root == false) |
212 |
{ |
{ |
213 |
fprintf (stderr, "ping: option not allowed: --flood\n"); |
fprintf (stderr, "ping: option not allowed: --flood\n"); |
214 |
exit (1); |
exit (1); |
251 |
exit (0); |
exit (0); |
252 |
} |
} |
253 |
|
|
254 |
|
if ((ping = ping_init (ICMP_ECHO, getpid ())) == NULL) |
255 |
|
{ |
256 |
|
fprintf (stderr, "can't init ping: %s\n", strerror (errno)); |
257 |
|
exit (1); |
258 |
|
} |
259 |
|
ping_set_sockopt (ping, SO_BROADCAST, (char *)&one, sizeof (one)); |
260 |
|
|
261 |
|
/* Reset root privileges */ |
262 |
|
setuid (getuid ()); |
263 |
|
|
264 |
|
if (count != 0) |
265 |
|
ping_set_count (ping, count); |
266 |
|
|
267 |
|
if (socket_type != 0) |
268 |
|
ping_set_sockopt (ping, socket_type, &one, sizeof (one)); |
269 |
|
|
270 |
|
if (options & OPT_INTERVAL) |
271 |
|
ping_set_interval (ping, interval); |
272 |
|
|
273 |
init_data_buffer (patptr, pattern_len); |
init_data_buffer (patptr, pattern_len); |
274 |
|
|
275 |
return (*ping_type)(argc, argv); |
return (*ping_type)(argc, argv); |