Back to index

nagios-nrpe  2.13
Defines | Functions | Variables
check_nrpe.c File Reference
#include "../include/common.h"
#include "../include/config.h"
#include "../include/utils.h"

Go to the source code of this file.

Defines

#define DEFAULT_NRPE_COMMAND   "_NRPE_CHECK" /* check version of NRPE daemon */

Functions

int process_arguments (int, char **)
void alarm_handler (int)
int graceful_close (int, int)
int main (int argc, char **argv)

Variables

int server_port = DEFAULT_SERVER_PORT
char * server_name = NULL
char * command_name = NULL
int socket_timeout = DEFAULT_SOCKET_TIMEOUT
int timeout_return_code = STATE_CRITICAL
int sd
char query [MAX_INPUT_BUFFER] = ""
int show_help = FALSE
int show_license = FALSE
int show_version = FALSE
int use_ssl = FALSE

Define Documentation

#define DEFAULT_NRPE_COMMAND   "_NRPE_CHECK" /* check version of NRPE daemon */

Definition at line 25 of file check_nrpe.c.


Function Documentation

void alarm_handler ( int  sig)

Definition at line 423 of file check_nrpe.c.

                           {

       printf("CHECK_NRPE: Socket timeout after %d seconds.\n",socket_timeout);

       exit(timeout_return_code);
        }

Here is the caller graph for this function:

int graceful_close ( int  sd,
int  timeout 
)

Definition at line 432 of file check_nrpe.c.

                                       {
        fd_set in;
        struct timeval tv;
        char buf[1000];

       /* send FIN packet */
        shutdown(sd,SHUT_WR);  
        for(;;){

                FD_ZERO(&in);
                FD_SET(sd,&in);
                tv.tv_sec=timeout/1000;
                tv.tv_usec=(timeout % 1000)*1000;

              /* timeout or error */
                if(1!=select(sd+1,&in,NULL,NULL,&tv))
                     break;   

              /* no more data (FIN or RST) */
                if(0>=recv(sd,buf,sizeof(buf),0))
                     break;
              }

#ifdef HAVE_CLOSESOCKET
        closesocket(sd);
#else
       close(sd);
#endif

       return OK;
       }

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

Definition at line 57 of file check_nrpe.c.

                               {
        u_int32_t packet_crc32;
        u_int32_t calculated_crc32;
       int16_t result;
       int rc;
       packet send_packet;
       packet receive_packet;
       int bytes_to_send;
       int bytes_to_recv;

       result=process_arguments(argc,argv);

        if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){

              if(result!=OK)
                     printf("Incorrect command line arguments supplied\n");
                printf("\n");
              printf("NRPE Plugin for Nagios\n");
              printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n");
              printf("Version: %s\n",PROGRAM_VERSION);
              printf("Last Modified: %s\n",MODIFICATION_DATE);
              printf("License: GPL v2 with exemptions (-l for more info)\n");
#ifdef HAVE_SSL
              printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n");
#endif
              printf("\n");
               }

       if(result!=OK || show_help==TRUE){

              printf("Usage: check_nrpe -H <host> [-n] [-u] [-p <port>] [-t <timeout>] [-c <command>] [-a <arglist...>]\n");
              printf("\n");
              printf("Options:\n");
              printf(" -n         = Do no use SSL\n");
              printf(" -u         = Make socket timeouts return an UNKNOWN state instead of CRITICAL\n");
              printf(" <host>     = The address of the host running the NRPE daemon\n");
              printf(" [port]     = The port on which the daemon is running (default=%d)\n",DEFAULT_SERVER_PORT);
              printf(" [timeout]  = Number of seconds before connection times out (default=%d)\n",DEFAULT_SOCKET_TIMEOUT);
              printf(" [command]  = The name of the command that the remote daemon should run\n");
              printf(" [arglist]  = Optional arguments that should be passed to the command.  Multiple\n");
              printf("              arguments should be separated by a space.  If provided, this must be\n");
              printf("              the last option supplied on the command line.\n");
              printf("\n");
              printf("Note:\n");
              printf("This plugin requires that you have the NRPE daemon running on the remote host.\n");
              printf("You must also have configured the daemon to associate a specific plugin command\n");
              printf("with the [command] option you are specifying here.  Upon receipt of the\n");
              printf("[command] argument, the NRPE daemon will run the appropriate plugin command and\n");
              printf("send the plugin output and return code back to *this* plugin.  This allows you\n");
              printf("to execute plugins on remote hosts and 'fake' the results to make Nagios think\n");
              printf("the plugin is being run locally.\n");
              printf("\n");
               }

       if(show_license==TRUE)
              display_license();

        if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE)
              exit(STATE_UNKNOWN);


        /* generate the CRC 32 table */
        generate_crc32_table();

#ifdef HAVE_SSL
       /* initialize SSL */
       if(use_ssl==TRUE){
              SSL_library_init();
              SSLeay_add_ssl_algorithms();
              meth=SSLv23_client_method();
              SSL_load_error_strings();
              if((ctx=SSL_CTX_new(meth))==NULL){
                     printf("CHECK_NRPE: Error - could not create SSL context.\n");
                     exit(STATE_CRITICAL);
                      }

              /* ADDED 01/19/2004 */
              /* use only TLSv1 protocol */
              SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
                }
#endif

       /* initialize alarm signal handling */
       signal(SIGALRM,alarm_handler);

       /* set socket timeout */
       alarm(socket_timeout);

       /* try to connect to the host at the given port number */
       result=my_tcp_connect(server_name,server_port,&sd);

#ifdef HAVE_SSL
       /* do SSL handshake */
       if(result==STATE_OK && use_ssl==TRUE){
              if((ssl=SSL_new(ctx))!=NULL){
                     SSL_CTX_set_cipher_list(ctx,"ADH");
                     SSL_set_fd(ssl,sd);
                     if((rc=SSL_connect(ssl))!=1){
                            printf("CHECK_NRPE: Error - Could not complete SSL handshake.\n");
#ifdef DEBUG
                            printf("SSL_connect=%d\n",rc);
                            /*
                            rc=SSL_get_error(ssl,rc);
                            printf("SSL_get_error=%d\n",rc);
                            printf("ERR_get_error=%lu\n",ERR_get_error());
                            printf("%s\n",ERR_error_string(rc,NULL));
                            */
                            ERR_print_errors_fp(stdout);
#endif
                            result=STATE_CRITICAL;
                             }
                      }
              else{
                     printf("CHECK_NRPE: Error - Could not create SSL connection structure.\n");
                     result=STATE_CRITICAL;
                      }

              /* bail if we had errors */
              if(result!=STATE_OK){
                     SSL_CTX_free(ctx);
                     close(sd);
                     exit(result);
                      }
               }
#endif

       /* we're connected and ready to go */
       if(result==STATE_OK){

              /* clear the packet buffer */
              bzero(&send_packet,sizeof(send_packet));

              /* fill the packet with semi-random data */
              randomize_buffer((char *)&send_packet,sizeof(send_packet));

              /* initialize packet data */
              send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2);
              send_packet.packet_type=(int16_t)htons(QUERY_PACKET);
              strncpy(&send_packet.buffer[0],query,MAX_PACKETBUFFER_LENGTH);
              send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';

              /* calculate the crc 32 value of the packet */
              send_packet.crc32_value=(u_int32_t)0L;
              calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet));
              send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32);


              /***** ENCRYPT REQUEST *****/


              /* send the packet */
              bytes_to_send=sizeof(send_packet);
              if(use_ssl==FALSE)
                     rc=sendall(sd,(char *)&send_packet,&bytes_to_send);
#ifdef HAVE_SSL
              else{
                     rc=SSL_write(ssl,&send_packet,bytes_to_send);
                     if(rc<0)
                            rc=-1;
                      }
#endif
              if(rc==-1){
                     printf("CHECK_NRPE: Error sending query to host.\n");
                     close(sd);
                     return STATE_UNKNOWN;
                      }

              /* wait for the response packet */
              bytes_to_recv=sizeof(receive_packet);
              if(use_ssl==FALSE)
                     rc=recvall(sd,(char *)&receive_packet,&bytes_to_recv,socket_timeout);
#ifdef HAVE_SSL
              else
                     rc=SSL_read(ssl,&receive_packet,bytes_to_recv);
#endif

              /* reset timeout */
              alarm(0);

              /* close the connection */
#ifdef HAVE_SSL
              if(use_ssl==TRUE){
                     SSL_shutdown(ssl);
                     SSL_free(ssl);
                     SSL_CTX_free(ctx);
                       }
#endif
              graceful_close(sd,1000);

              /* recv() error */
              if(rc<0){
                     printf("CHECK_NRPE: Error receiving data from daemon.\n");
                     return STATE_UNKNOWN;
                      }

              /* server disconnected */
              else if(rc==0){
                     printf("CHECK_NRPE: Received 0 bytes from daemon.  Check the remote server logs for error messages.\n");
                     return STATE_UNKNOWN;
                      }

              /* receive underflow */
              else if(bytes_to_recv<sizeof(receive_packet)){
                     printf("CHECK_NRPE: Receive underflow - only %d bytes received (%d expected).\n",bytes_to_recv,sizeof(receive_packet));
                     return STATE_UNKNOWN;
                      }

              
              /***** DECRYPT RESPONSE *****/


              /* check the crc 32 value */
              packet_crc32=ntohl(receive_packet.crc32_value);
              receive_packet.crc32_value=0L;
              calculated_crc32=calculate_crc32((char *)&receive_packet,sizeof(receive_packet));
              if(packet_crc32!=calculated_crc32){
                     printf("CHECK_NRPE: Response packet had invalid CRC32.\n");
                     close(sd);
                     return STATE_UNKNOWN;
                        }
       
              /* check packet version */
              if(ntohs(receive_packet.packet_version)!=NRPE_PACKET_VERSION_2){
                     printf("CHECK_NRPE: Invalid packet version received from server.\n");
                     close(sd);
                     return STATE_UNKNOWN;
                     }

              /* check packet type */
              if(ntohs(receive_packet.packet_type)!=RESPONSE_PACKET){
                     printf("CHECK_NRPE: Invalid packet type received from server.\n");
                     close(sd);
                     return STATE_UNKNOWN;
                     }

              /* get the return code from the remote plugin */
              result=(int16_t)ntohs(receive_packet.result_code);

              /* print the output returned by the daemon */
              receive_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
              if(!strcmp(receive_packet.buffer,""))
                     printf("CHECK_NRPE: No output returned from daemon.\n");
              else
                     printf("%s\n",receive_packet.buffer);
               }

       /* reset the alarm */
       else
              alarm(0);

       return result;
        }

Here is the call graph for this function:

int process_arguments ( int  argc,
char **  argv 
)

Definition at line 313 of file check_nrpe.c.

                                            {
       char optchars[MAX_INPUT_BUFFER];
       int argindex=0;
       int c=1;
       int i=1;

#ifdef HAVE_GETOPT_LONG
       int option_index=0;
       static struct option long_options[]={
              {"host", required_argument, 0, 'H'},
              {"command", required_argument, 0, 'c'},
              {"args", required_argument, 0, 'a'},
              {"no-ssl", no_argument, 0, 'n'},
              {"unknown-timeout", no_argument, 0, 'u'},
              {"timeout", required_argument, 0, 't'},
              {"port", required_argument, 0, 'p'},
              {"help", no_argument, 0, 'h'},
              {"license", no_argument, 0, 'l'},
              {0, 0, 0, 0}
                };
#endif

       /* no options were supplied */
       if(argc<2)
              return ERROR;

       snprintf(optchars,MAX_INPUT_BUFFER,"H:c:a:t:p:nuhl");

       while(1){
#ifdef HAVE_GETOPT_LONG
              c=getopt_long(argc,argv,optchars,long_options,&option_index);
#else
              c=getopt(argc,argv,optchars);
#endif
              if(c==-1 || c==EOF)
                     break;

              /* process all arguments */
              switch(c){

              case '?':
              case 'h':
                     show_help=TRUE;
                     break;
              case 'V':
                     show_version=TRUE;
                     break;
              case 'l':
                     show_license=TRUE;
                     break;
              case 't':
                     socket_timeout=atoi(optarg);
                     if(socket_timeout<=0)
                            return ERROR;
                     break;
              case 'p':
                     server_port=atoi(optarg);
                     if(server_port<=0)
                            return ERROR;
                     break;
              case 'H':
                     server_name=strdup(optarg);
                     break;
              case 'c':
                     command_name=strdup(optarg);
                     break;
              case 'a':
                     argindex=optind;
                     break;
              case 'n':
                     use_ssl=FALSE;
                     break;
              case 'u':
                     timeout_return_code=STATE_UNKNOWN;
                     break;
              default:
                     return ERROR;
                     break;
                      }
               }

       /* determine (base) command query */
       snprintf(query,sizeof(query),"%s",(command_name==NULL)?DEFAULT_NRPE_COMMAND:command_name);
       query[sizeof(query)-1]='\x0';

       /* get the command args */
       if(argindex>0){

              for(c=argindex-1;c<argc;c++){

                     i=sizeof(query)-strlen(query)-2;
                     if(i<=0)
                            break;

                     strcat(query,"!");
                     strncat(query,argv[c],i);
                     query[sizeof(query)-1]='\x0';
                      }
               }

       /* make sure required args were supplied */
       if(server_name==NULL && show_help==FALSE && show_version==FALSE  && show_license==FALSE)
              return ERROR;


       return OK;
        }

Variable Documentation

char* command_name = NULL

Definition at line 29 of file check_nrpe.c.

char query[MAX_INPUT_BUFFER] = ""

Definition at line 34 of file check_nrpe.c.

int sd

Definition at line 32 of file check_nrpe.c.

char* server_name = NULL

Definition at line 28 of file check_nrpe.c.

int server_port = DEFAULT_SERVER_PORT

Definition at line 27 of file check_nrpe.c.

Definition at line 36 of file check_nrpe.c.

Definition at line 37 of file check_nrpe.c.

Definition at line 38 of file check_nrpe.c.

Definition at line 30 of file check_nrpe.c.

Definition at line 31 of file check_nrpe.c.

int use_ssl = FALSE

Definition at line 46 of file check_nrpe.c.