diff options
Diffstat (limited to 'plugins/netutils.c')
-rw-r--r-- | plugins/netutils.c | 253 |
1 files changed, 65 insertions, 188 deletions
diff --git a/plugins/netutils.c b/plugins/netutils.c index fc85a24..c0e82da 100644 --- a/plugins/netutils.c +++ b/plugins/netutils.c | |||
@@ -40,20 +40,18 @@ RETSIGTYPE socket_timeout_alarm_handler (int); | |||
40 | int process_tcp_request2 (char *, int, char *, char *, int); | 40 | int process_tcp_request2 (char *, int, char *, char *, int); |
41 | int process_tcp_request (char *, int, char *, char *, int); | 41 | int process_tcp_request (char *, int, char *, char *, int); |
42 | int process_udp_request (char *, int, char *, char *, int); | 42 | int process_udp_request (char *, int, char *, char *, int); |
43 | int process_request (char *, int, char *, char *, char *, int); | 43 | int process_request (char *, int, int, char *, char *, int); |
44 | 44 | ||
45 | int my_tcp_connect (char *, int, int *); | 45 | int my_tcp_connect (char *, int, int *); |
46 | int my_udp_connect (char *, int, int *); | 46 | int my_udp_connect (char *, int, int *); |
47 | int my_connect (char *, int, int *, char *); | 47 | int my_connect (char *, int, int *, int); |
48 | |||
49 | int my_inet_aton (register const char *, struct in_addr *); | ||
50 | 48 | ||
51 | /* handles socket timeouts */ | 49 | /* handles socket timeouts */ |
52 | void | 50 | void |
53 | socket_timeout_alarm_handler (int sig) | 51 | socket_timeout_alarm_handler (int sig) |
54 | { | 52 | { |
55 | 53 | ||
56 | printf ("Socket timeout after %d seconds\n", socket_timeout); | 54 | printf ("CRITICAL - Socket timeout after %d seconds\n", socket_timeout); |
57 | 55 | ||
58 | exit (STATE_CRITICAL); | 56 | exit (STATE_CRITICAL); |
59 | } | 57 | } |
@@ -62,16 +60,13 @@ socket_timeout_alarm_handler (int sig) | |||
62 | /* connects to a host on a specified TCP port, sends a string, | 60 | /* connects to a host on a specified TCP port, sends a string, |
63 | and gets a response */ | 61 | and gets a response */ |
64 | int | 62 | int |
65 | process_tcp_request (char *server_address, | 63 | process_tcp_request (char *server_address, int server_port, |
66 | int server_port, | 64 | char *send_buffer, char *recv_buffer, int recv_size) |
67 | char *send_buffer, char *recv_buffer, int recv_size) | ||
68 | { | 65 | { |
69 | int result; | 66 | int result; |
70 | char proto[4] = "tcp"; | ||
71 | 67 | ||
72 | result = process_request (server_address, | 68 | result = process_request (server_address, server_port, |
73 | server_port, | 69 | IPPROTO_TCP, send_buffer, recv_buffer, recv_size); |
74 | proto, send_buffer, recv_buffer, recv_size); | ||
75 | 70 | ||
76 | return result; | 71 | return result; |
77 | } | 72 | } |
@@ -80,16 +75,13 @@ process_tcp_request (char *server_address, | |||
80 | /* connects to a host on a specified UDP port, sends a string, and gets a | 75 | /* connects to a host on a specified UDP port, sends a string, and gets a |
81 | response */ | 76 | response */ |
82 | int | 77 | int |
83 | process_udp_request (char *server_address, | 78 | process_udp_request (char *server_address, int server_port, |
84 | int server_port, | 79 | char *send_buffer, char *recv_buffer, int recv_size) |
85 | char *send_buffer, char *recv_buffer, int recv_size) | ||
86 | { | 80 | { |
87 | int result; | 81 | int result; |
88 | char proto[4] = "udp"; | ||
89 | 82 | ||
90 | result = process_request (server_address, | 83 | result = process_request (server_address, server_port, |
91 | server_port, | 84 | IPPROTO_UDP, send_buffer, recv_buffer, recv_size); |
92 | proto, send_buffer, recv_buffer, recv_size); | ||
93 | 85 | ||
94 | return result; | 86 | return result; |
95 | } | 87 | } |
@@ -100,9 +92,8 @@ process_udp_request (char *server_address, | |||
100 | response. loops on select-recv until timeout or eof to get all of a | 92 | response. loops on select-recv until timeout or eof to get all of a |
101 | multi-packet answer */ | 93 | multi-packet answer */ |
102 | int | 94 | int |
103 | process_tcp_request2 (char *server_address, | 95 | process_tcp_request2 (char *server_address, int server_port, |
104 | int server_port, | 96 | char *send_buffer, char *recv_buffer, int recv_size) |
105 | char *send_buffer, char *recv_buffer, int recv_size) | ||
106 | { | 97 | { |
107 | 98 | ||
108 | int result; | 99 | int result; |
@@ -113,7 +104,7 @@ process_tcp_request2 (char *server_address, | |||
113 | fd_set readfds; | 104 | fd_set readfds; |
114 | int recv_length = 0; | 105 | int recv_length = 0; |
115 | 106 | ||
116 | result = my_connect (server_address, server_port, &sd, "tcp"); | 107 | result = my_connect (server_address, server_port, &sd, IPPROTO_TCP); |
117 | if (result != STATE_OK) | 108 | if (result != STATE_OK) |
118 | return STATE_CRITICAL; | 109 | return STATE_CRITICAL; |
119 | 110 | ||
@@ -146,25 +137,31 @@ process_tcp_request2 (char *server_address, | |||
146 | } | 137 | } |
147 | else { /* it has */ | 138 | else { /* it has */ |
148 | recv_result = | 139 | recv_result = |
149 | recv (sd, recv_buffer + recv_length, recv_size - recv_length - 1, 0); | 140 | recv (sd, recv_buffer + recv_length, |
150 | if (recv_result == -1) { /* recv failed, bail out */ | 141 | recv_size - recv_length - 1, 0); |
142 | if (recv_result == -1) { | ||
143 | /* recv failed, bail out */ | ||
151 | strcpy (recv_buffer + recv_length, ""); | 144 | strcpy (recv_buffer + recv_length, ""); |
152 | result = STATE_WARNING; | 145 | result = STATE_WARNING; |
153 | break; | 146 | break; |
154 | } | 147 | } |
155 | else if (recv_result == 0) { /* end of file ? */ | 148 | else if (recv_result == 0) { |
149 | /* end of file ? */ | ||
156 | recv_buffer[recv_length] = 0; | 150 | recv_buffer[recv_length] = 0; |
157 | break; | 151 | break; |
158 | } | 152 | } |
159 | else { /* we got data! */ | 153 | else { /* we got data! */ |
160 | recv_length += recv_result; | 154 | recv_length += recv_result; |
161 | if (recv_length >= recv_size - 1) { /* buffer full, we're done */ | 155 | if (recv_length >= recv_size - 1) { |
156 | /* buffer full, we're done */ | ||
162 | recv_buffer[recv_size - 1] = 0; | 157 | recv_buffer[recv_size - 1] = 0; |
163 | break; | 158 | break; |
164 | } | 159 | } |
165 | } | 160 | } |
166 | } /* end if(!FD_ISSET(sd,&readfds)) */ | 161 | } |
167 | } /* end while(1) */ | 162 | /* end if(!FD_ISSET(sd,&readfds)) */ |
163 | } | ||
164 | /* end while(1) */ | ||
168 | 165 | ||
169 | close (sd); | 166 | close (sd); |
170 | return result; | 167 | return result; |
@@ -173,10 +170,8 @@ process_tcp_request2 (char *server_address, | |||
173 | /* connects to a host on a specified port, sends a string, and gets a | 170 | /* connects to a host on a specified port, sends a string, and gets a |
174 | response */ | 171 | response */ |
175 | int | 172 | int |
176 | process_request (char *server_address, | 173 | process_request (char *server_address, int server_port, int proto, |
177 | int server_port, | 174 | char *send_buffer, char *recv_buffer, int recv_size) |
178 | char *proto, | ||
179 | char *send_buffer, char *recv_buffer, int recv_size) | ||
180 | { | 175 | { |
181 | int result; | 176 | int result; |
182 | int send_result; | 177 | int send_result; |
@@ -216,7 +211,7 @@ process_request (char *server_address, | |||
216 | recv_result = recv (sd, recv_buffer, recv_size - 1, 0); | 211 | recv_result = recv (sd, recv_buffer, recv_size - 1, 0); |
217 | if (recv_result == -1) { | 212 | if (recv_result == -1) { |
218 | strcpy (recv_buffer, ""); | 213 | strcpy (recv_buffer, ""); |
219 | if (!strcmp (proto, "tcp")) | 214 | if (proto != IPPROTO_TCP) |
220 | printf ("recv() failed\n"); | 215 | printf ("recv() failed\n"); |
221 | result = STATE_WARNING; | 216 | result = STATE_WARNING; |
222 | } | 217 | } |
@@ -238,9 +233,8 @@ int | |||
238 | my_tcp_connect (char *host_name, int port, int *sd) | 233 | my_tcp_connect (char *host_name, int port, int *sd) |
239 | { | 234 | { |
240 | int result; | 235 | int result; |
241 | char proto[4] = "tcp"; | ||
242 | 236 | ||
243 | result = my_connect (host_name, port, sd, proto); | 237 | result = my_connect (host_name, port, sd, IPPROTO_TCP); |
244 | 238 | ||
245 | return result; | 239 | return result; |
246 | } | 240 | } |
@@ -251,9 +245,8 @@ int | |||
251 | my_udp_connect (char *host_name, int port, int *sd) | 245 | my_udp_connect (char *host_name, int port, int *sd) |
252 | { | 246 | { |
253 | int result; | 247 | int result; |
254 | char proto[4] = "udp"; | ||
255 | 248 | ||
256 | result = my_connect (host_name, port, sd, proto); | 249 | result = my_connect (host_name, port, sd, IPPROTO_UDP); |
257 | 250 | ||
258 | return result; | 251 | return result; |
259 | } | 252 | } |
@@ -261,169 +254,53 @@ my_udp_connect (char *host_name, int port, int *sd) | |||
261 | 254 | ||
262 | /* opens a tcp or udp connection to a remote host */ | 255 | /* opens a tcp or udp connection to a remote host */ |
263 | int | 256 | int |
264 | my_connect (char *host_name, int port, int *sd, char *proto) | 257 | my_connect (char *host_name, int port, int *sd, int proto) |
265 | { | 258 | { |
266 | struct sockaddr_in servaddr; | 259 | struct addrinfo hints; |
267 | struct hostent *hp; | 260 | struct addrinfo *res; |
268 | struct protoent *ptrp; | 261 | struct addrinfo *ptrp; |
262 | char port_str[6]; | ||
269 | int result; | 263 | int result; |
270 | 264 | ||
271 | bzero ((char *) &servaddr, sizeof (servaddr)); | 265 | memset (&hints, 0, sizeof (hints)); |
272 | servaddr.sin_family = AF_INET; | 266 | hints.ai_family = PF_UNSPEC; |
273 | servaddr.sin_port = htons (port); | 267 | hints.ai_protocol = proto; |
274 | 268 | ||
275 | /* try to bypass using a DNS lookup if this is just an IP address */ | 269 | snprintf (port_str, sizeof (port_str), "%d", port); |
276 | if (!my_inet_aton (host_name, &servaddr.sin_addr)) { | 270 | result = getaddrinfo (host_name, port_str, &hints, &res); |
277 | |||
278 | /* else do a DNS lookup */ | ||
279 | hp = gethostbyname ((const char *) host_name); | ||
280 | if (hp == NULL) { | ||
281 | printf ("Invalid host name '%s'\n", host_name); | ||
282 | return STATE_UNKNOWN; | ||
283 | } | ||
284 | |||
285 | memcpy (&servaddr.sin_addr, hp->h_addr, hp->h_length); | ||
286 | } | ||
287 | |||
288 | /* map transport protocol name to protocol number */ | ||
289 | if ((ptrp = getprotobyname (proto)) == NULL) { | ||
290 | printf ("Cannot map \"%s\" to protocol number\n", proto); | ||
291 | return STATE_UNKNOWN; | ||
292 | } | ||
293 | 271 | ||
294 | /* create a socket */ | 272 | if (result != 0) { |
295 | *sd = | 273 | printf ("%s\n", gai_strerror (result)); |
296 | socket (PF_INET, (!strcmp (proto, "udp")) ? SOCK_DGRAM : SOCK_STREAM, | ||
297 | ptrp->p_proto); | ||
298 | if (*sd < 0) { | ||
299 | printf ("Socket creation failed\n"); | ||
300 | return STATE_UNKNOWN; | 274 | return STATE_UNKNOWN; |
301 | } | 275 | } |
276 | else { | ||
277 | while (res) { | ||
278 | /* attempt to create a socket */ | ||
279 | *sd = socket (res->ai_family, (proto == IPPROTO_UDP) ? | ||
280 | SOCK_DGRAM : SOCK_STREAM, res->ai_protocol); | ||
281 | |||
282 | if (*sd < 0) { | ||
283 | printf ("Socket creation failed\n"); | ||
284 | freeaddrinfo (res); | ||
285 | return STATE_UNKNOWN; | ||
286 | } | ||
302 | 287 | ||
303 | /* open a connection */ | 288 | /* attempt to open a connection */ |
304 | result = connect (*sd, (struct sockaddr *) &servaddr, sizeof (servaddr)); | 289 | result = connect (*sd, res->ai_addr, res->ai_addrlen); |
305 | if (result < 0) { | ||
306 | switch (errno) { | ||
307 | case ECONNREFUSED: | ||
308 | printf ("Connection refused by host\n"); | ||
309 | break; | ||
310 | case ETIMEDOUT: | ||
311 | printf ("Timeout while attempting connection\n"); | ||
312 | break; | ||
313 | case ENETUNREACH: | ||
314 | printf ("Network is unreachable\n"); | ||
315 | break; | ||
316 | default: | ||
317 | printf ("Connection refused or timed out\n"); | ||
318 | } | ||
319 | |||
320 | return STATE_CRITICAL; | ||
321 | } | ||
322 | |||
323 | return STATE_OK; | ||
324 | } | ||
325 | |||
326 | |||
327 | |||
328 | /* This code was taken from Fyodor's nmap utility, which was originally | ||
329 | taken from the GLIBC 2.0.6 libraries because Solaris doesn't contain | ||
330 | the inet_aton() funtion. */ | ||
331 | int | ||
332 | my_inet_aton (register const char *cp, struct in_addr *addr) | ||
333 | { | ||
334 | register unsigned int val; /* changed from u_long --david */ | ||
335 | register int base, n; | ||
336 | register char c; | ||
337 | u_int parts[4]; | ||
338 | register u_int *pp = parts; | ||
339 | |||
340 | c = *cp; | ||
341 | |||
342 | for (;;) { | ||
343 | |||
344 | /* | ||
345 | * Collect number up to ``.''. | ||
346 | * Values are specified as for C: | ||
347 | * 0x=hex, 0=octal, isdigit=decimal. | ||
348 | */ | ||
349 | if (!isdigit ((int) c)) | ||
350 | return (0); | ||
351 | val = 0; | ||
352 | base = 10; | ||
353 | |||
354 | if (c == '0') { | ||
355 | c = *++cp; | ||
356 | if (c == 'x' || c == 'X') | ||
357 | base = 16, c = *++cp; | ||
358 | else | ||
359 | base = 8; | ||
360 | } | ||
361 | 290 | ||
362 | for (;;) { | 291 | if (result == 0) |
363 | if (isascii ((int) c) && isdigit ((int) c)) { | ||
364 | val = (val * base) + (c - '0'); | ||
365 | c = *++cp; | ||
366 | } | ||
367 | else if (base == 16 && isascii ((int) c) && isxdigit ((int) c)) { | ||
368 | val = (val << 4) | (c + 10 - (islower ((int) c) ? 'a' : 'A')); | ||
369 | c = *++cp; | ||
370 | } | ||
371 | else | ||
372 | break; | 292 | break; |
373 | } | ||
374 | 293 | ||
375 | if (c == '.') { | 294 | close (*sd); |
376 | 295 | res = res->ai_next; | |
377 | /* | ||
378 | * Internet format: | ||
379 | * a.b.c.d | ||
380 | * a.b.c (with c treated as 16 bits) | ||
381 | * a.b (with b treated as 24 bits) | ||
382 | */ | ||
383 | if (pp >= parts + 3) | ||
384 | return (0); | ||
385 | *pp++ = val; | ||
386 | c = *++cp; | ||
387 | } | 296 | } |
388 | else | 297 | freeaddrinfo (res); |
389 | break; | ||
390 | } | 298 | } |
391 | 299 | ||
392 | /* Check for trailing characters */ | 300 | if (result == 0) |
393 | if (c != '\0' && (!isascii ((int) c) || !isspace ((int) c))) | 301 | return STATE_OK; |
394 | return (0); | 302 | else { |
395 | 303 | printf ("%s\n", strerror(errno)); | |
396 | /* Concoct the address according to the number of parts specified */ | 304 | return STATE_CRITICAL; |
397 | n = pp - parts + 1; | ||
398 | switch (n) { | ||
399 | |||
400 | case 0: | ||
401 | return (0); /* initial nondigit */ | ||
402 | |||
403 | case 1: /* a -- 32 bits */ | ||
404 | break; | ||
405 | |||
406 | case 2: /* a.b -- 8.24 bits */ | ||
407 | if (val > 0xffffff) | ||
408 | return (0); | ||
409 | val |= parts[0] << 24; | ||
410 | break; | ||
411 | |||
412 | case 3: /* a.b.c -- 8.8.16 bits */ | ||
413 | if (val > 0xffff) | ||
414 | return (0); | ||
415 | val |= (parts[0] << 24) | (parts[1] << 16); | ||
416 | break; | ||
417 | |||
418 | case 4: /* a.b.c.d -- 8.8.8.8 bits */ | ||
419 | if (val > 0xff) | ||
420 | return (0); | ||
421 | val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); | ||
422 | break; | ||
423 | } | 305 | } |
424 | |||
425 | if (addr) | ||
426 | addr->s_addr = htonl (val); | ||
427 | |||
428 | return (1); | ||
429 | } | 306 | } |