~ubuntu-branches/ubuntu/precise/nagios-plugins/precise-proposed

« back to all changes in this revision

Viewing changes to plugins/netutils.c

  • Committer: Bazaar Package Importer
  • Author(s): Guido Trotter
  • Date: 2004-06-15 15:37:48 UTC
  • Revision ID: james.westby@ubuntu.com-20040615153748-pq7702qdzghqfcns
Tags: upstream-1.3.1.0
ImportĀ upstreamĀ versionĀ 1.3.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
*
 
3
* Nagios plugins network utilities
 
4
*
 
5
* License: GPL
 
6
* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
 
7
*
 
8
* Last Modified: $Date: 2002/02/28 06:42:59 $
 
9
*
 
10
* Description:
 
11
*
 
12
* This file contains commons functions used in many of the plugins.
 
13
*
 
14
* License Information:
 
15
*
 
16
* This program is free software; you can redistribute it and/or modify
 
17
* it under the terms of the GNU General Public License as published by
 
18
* the Free Software Foundation; either version 2 of the License, or
 
19
* (at your option) any later version.
 
20
*
 
21
* This program is distributed in the hope that it will be useful,
 
22
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
23
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
24
* GNU General Public License for more details.
 
25
*
 
26
* You should have received a copy of the GNU General Public License
 
27
* along with this program; if not, write to the Free Software
 
28
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
29
*
 
30
****************************************************************************/
 
31
 
 
32
#include "config.h"
 
33
#include "common.h"
 
34
#include <sys/socket.h>
 
35
#include <netinet/in.h>
 
36
#include <arpa/inet.h>
 
37
#include <netdb.h>
 
38
 
 
39
extern int socket_timeout;
 
40
RETSIGTYPE socket_timeout_alarm_handler (int);
 
41
 
 
42
int process_tcp_request2 (char *, int, char *, char *, int);
 
43
int process_tcp_request (char *, int, char *, char *, int);
 
44
int process_udp_request (char *, int, char *, char *, int);
 
45
int process_request (char *, int, char *, char *, char *, int);
 
46
 
 
47
int my_tcp_connect (char *, int, int *);
 
48
int my_udp_connect (char *, int, int *);
 
49
int my_connect (char *, int, int *, char *);
 
50
 
 
51
int my_inet_aton (register const char *, struct in_addr *);
 
52
 
 
53
/* handles socket timeouts */
 
54
void
 
55
socket_timeout_alarm_handler (int sig)
 
56
{
 
57
 
 
58
        printf ("Socket timeout after %d seconds\n", socket_timeout);
 
59
 
 
60
        exit (STATE_CRITICAL);
 
61
}
 
62
 
 
63
 
 
64
/* connects to a host on a specified TCP port, sends a string,
 
65
   and gets a response */
 
66
int
 
67
process_tcp_request (char *server_address,
 
68
                                                                                 int server_port,
 
69
                                                                                 char *send_buffer, char *recv_buffer, int recv_size)
 
70
{
 
71
        int result;
 
72
        char proto[4] = "tcp";
 
73
 
 
74
        result = process_request (server_address,
 
75
                                                                                                                server_port,
 
76
                                                                                                                proto, send_buffer, recv_buffer, recv_size);
 
77
 
 
78
        return result;
 
79
}
 
80
 
 
81
 
 
82
/* connects to a host on a specified UDP port, sends a string, and gets a
 
83
    response */
 
84
int
 
85
process_udp_request (char *server_address,
 
86
                                                                                 int server_port,
 
87
                                                                                 char *send_buffer, char *recv_buffer, int recv_size)
 
88
{
 
89
        int result;
 
90
        char proto[4] = "udp";
 
91
 
 
92
        result = process_request (server_address,
 
93
                                                                                                                server_port,
 
94
                                                                                                                proto, send_buffer, recv_buffer, recv_size);
 
95
 
 
96
        return result;
 
97
}
 
98
 
 
99
 
 
100
 
 
101
/* connects to a host on a specified tcp port, sends a string, and gets a 
 
102
         response. loops on select-recv until timeout or eof to get all of a 
 
103
         multi-packet answer */
 
104
int
 
105
process_tcp_request2 (char *server_address,
 
106
                                                                                        int server_port,
 
107
                                                                                        char *send_buffer, char *recv_buffer, int recv_size)
 
108
{
 
109
 
 
110
        int result;
 
111
        int send_result;
 
112
        int recv_result;
 
113
        int sd;
 
114
        struct timeval tv;
 
115
        fd_set readfds;
 
116
        int recv_length = 0;
 
117
 
 
118
        result = my_connect (server_address, server_port, &sd, "tcp");
 
119
        if (result != STATE_OK)
 
120
                return STATE_CRITICAL;
 
121
 
 
122
        send_result = send (sd, send_buffer, strlen (send_buffer), 0);
 
123
        if (send_result != strlen (send_buffer)) {
 
124
                printf ("send() failed\n");
 
125
                result = STATE_WARNING;
 
126
        }
 
127
 
 
128
        while (1) {
 
129
                /* wait up to the number of seconds for socket timeout
 
130
                   minus one for data from the host */
 
131
                tv.tv_sec = socket_timeout - 1;
 
132
                tv.tv_usec = 0;
 
133
                FD_ZERO (&readfds);
 
134
                FD_SET (sd, &readfds);
 
135
                select (sd + 1, &readfds, NULL, NULL, &tv);
 
136
 
 
137
                /* make sure some data has arrived */
 
138
                if (!FD_ISSET (sd, &readfds)) { /* it hasn't */
 
139
                        if (!recv_length) {
 
140
                                strcpy (recv_buffer, "");
 
141
                                printf ("No data was recieved from host!\n");
 
142
                                result = STATE_WARNING;
 
143
                        }
 
144
                        else {                                                                          /* this one failed, but previous ones worked */
 
145
                                recv_buffer[recv_length] = 0;
 
146
                        }
 
147
                        break;
 
148
                }
 
149
                else {                                                                                  /* it has */
 
150
                        recv_result =
 
151
                                recv (sd, recv_buffer + recv_length, recv_size - recv_length - 1, 0);
 
152
                        if (recv_result == -1) {        /* recv failed, bail out */
 
153
                                strcpy (recv_buffer + recv_length, "");
 
154
                                result = STATE_WARNING;
 
155
                                break;
 
156
                        }
 
157
                        else if (recv_result == 0) {    /* end of file ? */
 
158
                                recv_buffer[recv_length] = 0;
 
159
                                break;
 
160
                        }
 
161
                        else {                                                                          /* we got data! */
 
162
                                recv_length += recv_result;
 
163
                                if (recv_length >= recv_size - 1) {     /* buffer full, we're done */
 
164
                                        recv_buffer[recv_size - 1] = 0;
 
165
                                        break;
 
166
                                }
 
167
                        }
 
168
                }                                                                                                               /* end if(!FD_ISSET(sd,&readfds)) */
 
169
        }                                                                                                                       /* end while(1) */
 
170
 
 
171
        close (sd);
 
172
        return result;
 
173
}
 
174
 
 
175
/* connects to a host on a specified port, sends a string, and gets a 
 
176
   response */
 
177
int
 
178
process_request (char *server_address,
 
179
                                                                 int server_port,
 
180
                                                                 char *proto,
 
181
                                                                 char *send_buffer, char *recv_buffer, int recv_size)
 
182
{
 
183
        int result;
 
184
        int send_result;
 
185
        int recv_result;
 
186
        int sd;
 
187
        struct timeval tv;
 
188
        fd_set readfds;
 
189
 
 
190
        result = STATE_OK;
 
191
 
 
192
        result = my_connect (server_address, server_port, &sd, proto);
 
193
        if (result != STATE_OK)
 
194
                return STATE_CRITICAL;
 
195
 
 
196
        send_result = send (sd, send_buffer, strlen (send_buffer), 0);
 
197
        if (send_result != strlen (send_buffer)) {
 
198
                printf ("send() failed\n");
 
199
                result = STATE_WARNING;
 
200
        }
 
201
 
 
202
        /* wait up to the number of seconds for socket timeout minus one 
 
203
           for data from the host */
 
204
        tv.tv_sec = socket_timeout - 1;
 
205
        tv.tv_usec = 0;
 
206
        FD_ZERO (&readfds);
 
207
        FD_SET (sd, &readfds);
 
208
        select (sd + 1, &readfds, NULL, NULL, &tv);
 
209
 
 
210
        /* make sure some data has arrived */
 
211
        if (!FD_ISSET (sd, &readfds)) {
 
212
                strcpy (recv_buffer, "");
 
213
                printf ("No data was recieved from host!\n");
 
214
                result = STATE_WARNING;
 
215
        }
 
216
 
 
217
        else {
 
218
                recv_result = recv (sd, recv_buffer, recv_size - 1, 0);
 
219
                if (recv_result == -1) {
 
220
                        strcpy (recv_buffer, "");
 
221
                        if (!strcmp (proto, "tcp"))
 
222
                                printf ("recv() failed\n");
 
223
                        result = STATE_WARNING;
 
224
                }
 
225
                else
 
226
                        recv_buffer[recv_result] = 0;
 
227
 
 
228
                /* terminate returned string */
 
229
                recv_buffer[recv_size - 1] = 0;
 
230
        }
 
231
 
 
232
        close (sd);
 
233
 
 
234
        return result;
 
235
}
 
236
 
 
237
 
 
238
/* opens a connection to a remote host/tcp port */
 
239
int
 
240
my_tcp_connect (char *host_name, int port, int *sd)
 
241
{
 
242
        int result;
 
243
        char proto[4] = "tcp";
 
244
 
 
245
        result = my_connect (host_name, port, sd, proto);
 
246
 
 
247
        return result;
 
248
}
 
249
 
 
250
 
 
251
/* opens a connection to a remote host/udp port */
 
252
int
 
253
my_udp_connect (char *host_name, int port, int *sd)
 
254
{
 
255
        int result;
 
256
        char proto[4] = "udp";
 
257
 
 
258
        result = my_connect (host_name, port, sd, proto);
 
259
 
 
260
        return result;
 
261
}
 
262
 
 
263
 
 
264
/* opens a tcp or udp connection to a remote host */
 
265
int
 
266
my_connect (char *host_name, int port, int *sd, char *proto)
 
267
{
 
268
        struct sockaddr_in servaddr;
 
269
        struct hostent *hp;
 
270
        struct protoent *ptrp;
 
271
        int result;
 
272
 
 
273
        bzero ((char *) &servaddr, sizeof (servaddr));
 
274
        servaddr.sin_family = AF_INET;
 
275
        servaddr.sin_port = htons (port);
 
276
 
 
277
        /* try to bypass using a DNS lookup if this is just an IP address */
 
278
        if (!my_inet_aton (host_name, &servaddr.sin_addr)) {
 
279
 
 
280
                /* else do a DNS lookup */
 
281
                hp = gethostbyname ((const char *) host_name);
 
282
                if (hp == NULL) {
 
283
                        printf ("Invalid host name '%s'\n", host_name);
 
284
                        return STATE_UNKNOWN;
 
285
                }
 
286
 
 
287
                memcpy (&servaddr.sin_addr, hp->h_addr, hp->h_length);
 
288
        }
 
289
 
 
290
        /* map transport protocol name to protocol number */
 
291
        if ((ptrp = getprotobyname (proto)) == NULL) {
 
292
                printf ("Cannot map \"%s\" to protocol number\n", proto);
 
293
                return STATE_UNKNOWN;
 
294
        }
 
295
 
 
296
        /* create a socket */
 
297
        *sd =
 
298
                socket (PF_INET, (!strcmp (proto, "udp")) ? SOCK_DGRAM : SOCK_STREAM,
 
299
                                                ptrp->p_proto);
 
300
        if (*sd < 0) {
 
301
                printf ("Socket creation failed\n");
 
302
                return STATE_UNKNOWN;
 
303
        }
 
304
 
 
305
        /* open a connection */
 
306
        result = connect (*sd, (struct sockaddr *) &servaddr, sizeof (servaddr));
 
307
        if (result < 0) {
 
308
                switch (errno) {
 
309
                case ECONNREFUSED:
 
310
                        printf ("Connection refused by host\n");
 
311
                        break;
 
312
                case ETIMEDOUT:
 
313
                        printf ("Timeout while attempting connection\n");
 
314
                        break;
 
315
                case ENETUNREACH:
 
316
                        printf ("Network is unreachable\n");
 
317
                        break;
 
318
                default:
 
319
                        printf ("Connection refused or timed out\n");
 
320
                }
 
321
 
 
322
                return STATE_CRITICAL;
 
323
        }
 
324
 
 
325
        return STATE_OK;
 
326
}
 
327
 
 
328
 
 
329
 
 
330
/* This code was taken from Fyodor's nmap utility, which was originally
 
331
         taken from the GLIBC 2.0.6 libraries because Solaris doesn't contain
 
332
         the inet_aton() funtion. */
 
333
int
 
334
my_inet_aton (register const char *cp, struct in_addr *addr)
 
335
{
 
336
        register unsigned int val;              /* changed from u_long --david */
 
337
        register int base, n;
 
338
        register char c;
 
339
        u_int parts[4];
 
340
        register u_int *pp = parts;
 
341
 
 
342
        c = *cp;
 
343
 
 
344
        for (;;) {
 
345
 
 
346
                /*
 
347
                 * Collect number up to ``.''.
 
348
                 * Values are specified as for C:
 
349
                 * 0x=hex, 0=octal, isdigit=decimal.
 
350
                 */
 
351
                if (!isdigit ((int) c))
 
352
                        return (0);
 
353
                val = 0;
 
354
                base = 10;
 
355
 
 
356
                if (c == '0') {
 
357
                        c = *++cp;
 
358
                        if (c == 'x' || c == 'X')
 
359
                                base = 16, c = *++cp;
 
360
                        else
 
361
                                base = 8;
 
362
                }
 
363
 
 
364
                for (;;) {
 
365
                        if (isascii ((int) c) && isdigit ((int) c)) {
 
366
                                val = (val * base) + (c - '0');
 
367
                                c = *++cp;
 
368
                        }
 
369
                        else if (base == 16 && isascii ((int) c) && isxdigit ((int) c)) {
 
370
                                val = (val << 4) | (c + 10 - (islower ((int) c) ? 'a' : 'A'));
 
371
                                c = *++cp;
 
372
                        }
 
373
                        else
 
374
                                break;
 
375
                }
 
376
 
 
377
                if (c == '.') {
 
378
 
 
379
                        /*
 
380
                         * Internet format:
 
381
                         *  a.b.c.d
 
382
                         *  a.b.c (with c treated as 16 bits)
 
383
                         *  a.b (with b treated as 24 bits)
 
384
                         */
 
385
                        if (pp >= parts + 3)
 
386
                                return (0);
 
387
                        *pp++ = val;
 
388
                        c = *++cp;
 
389
                }
 
390
                else
 
391
                        break;
 
392
        }
 
393
 
 
394
        /* Check for trailing characters */
 
395
        if (c != '\0' && (!isascii ((int) c) || !isspace ((int) c)))
 
396
                return (0);
 
397
 
 
398
        /* Concoct the address according to the number of parts specified */
 
399
        n = pp - parts + 1;
 
400
        switch (n) {
 
401
 
 
402
        case 0:
 
403
                return (0);                                                                     /* initial nondigit */
 
404
 
 
405
        case 1:                                                                                 /* a -- 32 bits */
 
406
                break;
 
407
 
 
408
        case 2:                                                                                 /* a.b -- 8.24 bits */
 
409
                if (val > 0xffffff)
 
410
                        return (0);
 
411
                val |= parts[0] << 24;
 
412
                break;
 
413
 
 
414
        case 3:                                                                                 /* a.b.c -- 8.8.16 bits */
 
415
                if (val > 0xffff)
 
416
                        return (0);
 
417
                val |= (parts[0] << 24) | (parts[1] << 16);
 
418
                break;
 
419
 
 
420
        case 4:                                                                                 /* a.b.c.d -- 8.8.8.8 bits */
 
421
                if (val > 0xff)
 
422
                        return (0);
 
423
                val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
 
424
                break;
 
425
        }
 
426
 
 
427
        if (addr)
 
428
                addr->s_addr = htonl (val);
 
429
 
 
430
        return (1);
 
431
}