![]() |
Icinga-core 1.4.0
next gen monitoring
|
00001 /*************************************************************** 00002 * IO.C - IDO I/O Functions 00003 * 00004 * Copyright (c) 2005-2006 Ethan Galstad 00005 * Copyright (c) 2009-2011 Icinga Development Team (http://www.icinga.org) 00006 * 00007 * 00008 **************************************************************/ 00009 00010 #include "../../../include/config.h" 00011 #include "../include/common.h" 00012 #include "../include/io.h" 00013 00014 #ifdef HAVE_SSL 00015 SSL_METHOD *meth; 00016 SSL_CTX *ctx; 00017 SSL *ssl; 00018 int use_ssl=IDO_FALSE; 00019 #else 00020 int use_ssl=IDO_FALSE; 00021 #endif 00022 00023 00024 00025 /**************************************************************/ 00026 /****** MMAP()'ED FILE FUNCTIONS ******************************/ 00027 /**************************************************************/ 00028 00029 /* open a file read-only via mmap() */ 00030 ido_mmapfile *ido_mmap_fopen(char *filename){ 00031 ido_mmapfile *new_mmapfile; 00032 int fd; 00033 void *mmap_buf; 00034 struct stat statbuf; 00035 int mode=O_RDONLY; 00036 00037 /* allocate memory */ 00038 if((new_mmapfile=(ido_mmapfile *)malloc(sizeof(ido_mmapfile)))==NULL) 00039 return NULL; 00040 00041 /* open the file */ 00042 if((fd=open(filename,mode))==-1){ 00043 free(new_mmapfile); 00044 return NULL; 00045 } 00046 00047 /* get file info */ 00048 if((fstat(fd,&statbuf))==-1){ 00049 close(fd); 00050 free(new_mmapfile); 00051 return NULL; 00052 } 00053 00054 /* mmap() the file */ 00055 if((mmap_buf=(void *)mmap(0,statbuf.st_size,PROT_READ,MAP_PRIVATE,fd,0))==MAP_FAILED){ 00056 close(fd); 00057 free(new_mmapfile); 00058 return NULL; 00059 } 00060 00061 /* populate struct info for later use */ 00062 /*new_mmapfile->path=strdup(filename);*/ 00063 new_mmapfile->path=NULL; 00064 new_mmapfile->fd=fd; 00065 new_mmapfile->file_size=(unsigned long)(statbuf.st_size); 00066 new_mmapfile->current_position=0L; 00067 new_mmapfile->current_line=0L; 00068 new_mmapfile->mmap_buf=mmap_buf; 00069 00070 return new_mmapfile; 00071 } 00072 00073 00074 /* close a file originally opened via mmap() */ 00075 int ido_mmap_fclose(ido_mmapfile *temp_mmapfile){ 00076 00077 if(temp_mmapfile==NULL) 00078 return IDO_ERROR; 00079 00080 /* un-mmap() the file */ 00081 munmap(temp_mmapfile->mmap_buf,temp_mmapfile->file_size); 00082 00083 /* close the file */ 00084 close(temp_mmapfile->fd); 00085 00086 /* free memory */ 00087 if(temp_mmapfile->path!=NULL) 00088 free(temp_mmapfile->path); 00089 free(temp_mmapfile); 00090 00091 return IDO_OK; 00092 } 00093 00094 00095 /* gets one line of input from an mmap()'ed file */ 00096 char *ido_mmap_fgets(ido_mmapfile *temp_mmapfile){ 00097 char *buf=NULL; 00098 unsigned long x=0L; 00099 int len=0; 00100 00101 if(temp_mmapfile==NULL) 00102 return NULL; 00103 00104 /* we've reached the end of the file */ 00105 if(temp_mmapfile->current_position>=temp_mmapfile->file_size) 00106 return NULL; 00107 00108 /* find the end of the string (or buffer) */ 00109 for(x=temp_mmapfile->current_position;x<temp_mmapfile->file_size;x++){ 00110 if(*((char *)(temp_mmapfile->mmap_buf)+x)=='\n'){ 00111 x++; 00112 break; 00113 } 00114 } 00115 00116 /* calculate length of line we just read */ 00117 len=(int)(x-temp_mmapfile->current_position); 00118 00119 /* allocate memory for the new line */ 00120 if((buf=(char *)malloc(len+1))==NULL) 00121 return NULL; 00122 00123 /* copy string to newly allocated memory and terminate the string */ 00124 memcpy(buf,((char *)(temp_mmapfile->mmap_buf)+temp_mmapfile->current_position),len); 00125 buf[len]='\x0'; 00126 00127 /* update the current position */ 00128 temp_mmapfile->current_position=x; 00129 00130 /* increment the current line */ 00131 temp_mmapfile->current_line++; 00132 00133 return buf; 00134 } 00135 00136 00137 00138 00139 /**************************************************************/ 00140 /****** SOCKET FUNCTIONS **************************************/ 00141 /**************************************************************/ 00142 00143 00144 /* opens data sink */ 00145 int ido_sink_open(char *name, int fd, int type, int port, int flags, int *nfd){ 00146 struct sockaddr_un server_address_u; 00147 struct sockaddr_in server_address_i; 00148 struct hostent *hp=NULL; 00149 mode_t mode=S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; 00150 int newfd=0; 00151 #ifdef HAVE_SSL 00152 int rc=0; 00153 #endif 00154 00155 /* use file */ 00156 if(type==IDO_SINK_FILE){ 00157 if((newfd=open(name,flags,mode))==-1) 00158 return IDO_ERROR; 00159 } 00160 00161 /* use existing file descriptor */ 00162 else if(type==IDO_SINK_FD){ 00163 if(fd<0) 00164 return IDO_ERROR; 00165 else 00166 newfd=fd; 00167 } 00168 00169 /* we are sending output to a unix domain socket */ 00170 else if(type==IDO_SINK_UNIXSOCKET){ 00171 00172 if(name==NULL) 00173 return IDO_ERROR; 00174 00175 /* create a socket */ 00176 if(!(newfd=socket(PF_UNIX,SOCK_STREAM,0))) 00177 return IDO_ERROR; 00178 00179 /* copy the socket address/path */ 00180 strncpy(server_address_u.sun_path,name,sizeof(server_address_u.sun_path)); 00181 server_address_u.sun_family=AF_UNIX; 00182 00183 /* connect to the socket */ 00184 if((connect(newfd,(struct sockaddr *)&server_address_u,SUN_LEN(&server_address_u)))){ 00185 close(newfd); 00186 return IDO_ERROR; 00187 } 00188 } 00189 00190 /* we are sending output to a TCP socket */ 00191 else if(type==IDO_SINK_TCPSOCKET){ 00192 00193 if(name==NULL) 00194 return IDO_ERROR; 00195 00196 #ifdef HAVE_SSL 00197 if(use_ssl==IDO_TRUE){ 00198 SSL_library_init(); 00199 SSLeay_add_ssl_algorithms(); 00200 meth=SSLv23_client_method(); 00201 SSL_load_error_strings(); 00202 00203 if((ctx=SSL_CTX_new(meth))==NULL){ 00204 printf("IDOUtils: Error - could not create SSL context.\n"); 00205 return IDO_ERROR; 00206 } 00207 /* ADDED 01/19/2004 */ 00208 /* use only TLSv1 protocol */ 00209 SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); 00210 } 00211 #endif 00212 00213 /* clear the address */ 00214 bzero((char *)&server_address_i,sizeof(server_address_i)); 00215 00216 /* try to bypass using a DNS lookup if this is just an IP address */ 00217 if(!ido_inet_aton(name,&server_address_i.sin_addr)){ 00218 00219 /* else do a DNS lookup */ 00220 if((hp=gethostbyname((const char *)name))==NULL) 00221 return IDO_ERROR; 00222 00223 memcpy(&server_address_i.sin_addr,hp->h_addr,hp->h_length); 00224 } 00225 00226 /* create a socket */ 00227 if(!(newfd=socket(PF_INET,SOCK_STREAM,0))) 00228 return IDO_ERROR; 00229 00230 /* copy the host/ip address and port */ 00231 server_address_i.sin_family=AF_INET; 00232 server_address_i.sin_port=htons(port); 00233 00234 /* connect to the socket */ 00235 if((connect(newfd,(struct sockaddr *)&server_address_i,sizeof(server_address_i)))){ 00236 close(newfd); 00237 return IDO_ERROR; 00238 } 00239 00240 #ifdef HAVE_SSL 00241 if(use_ssl==IDO_TRUE){ 00242 if((ssl=SSL_new(ctx))!=NULL){ 00243 SSL_CTX_set_cipher_list(ctx,"ADH"); 00244 SSL_set_fd(ssl,newfd); 00245 if((rc=SSL_connect(ssl))!=1){ 00246 printf("Error - Could not complete SSL handshake.\n"); 00247 SSL_CTX_free(ctx); 00248 close(newfd); 00249 return IDO_ERROR; 00250 } 00251 } else { 00252 printf("IDOUtils: Error - Could not create SSL connection structure.\n"); 00253 return IDO_ERROR; 00254 } 00255 } 00256 #endif 00257 } 00258 00259 /* unknown sink type */ 00260 else 00261 return IDO_ERROR; 00262 00263 /* save the new file descriptor */ 00264 *nfd=newfd; 00265 00266 return IDO_OK; 00267 } 00268 00269 00270 /* writes to data sink */ 00271 int ido_sink_write(int fd, char *buf, int buflen){ 00272 int tbytes=0; 00273 int result=0; 00274 00275 if(buf==NULL) 00276 return IDO_ERROR; 00277 if(buflen<=0) 00278 return 0; 00279 00280 while(tbytes<buflen){ 00281 00282 /* try to write everything we have left */ 00283 #ifdef HAVE_SSL 00284 if (use_ssl == IDO_TRUE) 00285 result=SSL_write(ssl, buf+tbytes, buflen-tbytes); 00286 else 00287 #endif 00288 result=write(fd, buf+tbytes, buflen-tbytes); 00289 00290 /* some kind of error occurred */ 00291 if(result==-1){ 00292 00293 /* unless we encountered a recoverable error, bail out */ 00294 if(errno!=EAGAIN && errno!=EINTR) 00295 return IDO_ERROR; 00296 } 00297 00298 /* update the number of bytes we've written */ 00299 tbytes+=result; 00300 } 00301 00302 return tbytes; 00303 } 00304 00305 00306 /* writes a newline to data sink */ 00307 int ido_sink_write_newline(int fd){ 00308 00309 return ido_sink_write(fd,"\n",1); 00310 } 00311 00312 00313 /* flushes data sink */ 00314 int ido_sink_flush(int fd){ 00315 00316 /* flush sink */ 00317 fsync(fd); 00318 00319 return IDO_OK; 00320 } 00321 00322 00323 /* closes data sink */ 00324 int ido_sink_close(int fd){ 00325 00326 /* no need to close STDOUT */ 00327 if(fd==STDOUT_FILENO) 00328 return IDO_OK; 00329 00330 /* close the socket */ 00331 shutdown(fd,2); 00332 close(fd); 00333 00334 return IDO_OK; 00335 } 00336 00337 00338 /* This code was taken from Fyodor's nmap utility, which was originally taken from 00339 the GLIBC 2.0.6 libraries because Solaris doesn't contain the inet_aton() funtion. */ 00340 int ido_inet_aton(register const char *cp, struct in_addr *addr){ 00341 register unsigned int val; /* changed from u_long --david */ 00342 register int base, n; 00343 register char c; 00344 unsigned int parts[4]; 00345 register unsigned int *pp = parts; 00346 00347 c=*cp; 00348 00349 for(;;){ 00350 00351 /* 00352 * Collect number up to ``.''. 00353 * Values are specified as for C: 00354 * 0x=hex, 0=octal, isdigit=decimal. 00355 */ 00356 if (!isdigit((int)c)) 00357 return (0); 00358 val=0; 00359 base=10; 00360 00361 if(c=='0'){ 00362 c=*++cp; 00363 if(c=='x'||c=='X') 00364 base=16,c=*++cp; 00365 else 00366 base=8; 00367 } 00368 00369 for(;;){ 00370 if(isascii((int)c) && isdigit((int)c)){ 00371 val=(val*base)+(c -'0'); 00372 c=*++cp; 00373 } 00374 else if(base==16 && isascii((int)c) && isxdigit((int)c)){ 00375 val=(val<<4) | (c+10-(islower((int)c)?'a':'A')); 00376 c = *++cp; 00377 } 00378 else 00379 break; 00380 } 00381 00382 if(c=='.'){ 00383 00384 /* 00385 * Internet format: 00386 * a.b.c.d 00387 * a.b.c (with c treated as 16 bits) 00388 * a.b (with b treated as 24 bits) 00389 */ 00390 if(pp>=parts+3) 00391 return (0); 00392 *pp++=val; 00393 c=*++cp; 00394 } 00395 else 00396 break; 00397 } 00398 00399 /* Check for trailing characters */ 00400 if(c!='\0' && (!isascii((int)c) || !isspace((int)c))) 00401 return (0); 00402 00403 /* Concoct the address according to the number of parts specified */ 00404 n=pp-parts+1; 00405 switch(n){ 00406 00407 case 0: 00408 return (0); /* initial nondigit */ 00409 00410 case 1: /* a -- 32 bits */ 00411 break; 00412 00413 case 2: /* a.b -- 8.24 bits */ 00414 if(val>0xffffff) 00415 return (0); 00416 val|=parts[0]<<24; 00417 break; 00418 00419 case 3: /* a.b.c -- 8.8.16 bits */ 00420 if(val>0xffff) 00421 return (0); 00422 val|=(parts[0]<< 24) | (parts[1]<<16); 00423 break; 00424 00425 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 00426 if(val>0xff) 00427 return (0); 00428 val|=(parts[0]<<24) | (parts[1]<<16) | (parts[2]<<8); 00429 break; 00430 } 00431 00432 if(addr) 00433 addr->s_addr=htonl(val); 00434 00435 return (1); 00436 } 00437 00438 00439 /******************************************************************/ 00440 /************************ STRING FUNCTIONS ************************/ 00441 /******************************************************************/ 00442 00443 /* strip newline and carriage return characters from end of a string */ 00444 void ido_strip_buffer(char *buffer){ 00445 register int x; 00446 register int y; 00447 00448 if(buffer==NULL || buffer[0]=='\x0') 00449 return; 00450 00451 /* strip end of string */ 00452 y=(int)strlen(buffer); 00453 for(x=y-1;x>=0;x--){ 00454 if(buffer[x]=='\n' || buffer[x]=='\r' || buffer[x]==13) 00455 buffer[x]='\x0'; 00456 else 00457 break; 00458 } 00459 00460 return; 00461 } 00462 00463 00464 /* escape special characters in string */ 00465 char *ido_escape_buffer(char *buffer){ 00466 char *newbuf; 00467 register int x=0; 00468 register int y=0; 00469 register int len=0; 00470 00471 if(buffer==NULL) 00472 return NULL; 00473 00474 /* allocate memory for escaped string */ 00475 if((newbuf=(char *)malloc((strlen(buffer)*2)+1))==NULL) 00476 return NULL; 00477 00478 /* initialize string */ 00479 newbuf[0]='\x0'; 00480 00481 len=(int)strlen(buffer); 00482 for(x=0;x<len;x++){ 00483 if(buffer[x]=='\t'){ 00484 newbuf[y++]='\\'; 00485 newbuf[y++]='t'; 00486 } 00487 else if(buffer[x]=='\r'){ 00488 newbuf[y++]='\\'; 00489 newbuf[y++]='r'; 00490 } 00491 else if(buffer[x]=='\n'){ 00492 newbuf[y++]='\\'; 00493 newbuf[y++]='n'; 00494 } 00495 else if(buffer[x]=='\\'){ 00496 newbuf[y++]='\\'; 00497 newbuf[y++]='\\'; 00498 } 00499 else 00500 newbuf[y++]=buffer[x]; 00501 } 00502 00503 /* terminate new string */ 00504 newbuf[y++]='\x0'; 00505 00506 return newbuf; 00507 } 00508 00509 00510 /* unescape special characters in string */ 00511 char *ido_unescape_buffer(char *buffer){ 00512 register int x=0; 00513 register int y=0; 00514 register int len=0; 00515 00516 if(buffer==NULL) 00517 return NULL; 00518 00519 len=(int)strlen(buffer); 00520 for(x=0;x<len;x++){ 00521 if(buffer[x]=='\\'){ 00522 if(buffer[x+1]=='\t') 00523 buffer[y++]='\t'; 00524 else if(buffer[x+1]=='r') 00525 buffer[y++]='\r'; 00526 else if(buffer[x+1]=='n') 00527 buffer[y++]='\n'; 00528 else if(buffer[x+1]=='\\') 00529 buffer[y++]='\\'; 00530 else 00531 buffer[y++]=buffer[x+1]; 00532 x++; 00533 } 00534 else 00535 buffer[y++]=buffer[x]; 00536 } 00537 00538 /* terminate string */ 00539 buffer[y++]='\x0'; 00540 00541 return buffer; 00542 } 00543 00544