summaryrefslogtreecommitdiffstats
path: root/plugins/netutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/netutils.c')
-rw-r--r--plugins/netutils.c253
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);
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}