--- projects/cms/source/ihost/ihost.c 2004/01/05 15:22:17 1.44 +++ projects/cms/source/ihost/ihost.c 2006/05/02 06:49:53 1.54 @@ -1,7 +1,7 @@ /* * i-scream central monitoring system * http://www.i-scream.org - * Copyright (C) 2000-2002 i-scream + * 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 @@ -27,20 +27,48 @@ #include #include #include -#include #include #include +#ifndef WIN32 +#include #include #include +#else +#include +#include +#endif +#include #include #include #define LOG_CRIT 0 #define LOG_ERR 1 -#define LOG_INFO 2 +#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 filtermanager_port; char *filtermanager_host; @@ -52,24 +80,23 @@ typedef struct{ char *server_fqdn; int server_udp_port; - + /* Weird stuff iscream wants sent to it */ char *last_modified; char *file_list; int udp_update_time; -// int config_ttl; time_t config_ttl; }ihost_state_t; typedef struct{ - int verbose; - int daemon; + int verbose; + int daemon; FILE *log; -}ihost_config_t; +}ihost_config_t; typedef struct{ struct sockaddr_in addr; @@ -77,9 +104,17 @@ typedef struct{ }udp_sockinfo_t; ihost_config_t ihost_config; +ihost_state_t ihost_state; extern int errno; +#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 @@ -119,33 +154,33 @@ extern int errno; */ size_t strlcat(dst, src, siz) - char *dst; - const char *src; - size_t 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; + 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; + /* 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'; + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; - return(dlen + (s - src)); /* count does not include NUL */ + return(dlen + (s - src)); /* count does not include NUL */ } #endif @@ -170,24 +205,6 @@ void log_msg(int level, char *format, ...){ } } -/* Takes many pointers, checks if they are NULL or not, and then free's them */ -/* Deprciated - and i only wrote it today! :) -void m_free(int num_pointers, ...){ - int x=0; - va_list ap; - void *p; - - va_start(ap, num_pointers); - for(;xfiltermanager_host, ihost_state->filtermanager_port))==NULL){ + if((tcp_con=create_tcp_connection(ihost_state->filtermanager_host, ihost_state->filtermanager_port)) +#ifndef WIN32 + ==NULL +#else + ==0 +#endif + ) { return -1; } if(ihost_state->file_list!=NULL || ihost_state->last_modified!=NULL){ - if(tcp_con==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; } - fclose(tcp_con); + CLOSESOCKET(tcp_con); return 0; }else{ if((strcmp(response, "EXPIRED"))!=0){ @@ -338,7 +424,7 @@ int ihost_getconfig(ihost_state_t *ihost_state){ goto error; } last_modified=response; - + if((tcp_comm_strdup(tcp_con, "FILELIST", &response, NULL))!=0){ goto error; } @@ -383,37 +469,36 @@ int ihost_getconfig(ihost_state_t *ihost_state){ } response_ptr++; if(response_ptr==NULL){ - log_msg(LOG_ERR, "Incorrect data sent by server"); - goto error; - } + log_msg(LOG_ERR, "Incorrect data sent by server"); + goto error; + } - /*printf("string : %s\n", response_ptr);*/ - server_udp_port=atoi(response_ptr); + server_udp_port=atoi(response_ptr); if (server_udp_port==0){ log_msg(LOG_ERR, "Incorrect data sent by server"); goto error; } } - + if((tcp_comm(tcp_con, "END", &response, "OK"))!=0){ goto error; } - fclose(tcp_con); + 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->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); + if(ihost_state->host_fqdn!=NULL) free(ihost_state->host_fqdn); ihost_state->host_fqdn=host_fqdn; } @@ -444,24 +529,24 @@ error: if(host_fqdn!=NULL) free(host_fqdn); if(server_fqdn!=NULL) free(server_fqdn); if(host_ip!=NULL) free(host_ip); - fclose(tcp_con); + CLOSESOCKET(tcp_con); return -1; } int get_system_stats(int seq_no, ihost_state_t *ihost_state, char *xml, int size){ char tmp[size]; - cpu_percent_t *cpu_percent; - mem_stat_t *mem_stats; - load_stat_t *load_stats; - user_stat_t *user_stats; - swap_stat_t *swap_stats; - general_stat_t *general_stats; - disk_stat_t *disk_stats; - diskio_stat_t *diskio_stats; - process_stat_t *process_stats; - network_stat_t *network_stats; - page_stat_t *page_stats; + 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; @@ -472,11 +557,12 @@ int get_system_stats(int seq_no, ihost_state_t *ihost_ /* Print start of the packet we want */ snprintf(xml, size, "", \ - seq_no, ihost_state->host_fqdn, time(NULL), ihost_state->host_ip); + seq_no, ihost_state->host_fqdn, (long) time(NULL), ihost_state->host_ip); /* Get cpu stats, check it is correct, then fill in its entry for the xml */ - if((cpu_percent=cpu_percent_usage())==NULL){ - log_msg(LOG_CRIT, "Failed to get cpu statistics"); + 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", \ @@ -489,25 +575,29 @@ int get_system_stats(int seq_no, ihost_state_t *ihost_ if(strlcat(xml, tmp, size) >= size) goto too_big_error; } - - /*Get mem stats, and fill in xml */ - if((mem_stats=get_memory_stats())==NULL){ - log_msg(LOG_CRIT, "Failed to get memory statistics"); + + /*Get mem stats, and fill in xml */ + + 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", \ + ""LLD""LLD""LLD""LLD"", \ mem_stats->total, \ mem_stats->free, \ mem_stats->used, \ mem_stats->cache); - + if(strlcat(xml, tmp, size) >= size) goto too_big_error; } - /* Get load stats */ - if((load_stats=get_load_stats())==NULL){ - log_msg(LOG_CRIT, "Failed to get load statistics"); + /* 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", \ @@ -519,38 +609,42 @@ int get_system_stats(int seq_no, ihost_state_t *ihost_ /* get user stats */ - - if((user_stats=get_user_stats())==NULL){ - log_msg(LOG_CRIT, "Failed to get user statistics"); + + 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{ snprintf(tmp, size, \ "%s%d", \ user_stats->name_list, \ user_stats->num_entries); - + if(strlcat(xml, tmp, size) >= size) goto too_big_error; } /* swap stats */ - if((swap_stats=get_swap_stats())==NULL){ - log_msg(LOG_CRIT, "Failed to get swap statistics"); + + if((swap_stats=sg_get_swap_stats())==NULL){ + log_msg(LOG_CRIT, "Failed to get swap statistics: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); }else{ snprintf(tmp, size, \ - "%lld%lld%lld",\ + ""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=get_general_stats())==NULL){ - log_msg(LOG_CRIT, "Failed to get general statistics"); + + 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", \ @@ -560,15 +654,17 @@ int get_system_stats(int seq_no, ihost_state_t *ihost_ 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=get_process_stats())==NULL){ - log_msg(LOG_CRIT, "Failed to get general statistics"); + + 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",\ @@ -584,8 +680,10 @@ int get_system_stats(int seq_no, ihost_state_t *ihost_ /* Get paging stats */ - if((page_stats=get_page_stats_diff())==NULL){ - log_msg(LOG_CRIT, "Failed to get paging statistics"); + + 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; @@ -595,18 +693,19 @@ int get_system_stats(int seq_no, ihost_state_t *ihost_ y=page_stats->pages_pageout; } snprintf(tmp, size, \ - "%lld%lld", \ + ""LLD""LLD"", \ x, \ y); - + if(strlcat(xml, tmp, size) >= size) goto too_big_error; } /* get diskio stats */ - - if((diskio_stats=get_diskio_stats_diff(&diskio_entries))==NULL){ - log_msg(LOG_CRIT, "Failed to get diskio statistics"); + + 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;counterwrite_bytes / diskio_stats->systime; }else{ x=diskio_stats->read_bytes; - y=diskio_stats->write_bytes; + y=diskio_stats->write_bytes; } - + snprintf(tmp, size, \ - "", \ + "", \ counter, \ diskio_stats->disk_name, \ x, \ @@ -635,11 +734,12 @@ int get_system_stats(int seq_no, ihost_state_t *ihost_ } - + /* get networks stats */ - - if((network_stats=get_network_stats_diff(&network_entries))==NULL){ - log_msg(LOG_CRIT, "Failed to get network statistics"); + + 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;counter", \ + "", \ counter, \ network_stats->interface_name, \ x, \ @@ -669,14 +769,16 @@ int get_system_stats(int seq_no, ihost_state_t *ihost_ /* get disk stats */ - - if((disk_stats=get_disk_stats(&disk_entries))==NULL){ - log_msg(LOG_CRIT, "Failed to get disk statistics"); + + 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;counterfs_type, "nfs") == 0) continue; snprintf(tmp, size, \ - "", \ + "", \ counter, \ disk_stats->device_name, \ disk_stats->mnt_point, \ @@ -697,8 +799,8 @@ int get_system_stats(int seq_no, ihost_state_t *ihost_ 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 */ @@ -710,30 +812,200 @@ too_big_error: } - + +/* 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); + } +} + +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; + } + + SetServiceStatus (hstatus, &service_status); +} + +/* 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; +} + +int stop_service() { + SC_HANDLE scm; + SC_HANDLE service; + SERVICE_STATUS status; + + // 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); + exit(1); } -int main(int argc, char **argv){ +int run_ihost(){ - ihost_state_t ihost_state; udp_sockinfo_t udp_sockinfo; - - int cmdopt; - extern int optind; + pid_t pid; FILE *f; int packet_num=0; @@ -742,169 +1014,175 @@ int main(int argc, char **argv){ 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; - /* 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; + if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { + log_msg(LOG_CRIT, "Failed to init a winsock"); + service_stopped(); + exit(1); + } +#endif - /* 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, "vfhVs:i:")) != -1){ - switch(cmdopt){ - case 'v': - ihost_config.verbose++; - break; - - case 'f': - /* Force syslog logging since stderr will be closed in this case */ - ihost_config.daemon=0; - break; - - 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': - ihost_state.filtermanager_host=strdup(optarg); - break; - - case 'p': - ihost_state.filtermanager_port=atoi(optarg); - break; - - case 'h': - default: - usage(argv[0]); - exit(1); - } - } - 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"); - exit(1); + goto out; } if(ihost_state.filtermanager_port==0){ log_msg(LOG_ERR, "Invalid port number"); - exit(1); + goto out; } +#ifndef WIN32 if(ihost_config.daemon){ pid=fork(); if(pid==-1){ log_msg(LOG_CRIT, "Failed to background exiting"); - exit(1); + 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); - } - + /* 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); + fclose(stdin); + fclose(stdout); + fclose(stderr); - } + } +#endif log_msg(LOG_INFO, "Starting ihost..."); - log_msg(LOG_DEBUG, "Running statgrab_init()"); - if(!statgrab_init()){ - log_msg(LOG_CRIT, "statgrab_init failed (%m)"); - exit(1); + 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; } - - log_msg(LOG_DEBUG,"Writing PID FILE"); + if(sg_snapshot()) { + log_msg(LOG_ERR, "sg_snapshot failed: %s (%s)", + sg_str_error(sg_get_error()), sg_get_error_arg()); + } - pid=getpid(); +#ifndef WIN32 + log_msg(LOG_DEBUG,"Writing PID FILE"); - 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"); - } - } + 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, + /* Get the initial config from the filter manager. Should this fail, * wait, and then try again. */ + /* Win32 - for a max of one minute */ - get_diskio_stats_diff(&packet_num); + sg_get_disk_io_stats_diff(&packet_num); packet_num=0; - while(ihost_getconfig(&ihost_state)!=0){ + while(ihost_getconfig(&ihost_state)!=0 +#ifdef WIN32 + && (tries<6) +#endif + ){ log_msg(LOG_ERR, "Failed to get ihost config"); - sleep(10); + sleep(SLEEP); +#ifdef WIN32 + tries++; +#endif } - /*printf("%s\n%d\n", ihost_state.server_fqdn, ihost_state.server_udp_port);*/ - while((create_udp_sockinfo(&udp_sockinfo, ihost_state.server_fqdn, ihost_state.server_udp_port))!=0){ - log_msg(LOG_ERR, "Failed to create udp socket"); - sleep(10); +#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 */ - for(;;){ +#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 */ @@ -913,9 +1191,9 @@ int main(int argc, char **argv){ }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(10); + 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; @@ -926,8 +1204,196 @@ int main(int argc, char **argv){ 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; + + /* 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; + + /* 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': + ihost_config.verbose++; + break; + +#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': + ihost_state.filtermanager_host=strdup(optarg); + break; + + case 'p': + ihost_state.filtermanager_port=atoi(optarg); + break; + +#ifdef WIN32 + case 'w': + parse_w(argc, argv); + break; +#endif + + case 'h': + default: + usage(argv[0]); + exit(1); + } + } + +#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); + } + 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(); + } + } +#else + return run_ihost(); +#endif }