| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- /****************************************************************************
- *
- * UTILS.C - NRPE Utility Functions
- *
- * License: GPL
- * Copyright (c) 1999-2006 Ethan Galstad (nagios@nagios.org)
- *
- * Last Modified: 12-11-2006
- *
- * Description:
- *
- * This file contains common network functions used in nrpe and check_nrpe.
- *
- * License Information:
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************************/
- #include "../include/common.h"
- #include "../include/utils.h"
- #ifndef NI_MAXSERV
- #define NI_MAXSERV 32
- #endif
- #ifndef NI_MAXHOST
- #define NI_MAXHOST 1025
- #endif
- static unsigned long crc32_table[256];
- /* build the crc table - must be called before calculating the crc value */
- void generate_crc32_table(void){
- unsigned long crc, poly;
- int i, j;
- poly=0xEDB88320L;
- for(i=0;i<256;i++){
- crc=i;
- for(j=8;j>0;j--){
- if(crc & 1)
- crc=(crc>>1)^poly;
- else
- crc>>=1;
- }
- crc32_table[i]=crc;
- }
- return;
- }
- /* calculates the CRC 32 value for a buffer */
- unsigned long calculate_crc32(char *buffer, int buffer_size){
- register unsigned long crc;
- int this_char;
- int current_index;
- crc=0xFFFFFFFF;
- for(current_index=0;current_index<buffer_size;current_index++){
- this_char=(int)buffer[current_index];
- crc=((crc>>8) & 0x00FFFFFF) ^ crc32_table[(crc ^ this_char) & 0xFF];
- }
- return (crc ^ 0xFFFFFFFF);
- }
- /* fill a buffer with semi-random data */
- void randomize_buffer(char *buffer,int buffer_size){
- FILE *fp;
- int x;
- int seed;
- /**** FILL BUFFER WITH RANDOM ALPHA-NUMERIC CHARACTERS ****/
- /***************************************************************
- Only use alpha-numeric characters becase plugins usually
- only generate numbers and letters in their output. We
- want the buffer to contain the same set of characters as
- plugins, so its harder to distinguish where the real output
- ends and the rest of the buffer (padded randomly) starts.
- ***************************************************************/
- /* try to get seed value from /dev/urandom, as its a better source of entropy */
- fp=fopen("/dev/urandom","r");
- if(fp!=NULL){
- seed=fgetc(fp);
- fclose(fp);
- }
- /* else fallback to using the current time as the seed */
- else
- seed=(int)time(NULL);
- srand(seed);
- for(x=0;x<buffer_size;x++)
- buffer[x]=(int)'0'+(int)(72.0*rand()/(RAND_MAX+1.0));
- return;
- }
- /* opens a connection to a remote host */
- int my_connect(const char *host, struct sockaddr_storage * hostaddr, u_short port,
- int address_family, const char *bind_address){
- int gaierr;
- int sock = -1;
- char ntop[NI_MAXHOST], strport[NI_MAXSERV];
- struct addrinfo hints, *ai, *aitop;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = address_family;
- hints.ai_socktype = SOCK_STREAM;
- snprintf(strport, sizeof strport, "%u", port);
- if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
- fprintf(stderr,"Could not resolve hostname %.100s: %s\n", host,
- gai_strerror(gaierr));
- exit(1);
- }
- /*
- * Loop through addresses for this host, and try each one in
- * sequence until the connection succeeds.
- */
- for (ai = aitop; ai; ai = ai->ai_next) {
- if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue;
- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
- strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
- fprintf(stderr, "my_connect: getnameinfo failed\n");
- continue;
- }
- /* Create a socket for connecting. */
- sock = my_create_socket(ai, bind_address);
- if (sock < 0) {
- /* Any error is already output */
- continue;
- }
- if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
- /* Successful connection. */
- memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
- break;
- }
- else {
- fprintf(stderr,"connect to address %s port %s: %s\n", ntop, strport,
- strerror(errno));
- close(sock);
- sock = -1;
- }
- }
- freeaddrinfo(aitop);
- /* Return failure if we didn't get a successful connection. */
- if (sock == -1) {
- fprintf(stderr, "connect to host %s port %s: %s", host, strport,
- strerror(errno));
- return -1;
- }
- return sock;
- }
- /* Creates a socket for the connection. */
- int my_create_socket(struct addrinfo *ai, const char *bind_address) {
- int sock, gaierr;
- struct addrinfo hints, *res;
- sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (sock < 0) fprintf(stderr,"socket: %.100s\n", strerror(errno));
- /* Bind the socket to an alternative local IP address */
- if (bind_address == NULL) return sock;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = ai->ai_family;
- hints.ai_socktype = ai->ai_socktype;
- hints.ai_protocol = ai->ai_protocol;
- hints.ai_flags = AI_PASSIVE;
- gaierr = getaddrinfo(bind_address, NULL, &hints, &res);
- if(gaierr) {
- fprintf(stderr, "getaddrinfo: %s: %s\n", bind_address,
- gai_strerror(gaierr));
- close(sock);
- return -1;
- }
- if(bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
- fprintf(stderr, "bind: %s: %s\n", bind_address, strerror(errno));
- close(sock);
- freeaddrinfo(res);
- return -1;
- }
- freeaddrinfo(res);
- return sock;
- }
- void add_listen_addr(struct addrinfo **listen_addrs, int address_family,
- char *addr, int port) {
- struct addrinfo hints, *ai, *aitop;
- char strport[NI_MAXSERV];
- int gaierr;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = address_family;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
- snprintf(strport, sizeof strport, "%d", port);
- if((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
- syslog(LOG_ERR,"bad addr or host: %s (%s)\n", addr ? addr : "<NULL>",
- gai_strerror(gaierr));
- exit(1);
- }
- for(ai = aitop; ai->ai_next; ai = ai->ai_next);
- ai->ai_next = *listen_addrs;
- *listen_addrs = aitop;
- }
-
- void strip(char *buffer){
- int x;
- int index;
- for(x=strlen(buffer);x>=1;x--){
- index=x-1;
- if(buffer[index]==' ' || buffer[index]=='\r' || buffer[index]=='\n' || buffer[index]=='\t')
- buffer[index]='\x0';
- else
- break;
- }
- return;
- }
- /* sends all data - thanks to Beej's Guide to Network Programming */
- int sendall(int s, char *buf, int *len){
- int total=0;
- int bytesleft=*len;
- int n=0;
- /* send all the data */
- while(total<*len){
- /* send some data */
- n=send(s,buf+total,bytesleft,0);
- /* break on error */
- if(n==-1)
- break;
- /* apply bytes we sent */
- total+=n;
- bytesleft-=n;
- }
- /* return number of bytes actually send here */
- *len=total;
- /* return -1 on failure, 0 on success */
- return n==-1?-1:0;
- }
- /* receives all data - modelled after sendall() */
- int recvall(int s, char *buf, int *len, int timeout){
- int total=0;
- int bytesleft=*len;
- int n=0;
- time_t start_time;
- time_t current_time;
-
- /* clear the receive buffer */
- bzero(buf,*len);
- time(&start_time);
- /* receive all data */
- while(total<*len){
- /* receive some data */
- n=recv(s,buf+total,bytesleft,0);
- /* no data has arrived yet (non-blocking socket) */
- if(n==-1 && errno==EAGAIN){
- time(¤t_time);
- if(current_time-start_time>timeout)
- break;
- sleep(1);
- continue;
- }
- /* receive error or client disconnect */
- else if(n<=0)
- break;
- /* apply bytes we received */
- total+=n;
- bytesleft-=n;
- }
- /* return number of bytes actually received here */
- *len=total;
- /* return <=0 on failure, bytes received on success */
- return (n<=0)?n:total;
- }
- /* fixes compiler problems under Solaris, since strsep() isn't included */
- /* this code is taken from the glibc source */
- char *my_strsep (char **stringp, const char *delim){
- char *begin, *end;
- begin = *stringp;
- if (begin == NULL)
- return NULL;
- /* A frequent case is when the delimiter string contains only one
- character. Here we don't need to call the expensive `strpbrk'
- function and instead work using `strchr'. */
- if(delim[0]=='\0' || delim[1]=='\0'){
- char ch = delim[0];
- if(ch=='\0')
- end=NULL;
- else{
- if(*begin==ch)
- end=begin;
- else
- end=strchr(begin+1,ch);
- }
- }
- else
- /* Find the end of the token. */
- end = strpbrk (begin, delim);
- if(end){
- /* Terminate the token and set *STRINGP past NUL character. */
- *end++='\0';
- *stringp=end;
- }
- else
- /* No more delimiters; this is the last token. */
- *stringp=NULL;
- return begin;
- }
- int b64_decode(unsigned char *encoded)
- {
- static const char *b64 = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" };
- int i, j, l, padding = 0;
- unsigned char c[4], *outp = encoded;
- union {
- unsigned c3;
- struct {
- unsigned f1:6;
- unsigned f2:6;
- unsigned f3:6;
- unsigned f4:6;
- } fields;
- } enc;
- enc.c3 = 0;
- l = strlen((char*)encoded);
- for (i = 0; i < l; i += 4) {
- for (j = 0; j < 4; ++j) {
- if (encoded[i+j] == '=') {
- c[j] = 0;
- ++padding;
- } else if (encoded[i+j] >= 'A' && encoded[i+j] <= 'Z')
- c[j] = encoded[i+j] - 'A';
- else if (encoded[i+j] >= 'a' && encoded[i+j] <= 'z')
- c[j] = encoded[i+j] - 'a' + 26;
- else if (encoded[i+j] >= '0' && encoded[i+j] <= '9')
- c[j] = encoded[i+j] - '0' + 52;
- else if (encoded[i+j] == '+')
- c[j] = encoded[i+j] - '+' + 62;
- else
- c[j] = encoded[i+j] - '/' + 63;
- }
- enc.fields.f1 = c[3];
- enc.fields.f2 = c[2];
- enc.fields.f3 = c[1];
- enc.fields.f4 = c[0];
- *outp++ = (enc.c3 >> 16) & 0xff;
- *outp++ = (enc.c3 >> 8) & 0xff;
- *outp++ = (enc.c3) & 0xff;
- }
- *outp = '\0';
- return outp - encoded - padding;
- }
- /* show license */
- void display_license(void){
- printf("This program is released under the GPL (see below) with the additional\n");
- printf("exemption that compiling, linking, and/or using OpenSSL is allowed.\n\n");
- printf("This program is free software; you can redistribute it and/or modify\n");
- printf("it under the terms of the GNU General Public License as published by\n");
- printf("the Free Software Foundation; either version 2 of the License, or\n");
- printf("(at your option) any later version.\n\n");
- printf("This program is distributed in the hope that it will be useful,\n");
- printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
- printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
- printf("GNU General Public License for more details.\n\n");
- printf("You should have received a copy of the GNU General Public License\n");
- printf("along with this program; if not, write to the Free Software\n");
- printf("Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
- return;
- }
|