--- projects/cms/source/ihost/ihost.c 2002/05/20 12:28:46 1.17 +++ projects/cms/source/ihost/ihost.c 2005/09/24 13:30:40 1.53 @@ -1,6 +1,7 @@ /* * i-scream central monitoring system - * Copyright (C) 2000-2002 i-scream + * http://www.i-scream.org + * Copyright (C) 2000-2004 i-scream * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -17,518 +18,1381 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include -#include -#include -#include "ukcprog.h" -#include #include -#include "statgrab.h" -#include +#include +#include +#include +#ifndef WIN32 #include +#include #include -#include +#else +#include +#include +#endif +#include -#define versionNo 0.8 -#define RECONFIGURE_RETURN_CODE 2 -#define UDP_MAX_PACKET_SIZE 8192 +#include +#include +#define LOG_CRIT 0 +#define LOG_ERR 1 +#define LOG_INFO 2 +#define LOG_DEBUG 3 + +#define SERVICENAME "ihost" + +/* Windows printf does not understand %lld, so we have to use %I64d */ +#ifdef WIN32 +#define LLD "%I64d" +#define OPTSTRING "vVn:i:s:p:w:h" +#define SLEEP 10000 +#else +#define LLD "%lld" +#define OPTSTRING "vfVn:i:s:p:h" +#define SLEEP 10 +#endif + +/* The "socket" */ +#ifdef WIN32 +#define IHOST_SOCKET SOCKET +#define CLOSESOCKET(socket) closesocket(socket) +#else +#define IHOST_SOCKET FILE * +#define CLOSESOCKET(socket) fclose(socket) +#endif + typedef struct{ - int fm_port; - char *fm_host; + int filtermanager_port; + char *filtermanager_host; - char *my_ip; - char *my_fqdn; + char *host_ip; + char *host_fqdn; + int preset_fqdn; + int preset_ip; + char *server_fqdn; int server_udp_port; - int server_tcp_port; + + /* Weird stuff iscream wants sent to it */ char *last_modified; - char *files_list; - char *key; + char *file_list; + int udp_update_time; - int tcp_update_time; + time_t config_ttl; + }ihost_state_t; -char* sock_comm(FILE *f_r, FILE *f_w, char *sendString){ - char *reply; - fprintf(f_w, "%s\n", sendString); - fflush(f_w); - reply=fpgetline(f_r); - /* Returns pointer to static buffer */ - return reply; -} +typedef struct{ + int verbose; + int daemon; -int ihost_configure(ihost_state_t *ihost_state){ + FILE *log; +}ihost_config_t; + +typedef struct{ struct sockaddr_in addr; - struct in_addr haddr; - struct sockaddr ip; - int ip_len; - int sd; - FILE *fm_fd_r, *fm_fd_w; - char *reply; - char *reply_ptr; + int sock; +}udp_sockinfo_t; - /* Check to see if anything needs to be free'd */ - if (ihost_state->my_fqdn!=NULL) free(ihost_state->my_fqdn); - if (ihost_state->server_fqdn!=NULL) free(ihost_state->server_fqdn); - if (ihost_state->last_modified!=NULL) free(ihost_state->last_modified); - if (ihost_state->files_list!=NULL) free(ihost_state->files_list); +ihost_config_t ihost_config; +ihost_state_t ihost_state; - if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { - errf("Can't create AF_INET socket (%m)"); - return -1; - } +extern int errno; - if (get_host_addr(ihost_state->fm_host, &haddr) != 0){ - errf("Failed to resolve address %s (%m)", ihost_state->fm_host); - return -1; +#ifdef WIN32 +int run_server = 1; +int run_as_service = 0; +SERVICE_STATUS service_status; +SERVICE_STATUS_HANDLE hstatus; +#endif + +/* Taken from the OpenSSH code. Its licence included in function.*/ +#ifndef HAVE_STRLCAT + +/* + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(dst, src, siz) + char *dst; + const char *src; + size_t siz; +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; } + *d = '\0'; - memset(&addr, 0, sizeof addr); - addr.sin_family = AF_INET; - memcpy(&addr.sin_addr, &haddr, sizeof haddr); - addr.sin_port = htons(ihost_state->fm_port); + return(dlen + (s - src)); /* count does not include NUL */ +} - if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) { - errf("Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port); - return -1; +#endif +/* End strlcat function taken from OpenSSH */ + +void log_msg(int level, char *format, ...){ + int cur_errno; + va_list ap; + + cur_errno=errno; + + if(level<=ihost_config.verbose){ + va_start(ap, format); + vfprintf(ihost_config.log, format, ap); + va_end(ap); + if(level==LOG_CRIT){ + fprintf(ihost_config.log, " (%s)\n", strerror(cur_errno)); + }else{ + fprintf(ihost_config.log, "\n"); + } + fflush(ihost_config.log); } +} - /* Need to open 2 files, one for reading one for writing, as it gets confused if we only use 1 :) */ - if ((fm_fd_r=fdopen(sd,"r")) == NULL){ - errf("Failed to open read stream (%m)"); - return -1; +int create_udp_sockinfo(udp_sockinfo_t *udp_sockinfo, char *hostname, int port){ + + struct in_addr haddr; + + log_msg(LOG_DEBUG, "Resolving name for udp connection"); + if(get_host_addr(hostname, &haddr) != 0){ + log_msg(LOG_CRIT, "Failed to lookup name"); + return 1; } - if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){ - errf("Failed to open write stream (%m)"); - return -1; + if((udp_sockinfo->sock=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){ + log_msg(LOG_CRIT, "Failed to create UDP socket"); + return 1; } - ip_len=sizeof ip; - memset(&ip, 0, ip_len); - if((getsockname(sd, &ip, &ip_len)) != 0){ - errf("Failed to get IP address (%m)"); - return -1; + + memset(&(udp_sockinfo->addr), 0, sizeof(struct sockaddr_in)); + udp_sockinfo->addr.sin_family=AF_INET; + memcpy((char *)&(udp_sockinfo->addr.sin_addr), &haddr, sizeof(haddr)); + udp_sockinfo->addr.sin_port = htons(port); + + log_msg(LOG_DEBUG, "Socket created"); + return 0; +} + +IHOST_SOCKET create_tcp_connection(char *hostname, int port){ +#ifdef WIN32 + SOCKET sock; +#else + int sock; +#endif + struct sockaddr_in addr; + struct in_addr haddr; + FILE *f; + + log_msg(LOG_DEBUG, "Creating tcp socket"); + if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0){ + log_msg(LOG_CRIT, "Failed to make TCP Socket"); + goto out; } - if (ip.sa_family!=AF_INET){ - errf("sa family is wrong type"); - return -1; + + if((get_host_addr(hostname, &haddr))!=0){ + log_msg(LOG_CRIT, "Failed to lookup name for %s", hostname); + close(sock); + goto out; } - - if((ihost_state->my_ip=inet_ntoa(((struct sockaddr_in *)&ip)->sin_addr))==NULL){ - errf("Failed to get IP (%m)"); - return -1; - } - reply=sock_comm(fm_fd_r, fm_fd_w, "STARTCONFIG"); - if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) { - errf("Server error"); - return -1; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + memcpy(&addr.sin_addr, &haddr, sizeof(haddr)); + addr.sin_port = htons(port); + + log_msg(LOG_DEBUG, "Creating a tcp connection"); + if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) !=0){ + log_msg(LOG_CRIT, "Failed to connect to hostname %s on port %d", hostname, port); + close(sock); + goto out; } - reply=sock_comm(fm_fd_r, fm_fd_w, "LASTMODIFIED"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){ - errf("Server error (%m)"); - return -1; +#ifndef WIN32 +/* Windows does not treat sockets like this :( */ + if((f=fdopen(sock, "r+"))==NULL){ + log_msg(LOG_CRIT, "Failed to connect to open filedescriptor on tcp connection"); + close(sock); + return NULL; } - if((ihost_state->last_modified=strdup(reply)) == NULL){ - errf("strdup failed (%m)"); - return -1; - } + + return f; +#else + return sock; +#endif + +out: +#ifdef WIN32 + return 0; +#else + return NULL; +#endif +} + +#ifndef WIN32 +int tcp_comm(FILE *f, char *send, char **response, char *expected){ + + log_msg(LOG_DEBUG, "Sending %s", send); + fprintf(f, "%s\n", send); + fflush(f); + *response=fpgetline(f); + fseek(f, 0, SEEK_CUR); + + if(*response!=NULL) log_msg(LOG_DEBUG, "Received %s", *response); + + if( (*response==NULL) || (strcmp(*response, "ERROR")==0) ) return -1; + + if(expected==NULL) return 0; + + if((strcmp(expected, *response))==0) return 0; + + log_msg(LOG_DEBUG, "Did not get expected response"); + return -1; +} +#else +int tcp_comm(SOCKET soc, char *sendstr, char **response, char *expected) { + static char *rec = NULL; + char sendbuf[128]; + char recbuf[128]; + int bytesRecv; + char *tmp; - reply=sock_comm(fm_fd_r, fm_fd_w, "FILELIST"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){ - errf("Server error (%m)"); + sprintf(sendbuf, "%s\n", sendstr); + + log_msg(LOG_DEBUG, "Sending %s", sendstr); + send(soc, sendbuf, strlen(sendbuf), 0); + bytesRecv = recv(soc, recbuf, 128, 0); + + if(bytesRecv != 0 && bytesRecv != SOCKET_ERROR) { + /* remove \n and copy to a string */ + recbuf[bytesRecv-1] = '\0'; + tmp = realloc(rec, bytesRecv); + if(tmp == NULL) { + free(rec); + rec = NULL; + log_msg(LOG_CRIT, "out of memory"); + return -1; + } + rec = tmp; + rec = strcpy(rec, recbuf); + *response = rec; + log_msg(LOG_DEBUG, "Received %s", *response); + } else { return -1; } - if((ihost_state->files_list=strdup(reply)) == NULL){ - errf("strdup failed (%m)"); - return -1; - } + if(strcmp(*response, "ERROR")==0) return -1; - reply=sock_comm(fm_fd_r, fm_fd_w, "FQDN"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){ - errf("Server error (%m)"); + if(expected==NULL) return 0; + + if((strcmp(expected, *response))==0) return 0; + + log_msg(LOG_DEBUG, "Did not get expected response"); + return -1; +} +#endif /* WIN32 */ + +int tcp_comm_strdup(IHOST_SOCKET f, char *send, char **response, char *expected) +{ + if((tcp_comm(f, send, response, expected))!=0){ return -1; } - if((ihost_state->my_fqdn=strdup(reply)) == NULL){ - errf("strdup failed (%m)"); + + *response=strdup(*response); + if (response==NULL) return -1; + + return 0; +} + +int ihost_getconfig(ihost_state_t *ihost_state){ + IHOST_SOCKET tcp_con; + char *response; + char *response_ptr; + + /* Keep these in case of a failure and so it can keep running on the old config */ + char *file_list=NULL; + char *last_modified=NULL; + char *host_fqdn=NULL; + char *host_ip=NULL; + int udp_update_time=0; + char *server_fqdn=NULL; + int server_udp_port=0; + time_t config_ttl=0; + + if((tcp_con=create_tcp_connection(ihost_state->filtermanager_host, ihost_state->filtermanager_port)) +#ifndef WIN32 + ==NULL +#else + ==0 +#endif + ) { return -1; } - reply=sock_comm(fm_fd_r, fm_fd_w, "UDPUpdateTime"); - if(reply== NULL){ - errf("Server error (%m)"); - return -1; + if(ihost_state->file_list!=NULL || ihost_state->last_modified!=NULL){ +#ifndef WIN32 + if(tcp_con==NULL) +#else + if(tcp_con==0) +#endif + { + goto error; + } + + if((tcp_comm(tcp_con, "CHECKCONFIG", &response, "OK"))!=0){ + goto error; + } + + if((tcp_comm(tcp_con, ihost_state->file_list, &response, "OK"))!=0){ + goto error; + } + + if((tcp_comm(tcp_con, ihost_state->last_modified, &response, "OK"))==0){ + if((tcp_comm(tcp_con, "END", &response, "OK"))!=0){ + goto error; + } + CLOSESOCKET(tcp_con); + return 0; + }else{ + if((strcmp(response, "EXPIRED"))!=0){ + goto error; + } + } } - if (strncasecmp(reply, "ERROR", 5) != 0){ - ihost_state->udp_update_time=atoi(reply); + + /* If we got to here, the config must of expired */ + + if((tcp_comm(tcp_con, "STARTCONFIG", &response, "OK"))!=0){ + goto error; } - reply=sock_comm(fm_fd_r, fm_fd_w, "TCPUpdateTime"); - if(reply== NULL){ - errf("Server error (%m)"); - return -1; + if((tcp_comm_strdup(tcp_con, "LASTMODIFIED", &response, NULL))!=0){ + goto error; } - if (strncasecmp(reply, "ERROR", 5) != 0){ - ihost_state->tcp_update_time=atoi(reply); + last_modified=response; + + if((tcp_comm_strdup(tcp_con, "FILELIST", &response, NULL))!=0){ + goto error; } + file_list=response; - reply=sock_comm(fm_fd_r, fm_fd_w, "ENDCONFIG"); - if(reply== NULL){ - errf("Server error (%m)"); - return -1; + if((tcp_comm_strdup(tcp_con, "FQDN", &response, NULL))!=0){ + goto error; } + host_fqdn=response; - reply=sock_comm(fm_fd_r, fm_fd_w, "FILTER"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){ - errf("Server error FILTER failed (%m)"); - return -1; + if((tcp_comm_strdup(tcp_con, "IP", &response, NULL))!=0){ + goto error; } - reply_ptr=strchr(reply,';'); - if (reply_ptr==NULL){ - errf("Incorrect data returned"); - return -1; + host_ip=response; + + if((tcp_comm(tcp_con, "UDPUpdateTime", &response, NULL))!=0){ + goto error; } - *reply_ptr='\0'; - if((ihost_state->server_fqdn=strdup(reply)) == NULL){ - errf("strdup failed (%m)"); - return -1; + udp_update_time=atoi(response); + + if((tcp_comm(tcp_con, "ConfigTTL", &response, NULL))!=0){ + goto error; } - reply=reply_ptr + 1; - reply_ptr=strchr(reply,';'); - if (reply_ptr==NULL){ - errf("Incorrect data returned 2"); - return -1; + config_ttl=atoi(response); + + if((tcp_comm(tcp_con, "ENDCONFIG", &response, NULL))!=0){ + goto error; } - *reply_ptr='\0'; - ihost_state->server_udp_port=atoi(reply); - reply=reply_ptr+1; - ihost_state->server_tcp_port=atoi(reply); - if ((ihost_state->server_tcp_port==0) || (ihost_state->server_udp_port==0)){ - errf("Incorrect data returned 3 "); - return -1; + + if((tcp_comm(tcp_con, "FILTER", &response, NULL))!=0){ + goto error; + }else{ + response_ptr=strchr(response,';'); + if(response_ptr==NULL){ + log_msg(LOG_ERR, "Incorrect data sent by server"); + goto error; + } + *response_ptr='\0'; + server_fqdn=strdup(response); + if(server_fqdn==NULL){ + goto error; + } + response_ptr++; + if(response_ptr==NULL){ + log_msg(LOG_ERR, "Incorrect data sent by server"); + goto error; + } + + server_udp_port=atoi(response_ptr); + + if (server_udp_port==0){ + log_msg(LOG_ERR, "Incorrect data sent by server"); + goto error; + } } - reply=sock_comm(fm_fd_r, fm_fd_w, "END"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){ - errf("Server error (%m)"); - return -1; + if((tcp_comm(tcp_con, "END", &response, "OK"))!=0){ + goto error; } - if(fclose(fm_fd_r) !=0){ - errf("Failed to close read FD (%m)"); - return -1; + CLOSESOCKET(tcp_con); + + /* We have the data we need, and its all been read correctly */ + + /* Free the old data before pointing them to the new data. m_free copes should + * this already be NULL */ + if(ihost_state->file_list!=NULL) free(ihost_state->file_list); + if(ihost_state->last_modified!=NULL) free(ihost_state->last_modified); + if(ihost_state->server_fqdn!=NULL) free(ihost_state->server_fqdn); + + if(ihost_state->preset_fqdn){ + if(host_fqdn != NULL) free(host_fqdn); + }else{ + if(ihost_state->host_fqdn!=NULL) free(ihost_state->host_fqdn); + ihost_state->host_fqdn=host_fqdn; } - if(fclose(fm_fd_w) !=0){ - errf("Failed to close write FD (%m)"); - return -1; + + if(ihost_state->preset_ip){ + if(host_ip != NULL) free(host_ip); + }else{ + if(ihost_state->host_ip!=NULL) free(ihost_state->host_ip); + ihost_state->host_ip=host_ip; } + + ihost_state->file_list=file_list; + ihost_state->last_modified=last_modified; + ihost_state->server_fqdn=server_fqdn; + ihost_state->server_udp_port=server_udp_port; + ihost_state->udp_update_time=udp_update_time; + ihost_state->config_ttl=config_ttl; + + log_msg(LOG_DEBUG, "UDP Update time %d", udp_update_time); + log_msg(LOG_DEBUG, "Configure ttl %d", config_ttl); + return 0; + +error: + + if(file_list!=NULL) free(file_list); + if(last_modified!=NULL) free(last_modified); + if(host_fqdn!=NULL) free(host_fqdn); + if(server_fqdn!=NULL) free(server_fqdn); + if(host_ip!=NULL) free(host_ip); + CLOSESOCKET(tcp_con); + + return -1; } -int heartbeat(ihost_state_t *ihost_state){ - struct sockaddr_in addr; - struct in_addr haddr; - int sd; - FILE *fm_fd_r, *fm_fd_w; - char *reply; - int exitcode=0; +int get_system_stats(int seq_no, ihost_state_t *ihost_state, char *xml, int size){ + char tmp[size]; + sg_cpu_percents *cpu_percent; + sg_mem_stats *mem_stats; + sg_load_stats *load_stats; + sg_user_stats *user_stats; + sg_swap_stats *swap_stats; + sg_host_info *general_stats; + sg_fs_stats *disk_stats; + sg_disk_io_stats *diskio_stats; + sg_process_count *process_stats; + sg_network_io_stats *network_stats; + sg_page_stats *page_stats; + int disk_entries=0; + int diskio_entries=0; + int network_entries=0; - if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { - errf("Can't create AF_INET socket (%m)"); - return -1; - } + int counter; + long long x; + long long y; - if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){ - errf("Failed to resolve address %s (%m)", ihost_state->fm_host); - return -1; - } + /* Print start of the packet we want */ + snprintf(xml, size, "", \ + seq_no, ihost_state->host_fqdn, (long) time(NULL), ihost_state->host_ip); - memset(&addr, 0, sizeof addr); - addr.sin_family = AF_INET; - memcpy(&addr.sin_addr, &haddr, sizeof haddr); - addr.sin_port = htons(ihost_state->server_tcp_port); + /* Get cpu stats, check it is correct, then fill in its entry for the xml */ + if((cpu_percent=sg_get_cpu_percents())==NULL){ + log_msg(LOG_CRIT, "Failed to get cpu statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ + snprintf(tmp, size, \ + "%3.2f%3.2f%3.2f%3.2f%3.2f", \ + cpu_percent->user, \ + cpu_percent->kernel, \ + cpu_percent->idle, \ + cpu_percent->iowait, \ + cpu_percent->swap); - if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) { - errf("Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port); - return -1; - } + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + } - /* Need to open 2 files, one for reading one for writing, as it gets confused if we only use 1 :) */ - if ((fm_fd_r=fdopen(sd,"r")) == NULL){ - errf("Failed to open stream (%m)"); - return -1; - } - if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){ - errf("Failed to open stream (%m)"); - return -1; - } + /*Get mem stats, and fill in xml */ - reply=sock_comm(fm_fd_r, fm_fd_w, "HEARTBEAT"); - if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) { - errf("Server error"); - return -1; - } + if((mem_stats=sg_get_mem_stats())==NULL){ + log_msg(LOG_CRIT, "Failed to get memory statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ + snprintf(tmp, size, \ + ""LLD""LLD""LLD""LLD"", \ + mem_stats->total, \ + mem_stats->free, \ + mem_stats->used, \ + mem_stats->cache); - reply=sock_comm(fm_fd_r, fm_fd_w, "CONFIG"); - if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) { - errf("Server error"); - return -1; - } + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + } - reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->files_list); - if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) { - errf("Server error"); - return -1; - } - reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->last_modified); - if (reply==NULL) { - errf("Server error"); - return -1; - } - if (strncasecmp(reply, "ERROR", 5) == 0){ - /* Means the config has changed */ - exitcode=RECONFIGURE_RETURN_CODE; + /* Get load stats */ + + if((load_stats=sg_get_load_stats())==NULL){ + log_msg(LOG_CRIT, "Failed to get load statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ + snprintf(tmp, size, \ + "%.2lf%.2lf%.2lf", \ + load_stats->min1, \ + load_stats->min5, \ + load_stats->min15); + if(strlcat(xml, tmp, size) >= size) goto too_big_error; } - reply=sock_comm(fm_fd_r, fm_fd_w, "KEY"); - if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) { - errf("Server error"); - return -1; - } - if (ihost_state->key!=NULL) free(ihost_state->key); - - if((ihost_state->key=strdup(reply)) == NULL){ - errf("strdup failed (%m)"); - return -1; - } - reply=sock_comm(fm_fd_r, fm_fd_w, "ENDHEARTBEAT"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){ - errf("Server error (%m)"); - return -1; - } - fflush(fm_fd_r); - fflush(fm_fd_w); + /* get user stats */ - if(fclose(fm_fd_r) !=0){ - errf("Failed to close read FD (%m)"); - return -1; - } - if(fclose(fm_fd_w) !=0){ - errf("Failed to close write FD (%m)"); - return -1; - } + if((user_stats=sg_get_user_stats())==NULL){ + log_msg(LOG_CRIT, "Failed to get user statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ - return exitcode; -} + snprintf(tmp, size, \ + "%s%d", \ + user_stats->name_list, \ + user_stats->num_entries); -char *stat_grab(ihost_state_t *ihost_state, int counter){ -#define NUM_STATS 9 - char *stats[NUM_STATS]; - char *xml_data=NULL; - char *xml_data_p; - int x=0; - - stats[0]=get_cpu_stats(); - stats[1]=get_disk_stats(); - stats[2]=get_load_stats(); - stats[3]=get_memory_stats(); - stats[4]=get_os_info(); - stats[5]=get_page_stats(); - stats[6]=get_process_stats(); - stats[7]=get_swap_stats(); - stats[8]=get_user_stats(); + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + } - for(;x"LLD""LLD""LLD"",\ + swap_stats->total, \ + swap_stats->used, \ + swap_stats->free); + + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + } + + + /* general stats */ + + if((general_stats=sg_get_host_info())==NULL){ + log_msg(LOG_CRIT, "Failed to get host info statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ + snprintf(tmp, size, \ + "%s%s%s%s%s%ld", \ + general_stats->os_name, \ + general_stats->os_release, \ + general_stats->os_version, \ + general_stats->hostname, \ + general_stats->platform, \ + (long)general_stats->uptime); + + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + + } + + + /* process stats */ + + if((process_stats=sg_get_process_count())==NULL){ + log_msg(LOG_CRIT, "Failed to get process statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ + snprintf(tmp, size, \ + "%d%d%d%d%d",\ + process_stats->sleeping, \ + process_stats->running, \ + process_stats->zombie, \ + process_stats->stopped, \ + process_stats->total); + + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + + } + + + /* Get paging stats */ + + if((page_stats=sg_get_page_stats_diff())==NULL){ + log_msg(LOG_CRIT, "Failed to get paging statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ + if(page_stats->systime!=0){ + x=page_stats->pages_pagein / page_stats->systime; + y=page_stats->pages_pageout / page_stats->systime; + }else{ + x=page_stats->pages_pagein; + y=page_stats->pages_pageout; } - if(xml_data==NULL){ - if((xml_data=strf("%s", stats[x])) == NULL){ - errf("str failed (%m)"); - return NULL; + snprintf(tmp, size, \ + ""LLD""LLD"", \ + x, \ + y); + + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + } + + + /* get diskio stats */ + + if((diskio_stats=sg_get_disk_io_stats_diff(&diskio_entries))==NULL){ + log_msg(LOG_CRIT, "Failed to get disk io statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ + strlcat(xml, "", size); + for(counter=0;countersystime!=0){ + x=diskio_stats->read_bytes / diskio_stats->systime; + y=diskio_stats->write_bytes / diskio_stats->systime; + }else{ + x=diskio_stats->read_bytes; + y=diskio_stats->write_bytes; } - }else{ - xml_data_p=xml_data; - if((xml_data=strf("%s%s", xml_data, stats[x])) == NULL){ - errf("str failed (%m)"); - return NULL; + + snprintf(tmp, size, \ + "", \ + counter, \ + diskio_stats->disk_name, \ + x, \ + y, \ + counter); + + strlcat(xml, tmp, size); + diskio_stats++; + } + + if(strlcat(xml, "", size) >= size) goto too_big_error; + + } + + + /* get networks stats */ + + if((network_stats=sg_get_network_io_stats_diff(&network_entries))==NULL){ + log_msg(LOG_CRIT, "Failed to get network io statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ + strlcat(xml, "", size); + for(counter=0;countersystime!=0){ + x=network_stats->rx / network_stats->systime; + y=network_stats->tx / network_stats->systime; + }else{ + x=network_stats->rx; + y=network_stats->tx; } - free(xml_data_p); + + snprintf(tmp, size, \ + "", \ + counter, \ + network_stats->interface_name, \ + x, \ + y, \ + counter); + + strlcat(xml, tmp, size); + network_stats++; } - free(stats[x]); + + if(strlcat(xml, "", size) >= size) goto too_big_error; + } - xml_data_p=xml_data; - xml_data=strf("%s", counter, ihost_state->my_fqdn, time(NULL), ihost_state->my_ip, ihost_state->key, xml_data); - free(xml_data_p); - - return xml_data; + + + /* get disk stats */ + + if((disk_stats=sg_get_fs_stats(&disk_entries))==NULL){ + log_msg(LOG_CRIT, "Failed to get fs statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + }else{ + strlcat(xml, "", size); + for(counter=0;counter", \ + counter, \ + disk_stats->device_name, \ + disk_stats->mnt_point, \ + disk_stats->fs_type, \ + disk_stats->size, \ + disk_stats->used, \ + disk_stats->avail, \ + disk_stats->total_inodes, \ + disk_stats->used_inodes, \ + disk_stats->free_inodes, \ + counter); + + strlcat(xml, tmp, size); + + disk_stats++; + } + + if(strlcat(xml, "", size) >= size) goto too_big_error; + + } + + + if(strlcat(xml, "", size) >= size) goto too_big_error; + + /*If we got to here, it should of all been filled in nicely now */ + return 0; + +too_big_error: + log_msg(LOG_ERR, "UDP Packet is too large. Throwing away the packet"); + return -1; } -int send_stats(ihost_state_t *ihost_state, char *data_stream){ - struct sockaddr_in addr; - struct in_addr haddr; - int sd; - size_t len; - len=strlen(data_stream); - if(len>UDP_MAX_PACKET_SIZE){ - errf("Too big to send to server. Please reconfigure client and server and recompile"); - exit(1); +/* WIN32 NT service stuff */ +#ifdef WIN32 +void service_stopped() { + if(run_as_service) { + service_status.dwCurrentState = SERVICE_STOPPED; + service_status.dwWin32ExitCode = errno; + service_status.dwServiceSpecificExitCode = 0; + + SetServiceStatus(hstatus, &service_status); } - - if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){ - errf("Failed to resolve address %s (%m)", ihost_state->fm_host); - return -1; - } +} - if((sd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){ - errf("failed to create UDP socket (%m)"); - return -1; +void control_handler(DWORD request) { + switch(request) { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + service_status.dwWin32ExitCode = 0; + service_status.dwCurrentState = SERVICE_STOP_PENDING; + break; + default: + break; } - memset(&addr, 0, sizeof(addr)); - addr.sin_family=AF_INET; - memcpy((char *)&addr.sin_addr, &haddr, sizeof haddr); - addr.sin_port = htons(ihost_state->server_udp_port); + SetServiceStatus (hstatus, &service_status); +} - if((sendto(sd, data_stream, len, 0, (struct sockaddr *) &addr, sizeof(addr))) != len){ - errf("Send the wrong number of bytes (%m)"); - return -1; +/* attempt to tell service manager to start our service. + * return 0 on error, 1 on ok + */ +int start_service() { + SC_HANDLE scm; + SC_HANDLE service; + + // Open SCM + if((scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT)) == NULL) { + log_msg(LOG_CRIT, "Failed to open Service Control Manager"); + return 0; } + // Locate the service + if((service = OpenService(scm, SERVICENAME, SERVICE_START)) == NULL) { + log_msg(LOG_CRIT, "Unable to open the service"); + return 0; + } + // Start the service + if(StartService(service, 0, NULL) == 0) { + log_msg(LOG_CRIT, "Unable to start the service"); + return 0; + } + return 1; +} - close(sd); +int stop_service() { + SC_HANDLE scm; + SC_HANDLE service; + SERVICE_STATUS status; - return 0; + // Open SCM + if((scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT)) == NULL) { + log_msg(LOG_CRIT, "Failed to open Service Control Manager"); + return 0; + } + // Locate service + if((service = OpenService(scm, SERVICENAME, SERVICE_STOP)) == NULL) { + log_msg(LOG_CRIT, "Unable to open the service"); + return 0; + } + // Stop the service + if(!ControlService(service, SERVICE_CONTROL_STOP, &status)) { + log_msg(LOG_CRIT, "Unable to stop the service"); + return 0; + } + return 1; } +int register_service(int argc, char **argv) { + char path[MAX_PATH]; + int cmdline_len; + int i; + char *cmdline; + char *tmp; + SC_HANDLE scm; + + if(!GetModuleFileName(NULL, path, MAX_PATH)) { + log_msg(LOG_CRIT, "GetModuleFileName failed"); + return 0; + } + + // Calculate command line length + // 14 = 10 for " -w service", 2x quote around path and ending \0 + cmdline_len = strlen(path) + 14; + for (i=0; i.\n", PACKAGE_BUGREPORT); + exit(1); } -int main(int argc, char **argv){ - ihost_state_t ihost_state; - int heartbeat_exit; - int counter=0; - long udp_time=0, tcp_time=0, stat_grab_time=0, cur_time=0; - int sleep_delay=0; - char *xml_stats; +int run_ihost(){ + udp_sockinfo_t udp_sockinfo; + + pid_t pid; + FILE *f; + int packet_num=0; + int len; + + char packet[MAX_UDP_PACKET_SIZE]; + + time_t cur_time, sleep_delay, udp_time=0, config_time=0; +#ifdef WIN32 + int tries=0; + WSADATA wsaData; + + if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { + log_msg(LOG_CRIT, "Failed to init a winsock"); + service_stopped(); + exit(1); + } +#endif + + if(gethostbyname(ihost_state.filtermanager_host)==NULL){ + printf("%s\n", ihost_state.filtermanager_host); + log_msg(LOG_CRIT, "Failed to lookup hostname. Please check settings"); + goto out; + } + if(ihost_state.filtermanager_port==0){ + log_msg(LOG_ERR, "Invalid port number"); + goto out; + } + +#ifndef WIN32 + if(ihost_config.daemon){ + pid=fork(); + if(pid==-1){ + log_msg(LOG_CRIT, "Failed to background exiting"); + exit(1); + }else if(pid!=0){ + /* Parent process */ + return 0; + } + /* We should now be in the background*/ + if(setsid()==-1){ + log_msg(LOG_CRIT, "setsid failed"); + exit(1); + } + + if((ihost_config.log=fopen(LOG_FILE, "a"))==NULL){ + ihost_config.log=stderr; + log_msg(LOG_CRIT, "Failed to open Logfiles %s for writing", LOG_FILE); + exit(1); + } + + fclose(stdin); + fclose(stdout); + fclose(stderr); + + } +#endif + + log_msg(LOG_INFO, "Starting ihost..."); + + log_msg(LOG_DEBUG, "Running sg_init()"); + if(sg_init()){ + log_msg(LOG_CRIT, "sg_init failed: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + goto out; + } + if(sg_snapshot()) { + log_msg(LOG_ERR, "sg_snapshot failed: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + } + +#ifndef WIN32 + log_msg(LOG_DEBUG,"Writing PID FILE"); + + pid=getpid(); + + if((f=fopen(PID_FILE,"w")) == NULL){ + log_msg(LOG_CRIT, "Failed to write PID file"); + }else{ + if((fprintf(f,"%d",(int)pid)) <= 0 ){ + log_msg(LOG_CRIT, "Failed to write PID file"); + } + if((fclose(f))!=0){ + log_msg(LOG_CRIT, "failed to close PID file"); + } + } +#endif + + /* Get the initial config from the filter manager. Should this fail, + * wait, and then try again. */ + /* Win32 - for a max of one minute */ + + sg_get_disk_io_stats_diff(&packet_num); + packet_num=0; + + while(ihost_getconfig(&ihost_state)!=0 +#ifdef WIN32 + && (tries<6) +#endif + ){ + log_msg(LOG_ERR, "Failed to get ihost config"); + sleep(SLEEP); +#ifdef WIN32 + tries++; +#endif + } + +#ifdef WIN32 + if (tries == 6) { + log_msg(LOG_ERR, "Giving up"); + goto out; + } + tries = 0; +#endif + + while((create_udp_sockinfo(&udp_sockinfo, ihost_state.server_fqdn, ihost_state.server_udp_port))!=0 +#ifdef WIN32 + && (tries<6) +#endif + ){ + log_msg(LOG_ERR, "Failed to create udp socket"); + sleep(SLEEP); +#ifdef WIN32 + tries++; +#endif + } + +#ifdef WIN32 + if (tries == 6) { + log_msg(LOG_ERR, "Giving up"); + goto out; + } +#endif + + config_time=time(NULL)+ihost_state.config_ttl; + +#ifdef WIN32 + /* Finally, we have started successfully! + * We set state to running even for non-service calls so the while + * loop works. Bit of a hack ;) + */ + service_status.dwCurrentState = SERVICE_RUNNING; + if(run_as_service) { + SetServiceStatus(hstatus, &service_status); + } + printf("started\n"); +#endif + + /* Now have config.. collect data and send as often as required */ +#ifdef WIN32 + while(service_status.dwCurrentState == SERVICE_RUNNING) +#else + for(;;) +#endif + { + cur_time=time(NULL); + + if(cur_time>=udp_time){ + if(sg_snapshot()) { + log_msg(LOG_ERR, "sg_snapshot failed: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + continue; /* Could this get ugly? */ + } + if((get_system_stats(packet_num++, &ihost_state, packet, MAX_UDP_PACKET_SIZE))!=0){ + log_msg(LOG_ERR, "Failed to get system stats"); + } + + len=strlen(packet); + log_msg(LOG_DEBUG, "Packet size: %d\nPacket: %s\n", len, packet); + + if((sendto(udp_sockinfo.sock, packet, len, 0, (struct sockaddr *) &udp_sockinfo.addr, sizeof(udp_sockinfo.addr)))!=len){ + log_msg(LOG_CRIT, "Failed to send packet"); + } + udp_time=cur_time+ihost_state.udp_update_time; + log_msg(LOG_DEBUG, "Next packet should be sent on %d", udp_time); + } + + if(cur_time>=config_time){ + if(ihost_getconfig(&ihost_state)!=0){ + /* If we can't get the config, try again 5 minutes time */ + log_msg(LOG_ERR, "Failed to get config, try again 5 minutes time"); + config_time=time(NULL)+300; + }else{ + close(udp_sockinfo.sock); + + while((create_udp_sockinfo(&udp_sockinfo, ihost_state.server_fqdn, ihost_state.server_udp_port))!=0){ + log_msg(LOG_CRIT, "Failed to create udp socket"); + sleep(SLEEP); + } + + config_time=time(NULL)+ihost_state.config_ttl; + + log_msg(LOG_DEBUG, "Config expires on %d\n", ihost_state.config_ttl); + } + } + + sleep_delay=udp_time-time(NULL); + log_msg(LOG_DEBUG, "Sleeping for %d", sleep_delay); +#ifdef WIN32 + /* convert to millisecs */ + sleep_delay *= 1000; +#endif + if(sleep_delay>0) sleep(sleep_delay); + } + + if(sg_shutdown()) { + log_msg(LOG_ERR, "sg_shutdown failed: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + } + +#ifdef WIN32 + WSACleanup(); + if(run_as_service) { + service_status.dwWin32ExitCode = 0; + service_status.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(hstatus, &service_status); + } +#endif + log_msg(LOG_ERR, "ihost shutdown successfully"); + fclose(ihost_config.log); + + return(0); + +out: +#ifdef WIN32 + WSACleanup(); + service_stopped(); +#endif + exit(1); +} + +#ifdef WIN32 +int service_main(int argc, char **argv) { + int error; + + service_status.dwServiceType = SERVICE_WIN32; + service_status.dwCurrentState = SERVICE_START_PENDING; + service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_SHUTDOWN; + service_status.dwWin32ExitCode = 0; + service_status.dwServiceSpecificExitCode = 0; + service_status.dwCheckPoint = 0; + service_status.dwWaitHint = 0; + + hstatus = RegisterServiceCtrlHandler(SERVICENAME, + (LPHANDLER_FUNCTION)control_handler); + if(hstatus == (SERVICE_STATUS_HANDLE)0) { + log_msg(LOG_CRIT, "RegisterServiceCtrlHandle failed"); + return -1; + } + + return run_ihost(); +} + + +void parse_w(int argc, char **argv) { + if (strcasecmp(optarg, "start") == 0) { + log_msg(LOG_ERR, "Attempting to start service..."); + run_server = 0; + if(start_service()) + log_msg(LOG_ERR, "Service started"); + } else if (strcasecmp(optarg, "stop") == 0) { + log_msg(LOG_ERR, "Attempting to stop service..."); + run_server = 0; + if(stop_service()) + log_msg(LOG_ERR, "Service stopped"); + } else if (strcasecmp(optarg, "service") == 0) { + run_as_service = 1; + } else if (strcasecmp(optarg, "register") == 0) { + log_msg(LOG_ERR, "Attempting to register service..."); + run_server = 0; + int i = optind; + optind = argc; + /* Grab the remaining arguments and use each time the service + * is started */ + if (register_service(argc-i, &argv[i])) + log_msg(LOG_ERR, "Registered service successfully"); + } else if (strcasecmp(optarg, "unregister") == 0) { + log_msg(LOG_ERR, "Attempting to unregister service..."); + run_server = 0; + if(unregister_service()) + log_msg(LOG_ERR, "Unregistered service successfully"); + } else { + fprintf(stderr, "Unknown -w option\n"); + usage(argv[0]); + exit(1); + } +} +#endif + + +int main(int argc, char **argv){ int cmdopt; extern int optind; - int verbose=0, daemon=0, syslog=0 ; - - /* NULL'ify so i can tell if i need to free it or not */ - ihost_state.fm_host=NULL; - ihost_state.my_fqdn=NULL; - ihost_state.server_fqdn=NULL; - ihost_state.last_modified=NULL; - ihost_state.files_list=NULL; - ihost_state.key=NULL; - errf_set_progname(argv[0]); + /* Set default settings */ + ihost_config.verbose=1; + ihost_config.daemon=1; + /* Set all errors to go down stderr until told otherwise */ + ihost_config.log=stderr; - while((cmdopt=getopt(argc, argv, "vdshV")) != -1){ + /* Blank ihost_state to default settings */ + ihost_state.filtermanager_host=DEF_SERVER_NAME; + ihost_state.filtermanager_port=DEF_SERVER_PORT; + ihost_state.host_fqdn=NULL; + ihost_state.host_ip=NULL; + ihost_state.preset_fqdn = 0; + ihost_state.preset_ip = 0; + ihost_state.server_fqdn=NULL; + ihost_state.file_list=NULL; + ihost_state.last_modified=NULL; + + while((cmdopt=getopt(argc, argv, OPTSTRING)) != -1){ switch(cmdopt){ case 'v': - verbose++; + ihost_config.verbose++; break; - - case 'd': - daemon=1; + +#ifndef WIN32 + case 'f': + /* Force syslog logging since stderr will be closed in this case */ + ihost_config.daemon=0; break; - +#endif + + case 'V': + fprintf(stderr, "%s version %s\n", argv[0], VERSION); + break; + case 'n': + ihost_state.preset_fqdn = 1; + ihost_state.host_fqdn = strdup(optarg); + if(ihost_state.host_fqdn == NULL){ + fprintf(stderr, "Missing hostname\n"); + usage(argv[0]); + } + break; + case 'i': + /* Hmm.. Someone could set any string to be the IP, and it will let it */ + ihost_state.preset_ip = 1; + ihost_state.host_ip = strdup(optarg); + if(ihost_state.host_ip == NULL){ + fprintf(stderr, "Missing ip\n"); + usage(argv[0]); + } + break; + case 's': - syslog=1; + ihost_state.filtermanager_host=strdup(optarg); break; - - case 'h': - usage(argv[0]); + + case 'p': + ihost_state.filtermanager_port=atoi(optarg); break; - case 'V': - errf("%s version %f",argv[0], versionNo); + +#ifdef WIN32 + case 'w': + parse_w(argc, argv); break; +#endif + + case 'h': default: usage(argv[0]); exit(1); } } - if(argc!=optind+2){ - usage(argv[0]); - exit(1); - } - ihost_state.fm_host=argv[optind]; - ihost_state.fm_port=atoi(argv[optind+1]); - if(ihost_state.fm_port==0){ - errf("Invalid port number"); - usage(argv[0]); - } - printf("%s\n%d\n",ihost_state.fm_host, ihost_state.fm_port); - - if(ihost_configure(&ihost_state)!=0){ - errf("configure failed"); - /* Ok, ideally we prob should have 2 copies of the structure and carry on if this - happens.. But we dont :) (at the moment) */ - exit(1); - } - - for(;;){ - cur_time=time(NULL); - if(cur_time>=tcp_time){ - /*printf("sending TCP\n");*/ - heartbeat_exit=heartbeat(&ihost_state); - if(heartbeat_exit==RECONFIGURE_RETURN_CODE){ - /*errf("heartbeat needs to be reconfigured");*/ - ihost_configure(&ihost_state); - /* So udp doesn't wait til next sending before updating */ - udp_time=0; - } - if(heartbeat_exit==-1){ - errf("ah crap"); - exit(1); - } - tcp_time=time(NULL)+ihost_state.tcp_update_time; - } - - if(cur_time>=udp_time){ - /*printf("sending UDP\n");*/ - stat_grab_time=time(NULL); - if((xml_stats=stat_grab(&ihost_state, counter++)) == NULL){ - errf("Failed to get stats (%m)"); +#ifdef WIN32 + if (run_server) { + if(run_as_service) { + if((ihost_config.log=fopen(LOG_FILE, "a"))==NULL){ + ihost_config.log=stderr; + log_msg(LOG_CRIT, "Failed to open Logfiles %s for writing", LOG_FILE); exit(1); } - stat_grab_time=time(NULL)-stat_grab_time; - send_stats(&ihost_state, xml_stats); - free(xml_stats); - udp_time=time(NULL)+ihost_state.udp_update_time-stat_grab_time; + log_msg(LOG_ERR, "Starting Service-Mode i-host"); + SERVICE_TABLE_ENTRY service_table[2]; + service_table[0].lpServiceName = SERVICENAME; + service_table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main; + service_table[1].lpServiceName = NULL; + service_table[1].lpServiceProc = NULL; + return StartServiceCtrlDispatcher(service_table); + } else { + log_msg(LOG_ERR, "Starting User-Mode i-host"); + return run_ihost(); } - - if(tcp_time0) sleep(sleep_delay); } - return 0; +#else + return run_ihost(); +#endif } -