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 ****************************************************************************/
32 #include "common.h"
33 #include "netutils.h"
35 int socket_timeout = DEFAULT_SOCKET_TIMEOUT;
36 int econn_refuse_state = STATE_CRITICAL;
37 int was_refused = FALSE;
39 /* handles socket timeouts */
40 void
41 socket_timeout_alarm_handler (int sig)
42 {
44 printf ("CRITICAL - Socket timeout after %d seconds\n", socket_timeout);
46 exit (STATE_CRITICAL);
47 }
50 /* connects to a host on a specified TCP port, sends a string,
51 and gets a response */
52 int
53 process_tcp_request (char *server_address, int server_port,
54 char *send_buffer, char *recv_buffer, int recv_size)
55 {
56 int result;
58 result = process_request (server_address, server_port,
59 IPPROTO_TCP, send_buffer, recv_buffer, recv_size);
61 return result;
62 }
65 /* connects to a host on a specified UDP port, sends a string, and gets a
66 response */
67 int
68 process_udp_request (char *server_address, int server_port,
69 char *send_buffer, char *recv_buffer, int recv_size)
70 {
71 int result;
73 result = process_request (server_address, server_port,
74 IPPROTO_UDP, send_buffer, recv_buffer, recv_size);
76 return result;
77 }
81 /* connects to a host on a specified tcp port, sends a string, and gets a
82 response. loops on select-recv until timeout or eof to get all of a
83 multi-packet answer */
84 int
85 process_tcp_request2 (char *server_address, int server_port,
86 char *send_buffer, char *recv_buffer, int recv_size)
87 {
89 int result;
90 int send_result;
91 int recv_result;
92 int sd;
93 struct timeval tv;
94 fd_set readfds;
95 int recv_length = 0;
97 result = my_connect (server_address, server_port, &sd, IPPROTO_TCP);
98 if (result != STATE_OK)
99 return STATE_CRITICAL;
101 send_result = send (sd, send_buffer, strlen (send_buffer), 0);
102 if (send_result != strlen (send_buffer)) {
103 printf ("send() failed\n");
104 result = STATE_WARNING;
105 }
107 while (1) {
108 /* wait up to the number of seconds for socket timeout
109 minus one for data from the host */
110 tv.tv_sec = socket_timeout - 1;
111 tv.tv_usec = 0;
112 FD_ZERO (&readfds);
113 FD_SET (sd, &readfds);
114 select (sd + 1, &readfds, NULL, NULL, &tv);
116 /* make sure some data has arrived */
117 if (!FD_ISSET (sd, &readfds)) { /* it hasn't */
118 if (!recv_length) {
119 strcpy (recv_buffer, "");
120 printf ("No data was recieved from host!\n");
121 result = STATE_WARNING;
122 }
123 else { /* this one failed, but previous ones worked */
124 recv_buffer[recv_length] = 0;
125 }
126 break;
127 }
128 else { /* it has */
129 recv_result =
130 recv (sd, recv_buffer + recv_length,
131 recv_size - recv_length - 1, 0);
132 if (recv_result == -1) {
133 /* recv failed, bail out */
134 strcpy (recv_buffer + recv_length, "");
135 result = STATE_WARNING;
136 break;
137 }
138 else if (recv_result == 0) {
139 /* end of file ? */
140 recv_buffer[recv_length] = 0;
141 break;
142 }
143 else { /* we got data! */
144 recv_length += recv_result;
145 if (recv_length >= recv_size - 1) {
146 /* buffer full, we're done */
147 recv_buffer[recv_size - 1] = 0;
148 break;
149 }
150 }
151 }
152 /* end if(!FD_ISSET(sd,&readfds)) */
153 }
154 /* end while(1) */
156 close (sd);
157 return result;
158 }
160 /* connects to a host on a specified port, sends a string, and gets a
161 response */
162 int
163 process_request (char *server_address, int server_port, int proto,
164 char *send_buffer, char *recv_buffer, int recv_size)
165 {
166 int result;
167 int send_result;
168 int recv_result;
169 int sd;
170 struct timeval tv;
171 fd_set readfds;
173 result = STATE_OK;
175 result = my_connect (server_address, server_port, &sd, proto);
176 if (result != STATE_OK)
177 return STATE_CRITICAL;
179 send_result = send (sd, send_buffer, strlen (send_buffer), 0);
180 if (send_result != strlen (send_buffer)) {
181 printf ("send() failed\n");
182 result = STATE_WARNING;
183 }
185 /* wait up to the number of seconds for socket timeout minus one
186 for data from the host */
187 tv.tv_sec = socket_timeout - 1;
188 tv.tv_usec = 0;
189 FD_ZERO (&readfds);
190 FD_SET (sd, &readfds);
191 select (sd + 1, &readfds, NULL, NULL, &tv);
193 /* make sure some data has arrived */
194 if (!FD_ISSET (sd, &readfds)) {
195 strcpy (recv_buffer, "");
196 printf ("No data was recieved from host!\n");
197 result = STATE_WARNING;
198 }
200 else {
201 recv_result = recv (sd, recv_buffer, recv_size - 1, 0);
202 if (recv_result == -1) {
203 strcpy (recv_buffer, "");
204 if (proto != IPPROTO_TCP)
205 printf ("recv() failed\n");
206 result = STATE_WARNING;
207 }
208 else
209 recv_buffer[recv_result] = 0;
211 /* terminate returned string */
212 recv_buffer[recv_size - 1] = 0;
213 }
215 close (sd);
217 return result;
218 }
221 /* opens a connection to a remote host/tcp port */
222 int
223 my_tcp_connect (char *host_name, int port, int *sd)
224 {
225 int result;
227 result = my_connect (host_name, port, sd, IPPROTO_TCP);
229 return result;
230 }
233 /* opens a connection to a remote host/udp port */
234 int
235 my_udp_connect (char *host_name, int port, int *sd)
236 {
237 int result;
239 result = my_connect (host_name, port, sd, IPPROTO_UDP);
241 return result;
242 }
245 /* opens a tcp or udp connection to a remote host */
246 int
247 my_connect (char *host_name, int port, int *sd, int proto)
248 {
249 struct addrinfo hints;
250 struct addrinfo *res;
251 struct addrinfo *ptrp;
252 char port_str[6];
253 int result;
255 memset (&hints, 0, sizeof (hints));
256 hints.ai_family = PF_UNSPEC;
257 hints.ai_protocol = proto;
259 snprintf (port_str, sizeof (port_str), "%d", port);
260 result = getaddrinfo (host_name, port_str, &hints, &res);
262 if (result != 0) {
263 printf ("%s\n", gai_strerror (result));
264 return STATE_UNKNOWN;
265 }
266 else {
267 while (res) {
268 /* attempt to create a socket */
269 *sd = socket (res->ai_family, (proto == IPPROTO_UDP) ?
270 SOCK_DGRAM : SOCK_STREAM, res->ai_protocol);
272 if (*sd < 0) {
273 printf ("Socket creation failed\n");
274 freeaddrinfo (res);
275 return STATE_UNKNOWN;
276 }
278 /* attempt to open a connection */
279 result = connect (*sd, res->ai_addr, res->ai_addrlen);
281 if (result == 0) {
282 was_refused = FALSE;
283 break;
284 }
286 if (result < 0) {
287 switch (errno) {
288 case ECONNREFUSED:
289 switch (econn_refuse_state) {
290 case STATE_OK:
291 case STATE_WARNING:
292 was_refused = TRUE;
293 }
294 break;
295 }
296 }
298 close (*sd);
299 res = res->ai_next;
300 }
301 freeaddrinfo (res);
302 }
304 if (result == 0)
305 return STATE_OK;
306 else if (was_refused)
307 return econn_refuse_state;
308 else {
309 printf ("%s\n", strerror(errno));
310 return STATE_CRITICAL;
311 }
312 }
314 int
315 is_host (char *address)
316 {
317 if (is_addr (address) || is_hostname (address))
318 return (TRUE);
320 return (FALSE);
321 }
323 int
324 is_addr (char *address)
325 {
326 #ifdef USE_IPV6
327 if (is_inet_addr (address) || is_inet6_addr (address))
328 #else
329 if (is_inet_addr (address))
330 #endif
331 return (TRUE);
333 return (FALSE);
334 }
336 int
337 resolve_host_or_addr (char *address, int family)
338 {
339 struct addrinfo hints;
340 struct addrinfo *res;
341 int retval;
343 memset (&hints, 0, sizeof (hints));
344 hints.ai_family = family;
345 retval = getaddrinfo (address, NULL, &hints, &res);
347 if (retval != 0)
348 return FALSE;
349 else {
350 freeaddrinfo (res);
351 return TRUE;
352 }
353 }
355 int
356 is_inet_addr (char *address)
357 {
358 return resolve_host_or_addr (address, AF_INET);
359 }
361 #ifdef USE_IPV6
362 int
363 is_inet6_addr (char *address)
364 {
365 return resolve_host_or_addr (address, AF_INET6);
366 }
367 #endif
369 int
370 is_hostname (char *s1)
371 {
372 #ifdef USE_IPV6
373 return resolve_host_or_addr (s1, AF_UNSPEC);
374 #else
375 return resolve_host_or_addr (s1, AF_INET);
376 #endif
377 }