Code

standardize localization string
[nagiosplug.git] / plugins / netutils.c
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$
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 * $Id$
31 *
32 ****************************************************************************/
34 #include "common.h"
35 #include "netutils.h"
37 unsigned int socket_timeout = DEFAULT_SOCKET_TIMEOUT; 
38 int econn_refuse_state = STATE_CRITICAL;
39 int was_refused = FALSE;
40 int address_family = AF_UNSPEC;
42 static int my_connect(const char *address, int port, int *sd, int proto);
43 /* handles socket timeouts */
44 void
45 socket_timeout_alarm_handler (int sig)
46 {
47         if (sig == SIGALRM)
48                 printf ("CRITICAL - Socket timeout after %d seconds\n", socket_timeout);
49         else
50                 printf ("CRITICAL - Abnormal timeout after %d seconds\n", socket_timeout);
52         exit (STATE_CRITICAL);
53 }
56 /* connects to a host on a specified TCP port, sends a string,
57    and gets a response */
58 int
59 process_tcp_request (const char *server_address, int server_port,
60         const char *send_buffer, char *recv_buffer, int recv_size)
61 {
62         int result;
64         result = process_request (server_address, server_port,
65                         IPPROTO_TCP, send_buffer, recv_buffer, recv_size);
67         return result;
68 }
71 /* connects to a host on a specified UDP port, sends a string, and gets a
72     response */
73 int
74 process_udp_request (const char *server_address, int server_port,
75         const char *send_buffer, char *recv_buffer, int recv_size)
76 {
77         int result;
79         result = process_request (server_address, server_port,
80                         IPPROTO_UDP, send_buffer, recv_buffer, recv_size);
82         return result;
83 }
87 /* connects to a host on a specified tcp port, sends a string, and gets a 
88          response. loops on select-recv until timeout or eof to get all of a 
89          multi-packet answer */
90 int
91 process_tcp_request2 (const char *server_address, int server_port,
92         const char *send_buffer, char *recv_buffer, int recv_size)
93 {
95         int result;
96         int send_result;
97         int recv_result;
98         int sd;
99         struct timeval tv;
100         fd_set readfds;
101         int recv_length = 0;
103         result = my_connect (server_address, server_port, &sd, IPPROTO_TCP);
104         if (result != STATE_OK)
105                 return STATE_CRITICAL;
107         send_result = send (sd, send_buffer, strlen (send_buffer), 0);
108         if (send_result<0 || (size_t)send_result!=strlen(send_buffer)) {
109                 printf ("Send failed\n");
110                 result = STATE_WARNING;
111         }
113         while (1) {
114                 /* wait up to the number of seconds for socket timeout
115                    minus one for data from the host */
116                 tv.tv_sec = socket_timeout - 1;
117                 tv.tv_usec = 0;
118                 FD_ZERO (&readfds);
119                 FD_SET (sd, &readfds);
120                 select (sd + 1, &readfds, NULL, NULL, &tv);
122                 /* make sure some data has arrived */
123                 if (!FD_ISSET (sd, &readfds)) { /* it hasn't */
124                         if (!recv_length) {
125                                 strcpy (recv_buffer, "");
126                                 printf ("No data was received from host!\n");
127                                 result = STATE_WARNING;
128                         }
129                         else {                                                                          /* this one failed, but previous ones worked */
130                                 recv_buffer[recv_length] = 0;
131                         }
132                         break;
133                 }
134                 else {                                                                                  /* it has */
135                         recv_result =
136                                 recv (sd, recv_buffer + recv_length, 
137                                         (size_t)recv_size - recv_length - 1, 0);
138                         if (recv_result == -1) {
139                                 /* recv failed, bail out */
140                                 strcpy (recv_buffer + recv_length, "");
141                                 result = STATE_WARNING;
142                                 break;
143                         }
144                         else if (recv_result == 0) {
145                                 /* end of file ? */
146                                 recv_buffer[recv_length] = 0;
147                                 break;
148                         }
149                         else {                                                                          /* we got data! */
150                                 recv_length += recv_result;
151                                 if (recv_length >= recv_size - 1) {
152                                         /* buffer full, we're done */
153                                         recv_buffer[recv_size - 1] = 0;
154                                         break;
155                                 }
156                         }
157                 }
158                 /* end if(!FD_ISSET(sd,&readfds)) */
159         }
160         /* end while(1) */
162         close (sd);
163         return result;
166 /* connects to a host on a specified port, sends a string, and gets a 
167    response */
168 int
169 process_request (const char *server_address, int server_port, int proto,
170         const char *send_buffer, char *recv_buffer, int recv_size)
172         int result;
173         int sd;
175         result = STATE_OK;
177         result = my_connect (server_address, server_port, &sd, proto);
178         if (result != STATE_OK)
179                 return STATE_CRITICAL;
181         result = send_request (sd, proto, send_buffer, recv_buffer, recv_size);
183         close (sd);
185         return result;
189 /* opens a connection to a remote host/tcp port */
190 int
191 my_tcp_connect (const char *host_name, int port, int *sd)
193         int result;
195         result = my_connect (host_name, port, sd, IPPROTO_TCP);
197         return result;
201 /* opens a connection to a remote host/udp port */
202 int
203 my_udp_connect (const char *host_name, int port, int *sd)
205         int result;
207         result = my_connect (host_name, port, sd, IPPROTO_UDP);
209         return result;
213 /* opens a tcp or udp connection to a remote host */
214 static int
215 my_connect (const char *host_name, int port, int *sd, int proto)
217         struct addrinfo hints;
218         struct addrinfo *res, *res0;
219         char port_str[6];
220         int result;
222         memset (&hints, 0, sizeof (hints));
223         hints.ai_family = address_family;
224         hints.ai_protocol = proto;
225         hints.ai_socktype = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
227         snprintf (port_str, sizeof (port_str), "%d", port);
228         result = getaddrinfo (host_name, port_str, &hints, &res0);
230         if (result != 0) {
231                 printf ("%s\n", gai_strerror (result));
232                 return STATE_UNKNOWN;
233         }
234         else {
235                 res = res0;
236                 while (res) {
237                         /* attempt to create a socket */
238                         *sd = socket (res->ai_family, (proto == IPPROTO_UDP) ?
239                                       SOCK_DGRAM : SOCK_STREAM, res->ai_protocol);
241                         if (*sd < 0) {
242                                 printf ("Socket creation failed\n");
243                                 freeaddrinfo (res);
244                                 return STATE_UNKNOWN;
245                         }
247                         /* attempt to open a connection */
248                         result = connect (*sd, res->ai_addr, res->ai_addrlen);
250                         if (result == 0) {
251                                 was_refused = FALSE;
252                                 break;
253                         }
255                         if (result < 0) {
256                                 switch (errno) {
257                                 case ECONNREFUSED:
258                                         was_refused = TRUE;
259                                         break;
260                                 }
261                         }
263                         close (*sd);
264                         res = res->ai_next;
265                 }
266                 freeaddrinfo (res0);
267         }
269         if (result == 0)
270                 return STATE_OK;
271         else if (was_refused) {
272                 switch (econn_refuse_state) { /* a user-defined expected outcome */
273                 case STATE_OK:       
274                 case STATE_WARNING:  /* user wants WARN or OK on refusal */
275                         return econn_refuse_state;
276                         break;
277                 case STATE_CRITICAL: /* user did not set econn_refuse_state */
278                         printf ("%s\n", strerror(errno));
279                         return econn_refuse_state;
280                         break;
281                 default: /* it's a logic error if we do not end up in STATE_(OK|WARNING|CRITICAL) */
282                         return STATE_UNKNOWN;
283                         break;
284                 }
285         }
286         else {
287                 printf ("%s\n", strerror(errno));
288                 return STATE_CRITICAL;
289         }
293 int
294 send_tcp_request (int sd, const char *send_buffer, char *recv_buffer, int recv_size)
296         return send_request (sd, IPPROTO_TCP, send_buffer, recv_buffer, recv_size);
300 int
301 send_udp_request (int sd, const char *send_buffer, char *recv_buffer, int recv_size)
303         return send_request (sd, IPPROTO_UDP, send_buffer, recv_buffer, recv_size);
307 int
308 send_request (int sd, int proto, const char *send_buffer, char *recv_buffer, int recv_size)
310         int result = STATE_OK;
311         int send_result;
312         int recv_result;
313         struct timeval tv;
314         fd_set readfds;
316         send_result = send (sd, send_buffer, strlen (send_buffer), 0);
317         if (send_result<0 || (size_t)send_result!=strlen(send_buffer)) {
318                 printf ("Send failed\n");
319                 result = STATE_WARNING;
320         }
322         /* wait up to the number of seconds for socket timeout minus one 
323            for data from the host */
324         tv.tv_sec = socket_timeout - 1;
325         tv.tv_usec = 0;
326         FD_ZERO (&readfds);
327         FD_SET (sd, &readfds);
328         select (sd + 1, &readfds, NULL, NULL, &tv);
330         /* make sure some data has arrived */
331         if (!FD_ISSET (sd, &readfds)) {
332                 strcpy (recv_buffer, "");
333                 printf ("No data was received from host!\n");
334                 result = STATE_WARNING;
335         }
337         else {
338                 recv_result = recv (sd, recv_buffer, (size_t)recv_size - 1, 0);
339                 if (recv_result == -1) {
340                         strcpy (recv_buffer, "");
341                         if (proto != IPPROTO_TCP)
342                                 printf ("Receive failed\n");
343                         result = STATE_WARNING;
344                 }
345                 else
346                         recv_buffer[recv_result] = 0;
348                 /* die returned string */
349                 recv_buffer[recv_size - 1] = 0;
350         }
351         return result;
355 int
356 is_host (const char *address)
358         if (is_addr (address) || is_hostname (address))
359                 return (TRUE);
361         return (FALSE);
364 int
365 is_addr (const char *address)
367 #ifdef USE_IPV6
368         if (is_inet_addr (address) && address_family != AF_INET6)
369 #else
370         if (is_inet_addr (address))
371 #endif
372                 return (TRUE);
374 #ifdef USE_IPV6
375         if (is_inet6_addr (address) && address_family != AF_INET)
376                 return (TRUE);
377 #endif
379         return (FALSE);
382 int
383 resolve_host_or_addr (const char *address, int family)
385         struct addrinfo hints;
386         struct addrinfo *res;
387         int retval;
389         memset (&hints, 0, sizeof (hints));
390         hints.ai_family = family;
391         retval = getaddrinfo (address, NULL, &hints, &res);
393         if (retval != 0)
394                 return FALSE;
395         else {
396                 freeaddrinfo (res);
397                 return TRUE;
398         }
401 int
402 is_inet_addr (const char *address)
404         return resolve_host_or_addr (address, AF_INET);
407 #ifdef USE_IPV6
408 int
409 is_inet6_addr (const char *address)
411         return resolve_host_or_addr (address, AF_INET6);
413 #endif
415 int
416 is_hostname (const char *s1)
418 #ifdef USE_IPV6
419         return resolve_host_or_addr (s1, address_family);
420 #else
421         return resolve_host_or_addr (s1, AF_INET);
422 #endif