summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/netutils.c253
-rw-r--r--plugins/netutils.h.in17
-rw-r--r--plugins/utils.c72
-rw-r--r--plugins/utils.h.in4
4 files changed, 116 insertions, 230 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);
40int process_tcp_request2 (char *, int, char *, char *, int); 40int process_tcp_request2 (char *, int, char *, char *, int);
41int process_tcp_request (char *, int, char *, char *, int); 41int process_tcp_request (char *, int, char *, char *, int);
42int process_udp_request (char *, int, char *, char *, int); 42int process_udp_request (char *, int, char *, char *, int);
43int process_request (char *, int, char *, char *, char *, int); 43int process_request (char *, int, int, char *, char *, int);
44 44
45int my_tcp_connect (char *, int, int *); 45int my_tcp_connect (char *, int, int *);
46int my_udp_connect (char *, int, int *); 46int my_udp_connect (char *, int, int *);
47int my_connect (char *, int, int *, char *); 47int my_connect (char *, int, int *, int);
48
49int my_inet_aton (register const char *, struct in_addr *);
50 48
51/* handles socket timeouts */ 49/* handles socket timeouts */
52void 50void
53socket_timeout_alarm_handler (int sig) 51socket_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 */
64int 62int
65process_tcp_request (char *server_address, 63process_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 */
82int 77int
83process_udp_request (char *server_address, 78process_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 */
102int 94int
103process_tcp_request2 (char *server_address, 95process_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 */
175int 172int
176process_request (char *server_address, 173process_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
238my_tcp_connect (char *host_name, int port, int *sd) 233my_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
251my_udp_connect (char *host_name, int port, int *sd) 245my_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 */
263int 256int
264my_connect (char *host_name, int port, int *sd, char *proto) 257my_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. */
331int
332my_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}
diff --git a/plugins/netutils.h.in b/plugins/netutils.h.in
index 1907ab7..69cf278 100644
--- a/plugins/netutils.h.in
+++ b/plugins/netutils.h.in
@@ -34,6 +34,7 @@
34#undef HAVE_STRINGS_H 34#undef HAVE_STRINGS_H
35#undef HAVE_STRING_H 35#undef HAVE_STRING_H
36 36
37#include "config.h"
37#include "common.h" 38#include "common.h"
38#include <netinet/in.h> 39#include <netinet/in.h>
39#include <arpa/inet.h> 40#include <arpa/inet.h>
@@ -41,22 +42,16 @@
41void socket_timeout_alarm_handler (int); 42void socket_timeout_alarm_handler (int);
42 43
43int process_tcp_request2 (char *address, int port, char *sbuffer, 44int process_tcp_request2 (char *address, int port, char *sbuffer,
44 char *rbuffer, int rsize); 45 char *rbuffer, int rsize);
45int process_tcp_request (char *address, int port, char *sbuffer, 46int process_tcp_request (char *address, int port, char *sbuffer,
46 char *rbuffer, int rsize); 47 char *rbuffer, int rsize);
47int process_udp_request (char *address, int port, char *sbuffer, 48int process_udp_request (char *address, int port, char *sbuffer,
48 char *rbuffer, int rsize); 49 char *rbuffer, int rsize);
49int process_request (char *address, int port, char *proto, char *sbuffer, 50int process_request (char *address, int port, char *proto, char *sbuffer,
50 char *rbuffer, int rsize); 51 char *rbuffer, int rsize);
51 52
52int my_tcp_connect (char *address, int port, int *sd); 53int my_tcp_connect (char *address, int port, int *sd);
53int my_udp_connect (char *address, int port, int *sd); 54int my_udp_connect (char *address, int port, int *sd);
54int my_connect (char *address, int port, int *sd, char *proto); 55int my_connect (char *address, int port, int *sd, int proto);
55
56int my_inet_aton (register const char *cp, struct in_addr *addr);
57 56
58#ifndef DEFAULT_SOCKET_TIMEOUT
59#include "config.h"
60#include "common.h"
61#endif
62int socket_timeout = DEFAULT_SOCKET_TIMEOUT; 57int socket_timeout = DEFAULT_SOCKET_TIMEOUT;
diff --git a/plugins/utils.c b/plugins/utils.c
index aaa9fe5..0d25067 100644
--- a/plugins/utils.c
+++ b/plugins/utils.c
@@ -17,6 +17,8 @@
17#include <stdarg.h> 17#include <stdarg.h>
18#include <limits.h> 18#include <limits.h>
19 19
20#include <arpa/inet.h>
21
20extern int timeout_interval; 22extern int timeout_interval;
21extern const char *progname; 23extern const char *progname;
22 24
@@ -27,7 +29,10 @@ void terminate (int, const char *fmt, ...);
27RETSIGTYPE timeout_alarm_handler (int); 29RETSIGTYPE timeout_alarm_handler (int);
28 30
29int is_host (char *); 31int is_host (char *);
30int is_dotted_quad (char *); 32int is_addr (char *);
33int resolve_host_or_addr (char *, int);
34int is_inet_addr (char *);
35int is_inet6_addr (char *);
31int is_hostname (char *); 36int is_hostname (char *);
32 37
33int is_integer (char *); 38int is_integer (char *);
@@ -58,7 +63,7 @@ char *strpcat (char *dest, const char *src, const char *str);
58#define TXTBLK 128 63#define TXTBLK 128
59 64
60/* ************************************************************************** 65/* **************************************************************************
61 * max_state(STATE_x, STATE_y) 66 /* max_state(STATE_x, STATE_y)
62 * compares STATE_x to STATE_y and returns result based on the following 67 * compares STATE_x to STATE_y and returns result based on the following
63 * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL 68 * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
64 * 69 *
@@ -167,28 +172,50 @@ timeout_alarm_handler (int signo)
167int 172int
168is_host (char *address) 173is_host (char *address)
169{ 174{
170 if (is_dotted_quad (address) || is_hostname (address)) 175 if (is_addr (address) || is_hostname (address))
171 return (TRUE); 176 return (TRUE);
177
172 return (FALSE); 178 return (FALSE);
173} 179}
174 180
175int 181int
176is_dotted_quad (char *address) 182is_addr (char *address)
177{ 183{
178 int o1, o2, o3, o4; 184 if (is_inet_addr (address) || is_inet6_addr (address))
179 char c[1]; 185 return (TRUE);
180 186
181 if (!address) 187 return (FALSE);
182 return FALSE; 188}
183 189
184 if (sscanf (address, "%d.%d.%d.%d%c", &o1, &o2, &o3, &o4, c) != 4) 190int
185 return FALSE; 191resolve_host_or_addr (char *address, int family)
186 else if (o1 > 255 || o2 > 255 || o3 > 255 || o4 > 255) 192{
187 return FALSE; 193 struct addrinfo hints;
188 else if (o1 < 0 || o2 < 0 || o3 < 0 || o4 < 0) 194 struct addrinfo *res;
195 int retval;
196
197 memset (&hints, 0, sizeof (hints));
198 hints.ai_family = family;
199 retval = getaddrinfo (address, NULL, &hints, &res);
200
201 if (retval != 0)
189 return FALSE; 202 return FALSE;
190 else 203 else {
204 freeaddrinfo (res);
191 return TRUE; 205 return TRUE;
206 }
207}
208
209int
210is_inet_addr (char *address)
211{
212 return resolve_host_or_addr (address, AF_INET);
213}
214
215int
216is_inet6_addr (char *address)
217{
218 return resolve_host_or_addr (address, AF_INET6);
192} 219}
193 220
194/* from RFC-1035 221/* from RFC-1035
@@ -201,22 +228,7 @@ is_dotted_quad (char *address)
201int 228int
202is_hostname (char *s1) 229is_hostname (char *s1)
203{ 230{
204 if (!s1 || strlen (s1) > 63) { 231 return resolve_host_or_addr (s1, AF_UNSPEC);
205 return FALSE;
206 }
207 if (strcspn (s1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUWVXYZ0123456789-.") != 0) {
208 return FALSE;
209 }
210 if (strspn (s1, "0123456789-.") == 1) {
211 return FALSE;
212 }
213 while ((s1 = index (s1, '.'))) {
214 s1++;
215 if (strspn (s1, "0123456789-.") == 1) {
216 return FALSE;
217 }
218 }
219 return TRUE;
220} 232}
221 233
222int 234int
diff --git a/plugins/utils.h.in b/plugins/utils.h.in
index 317ec46..0d947f4 100644
--- a/plugins/utils.h.in
+++ b/plugins/utils.h.in
@@ -28,7 +28,9 @@ int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
28/* Test input types */ 28/* Test input types */
29 29
30int is_host (char *); 30int is_host (char *);
31int is_dotted_quad (char *); 31int is_addr (char *);
32int is_inet_addr (char *);
33int is_inet6_addr (char *);
32int is_hostname (char *); 34int is_hostname (char *);
33 35
34int is_integer (char *); 36int is_integer (char *);