--- projects/cms/source/ihost/ihost.c 2002/05/29 23:03:53 1.27 +++ projects/cms/source/ihost/ihost.c 2003/03/03 12:18:35 1.28 @@ -24,622 +24,795 @@ #include #include -#include #include -#include -#include -#include "ukcprog.h" -#include #include -#include "statgrab.h" -#include +#include #include -#include -#include +#include +#include +#include -#define RECONFIGURE_RETURN_CODE 2 +#include +#include "statgrab.h" -#define logmessage(level, ...) do { cur_level = level; errf(__VA_ARGS__); } while (0) +#define LOG_CRIT 0 +#define LOG_ERR 1 +#define LOG_INFO 2 +#define LOG_DEBUG 3 +#define PID_FILE "/var/run/ihost.pid" +#define LOGFILE_PATH "/var/log/ihost.log" +#define VERSION ".03" + +#define MAX_UDP_PACKET_SIZE 8192 + 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; + 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; +// int config_ttl; + time_t config_ttl; + }ihost_state_t; -static int log_level; -static int cur_level; -static int syslog_logging; +typedef struct{ + int verbose; + int daemon; -void log_errors(const char *message){ - if(log_level>=cur_level){ - if (syslog_logging==1){ - syslog(cur_level, "%s\n", message); + FILE *log; +}ihost_config_t; + +typedef struct{ + struct sockaddr_in addr; + int sock; +}udp_sockinfo_t; + +ihost_config_t ihost_config; + +void log_msg(int level, char *format, ...){ + extern int errno; + 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(stderr, "%s\n", message); + fprintf(ihost_config.log, "\n"); } - } + } } -char* sock_comm(FILE *f_r, FILE *f_w, char *sendString){ - char *reply; - logmessage(LOG_DEBUG, "Sending %s",sendString); - fprintf(f_w, "%s\n", sendString); - fflush(f_w); - reply=fpgetline(f_r); - if (reply!=NULL) logmessage(LOG_DEBUG, "Received %s", reply); - /* Returns pointer to static buffer */ - return reply; -} +/* 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; -int ihost_configure(ihost_state_t *ihost_state){ - 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; + va_start(ap, num_pointers); + for(;xmy_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); +int create_udp_sockinfo(udp_sockinfo_t *udp_sockinfo, char *hostname, int port){ - logmessage(LOG_DEBUG, "Setting up configure socket to %s on port %d", ihost_state->fm_host, ihost_state->fm_port); - if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { - logmessage(LOG_ERR, "Can't create AF_INET socket (%m)"); - return -1; - } + struct in_addr haddr; - if (get_host_addr(ihost_state->fm_host, &haddr) != 0){ - logmessage(LOG_ERR, "Failed to resolve address %s (%m)", ihost_state->fm_host); - return -1; + 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; } - 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); + if((udp_sockinfo->sock=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){ + log_msg(LOG_CRIT, "Failed to create UDP socket"); + return 1; + } - if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) { - logmessage(LOG_ERR, "Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port); - 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; +} + +FILE *create_tcp_connection(char *hostname, int port){ + int sock; + 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"); + return NULL; } - /* 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){ - logmessage(LOG_ERR, "Failed to open read stream (%m)"); - return -1; + if((get_host_addr(hostname, &haddr))!=0){ + log_msg(LOG_CRIT, "Failed to lookup name for %s", hostname); + return NULL; } - if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){ - logmessage(LOG_ERR, "Failed to open write stream (%m)"); - 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); + return NULL; } - ip_len=sizeof ip; - memset(&ip, 0, ip_len); - if((getsockname(sd, &ip, &ip_len)) != 0){ - logmessage(LOG_ERR, "Failed to get IP address (%m)"); - return -1; + + if((f=fdopen(sock, "r+"))==NULL){ + log_msg(LOG_CRIT, "Failed to connect to open filedescriptor on tcp connection"); + close(sock); + return NULL; } - if (ip.sa_family!=AF_INET){ - logmessage(LOG_ERR, "sa family is wrong type"); - return -1; - } - if(ihost_state->my_ip!=NULL) free(ihost_state->my_ip); - if((ihost_state->my_ip=strdup(inet_ntoa(((struct sockaddr_in *)&ip)->sin_addr)))==NULL){ - logmessage(LOG_ERR, "Failed to get IP (%m)"); - return -1; - } + return f; +} + +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, "Recieved %s", *response); + + if( (*response==NULL) || (strcmp(*response, "ERROR")==0) ) return -1; - reply=sock_comm(fm_fd_r, fm_fd_w, "STARTCONFIG"); - if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) { - logmessage(LOG_ERR, "Server error on STARTCONFIG"); - return -1; - } + if(expected==NULL) return 0; - reply=sock_comm(fm_fd_r, fm_fd_w, "LASTMODIFIED"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){ - logmessage(LOG_ERR, "Server error on LASTMODIFIED (%m)"); - return -1; - } - if((ihost_state->last_modified=strdup(reply)) == NULL){ - logmessage(LOG_ERR, "strdup failed (%m)"); - return -1; - } + if((strcmp(expected, *response))==0) return 0; - reply=sock_comm(fm_fd_r, fm_fd_w, "FILELIST"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){ - logmessage(LOG_ERR, "Server error on FILELIST (%m)"); - return -1; - } - if((ihost_state->files_list=strdup(reply)) == NULL){ - logmessage(LOG_ERR, "strdup failed (%m)"); - return -1; - } + log_msg(LOG_DEBUG, "Did not get expected response"); + return -1; +} - reply=sock_comm(fm_fd_r, fm_fd_w, "FQDN"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){ - logmessage(LOG_ERR, "Server error on FQDN (%m)"); +int tcp_comm_strdup(FILE *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){ - logmessage(LOG_ERR, "strdup failed (%m)"); - return -1; - } - reply=sock_comm(fm_fd_r, fm_fd_w, "UDPUpdateTime"); - if(reply== NULL){ - logmessage(LOG_ERR, "Server error (%m)"); - return -1; - } - if (strncasecmp(reply, "ERROR", 5) != 0){ - ihost_state->udp_update_time=atoi(reply); - } + *response=strdup(*response); + if (response==NULL) return -1; + + return 0; +} - reply=sock_comm(fm_fd_r, fm_fd_w, "TCPUpdateTime"); - if(reply== NULL){ - logmessage(LOG_ERR, "Server error on TCPUpdateTime (%m)"); - return -1; +int ihost_getconfig(ihost_state_t *ihost_state){ + + FILE *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; + + tcp_con=create_tcp_connection(ihost_state->filtermanager_host, ihost_state->filtermanager_port); + + if(ihost_state->file_list!=NULL || ihost_state->last_modified!=NULL){ + if(tcp_con==NULL){ + 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); + return 0; + }else{ + if((strcmp(response, "EXPIRED"))!=0){ + goto error; + } + } } - if (strncasecmp(reply, "ERROR", 5) != 0){ - ihost_state->tcp_update_time=atoi(reply); - } - reply=sock_comm(fm_fd_r, fm_fd_w, "ENDCONFIG"); - if(reply== NULL){ - logmessage(LOG_ERR, "Server error on ENDCONFIG (%m)"); - return -1; + /* 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, "FILTER"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){ - logmessage(LOG_ERR, "Server error FILTER failed (%m)"); - return -1; + if((tcp_comm_strdup(tcp_con, "LASTMODIFIED", &response, NULL))!=0){ + goto error; } - reply_ptr=strchr(reply,';'); - if (reply_ptr==NULL){ - logmessage(LOG_ERR, "Incorrect data returned"); - return -1; + last_modified=response; + + if((tcp_comm_strdup(tcp_con, "FILELIST", &response, NULL))!=0){ + goto error; } - *reply_ptr='\0'; - if((ihost_state->server_fqdn=strdup(reply)) == NULL){ - logmessage(LOG_ERR, "strdup failed (%m)"); - return -1; + file_list=response; + + if((tcp_comm_strdup(tcp_con, "FQDN", &response, NULL))!=0){ + goto error; } - reply=reply_ptr + 1; - reply_ptr=strchr(reply,';'); - if (reply_ptr==NULL){ - logmessage(LOG_ERR, "Incorrect data returned 2"); - return -1; + host_fqdn=response; + + if((tcp_comm_strdup(tcp_con, "IP", &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)){ - logmessage(LOG_ERR, "Incorrect data returned 3 "); - return -1; + host_ip=response; + + if((tcp_comm(tcp_con, "UDPUpdateTime", &response, NULL))!=0){ + goto error; } + udp_update_time=atoi(response); - reply=sock_comm(fm_fd_r, fm_fd_w, "END"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){ - logmessage(LOG_ERR, "Server error on END (%m)"); - return -1; + if((tcp_comm(tcp_con, "ConfigTTL", &response, NULL))!=0){ + goto error; } + config_ttl=atoi(response); - if(fclose(fm_fd_r) !=0){ - logmessage(LOG_ERR, "Failed to close read FD (%m)"); - return -1; + if((tcp_comm(tcp_con, "ENDCONFIG", &response, NULL))!=0){ + goto error; } - if(fclose(fm_fd_w) !=0){ - logmessage(LOG_ERR, "Failed to close write FD (%m)"); - 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; + } + + printf("string : %s\n", 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); + + /* 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->host_fqdn!=NULL) free(ihost_state->host_fqdn); + if(ihost_state->server_fqdn!=NULL) free(ihost_state->server_fqdn); + if(ihost_state->host_ip!=NULL) free(ihost_state->host_ip); + + ihost_state->file_list=file_list; + ihost_state->last_modified=last_modified; + ihost_state->host_fqdn=host_fqdn; + ihost_state->host_ip=host_ip; + 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; -} -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; +error: - logmessage(LOG_DEBUG, "Setting up configure socket to %s on port %d", ihost_state->server_fqdn, ihost_state->server_tcp_port); - if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { - logmessage(LOG_ERR, "Can't create AF_INET socket (%m)"); - return -1; - } + 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); + fclose(tcp_con); - if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){ - logmessage(LOG_ERR, "Failed to resolve address %s (%m)", ihost_state->server_fqdn); - return -1; - } + return -1; +} - 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); +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; + int disk_entries=0; + int diskio_entries=0; + int network_entries=0; - if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) { - logmessage(LOG_ERR, "Failed to connect to %s on port %d (%m)", ihost_state->server_fqdn, ihost_state->server_tcp_port); - return -1; - } + int counter; + long long x; + long long y; - /* 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){ - logmessage(LOG_ERR, "Failed to open stream (%m)"); - return -1; - } + /* Print start of the packet we want */ + snprintf(xml, size, "", \ + seq_no, ihost_state->host_fqdn, time(NULL), ihost_state->host_ip); - if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){ - logmessage(LOG_ERR, "Failed to open stream (%m)"); - return -1; - } + /* 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"); + }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); - reply=sock_comm(fm_fd_r, fm_fd_w, "HEARTBEAT"); - if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) { - logmessage(LOG_ERR, "Server error on HEARTBEAT"); - return -1; - } + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + } - reply=sock_comm(fm_fd_r, fm_fd_w, "CONFIG"); - if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) { - logmessage(LOG_ERR, "Server error on CONFIG"); - return -1; - } + + /*Get mem stats, and fill in xml */ + if((mem_stats=get_memory_stats())==NULL){ + log_msg(LOG_CRIT, "Failed to get memory statistics"); + }else{ + snprintf(tmp, size, \ + "%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; + } - reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->files_list); - if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) { - logmessage(LOG_ERR, "Server error on fileslist"); - return -1; - } - reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->last_modified); - if (reply==NULL) { - logmessage(LOG_ERR, "Server error NULL recieved on lastmodified"); - return -1; - } - if (strncasecmp(reply, "ERROR", 5) == 0){ - /* Means the config has changed */ - logmessage(LOG_INFO, "Recieved ERROR from server for a reconfigure required"); - exitcode=RECONFIGURE_RETURN_CODE; + /* Get load stats */ + if((load_stats=get_load_stats())==NULL){ + log_msg(LOG_CRIT, "Failed to get load statistics"); + }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) ) { - logmessage(LOG_ERR, "Server error on KEY"); - return -1; - } - if (ihost_state->key!=NULL) free(ihost_state->key); - - if((ihost_state->key=strdup(reply)) == NULL){ - logmessage(LOG_ERR, "strdup failed (%m)"); - return -1; - } - reply=sock_comm(fm_fd_r, fm_fd_w, "ENDHEARTBEAT"); - if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){ - logmessage(LOG_ERR, "Server error on ENDHEARTBEAT (%m)"); - return -1; - } + /* get user stats */ + + if((user_stats=get_user_stats())==NULL){ + log_msg(LOG_CRIT, "Failed to get user statistics"); + }else{ - fflush(fm_fd_r); - fflush(fm_fd_w); + snprintf(tmp, size, \ + "%s%d", \ + user_stats->name_list, \ + user_stats->num_entries); + + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + } - if(fclose(fm_fd_r) !=0){ - logmessage(LOG_ERR, "Failed to close read FD (%m)"); - return -1; - } - if(fclose(fm_fd_w) !=0){ - logmessage(LOG_ERR, "Failed to close write FD (%m)"); - return -1; - } - return exitcode; -} + /* swap stats */ + if((swap_stats=get_swap_stats())==NULL){ + log_msg(LOG_CRIT, "Failed to get swap statistics"); + }else{ + snprintf(tmp, size, \ + "%lld%lld%lld",\ + swap_stats->total, \ + swap_stats->used, \ + swap_stats->free); + + if(strlcat(xml, tmp, size) >= size) goto too_big_error; + } -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 xml_size=0; - int x=0; - logmessage(LOG_DEBUG,"get_cpu_stats"); - stats[0]=get_cpu_stats(); - logmessage(LOG_DEBUG,"get_disk_stats"); - stats[1]=get_disk_stats(); - logmessage(LOG_DEBUG,"get_load_stats"); - stats[2]=get_load_stats(); - logmessage(LOG_DEBUG,"get_memory_stats"); - stats[3]=get_memory_stats(); - logmessage(LOG_DEBUG,"get_os_info"); - stats[4]=get_os_info(); - logmessage(LOG_DEBUG,"get_page_stats"); - stats[5]=get_page_stats(); - logmessage(LOG_DEBUG,"get_process_stats"); - stats[6]=get_process_stats(); - logmessage(LOG_DEBUG,"get_swap_stats"); - stats[7]=get_swap_stats(); - logmessage(LOG_DEBUG,"get_user_stats"); - stats[8]=get_user_stats(); + /* general stats */ + if((general_stats=get_general_stats())==NULL){ + log_msg(LOG_CRIT, "Failed to get general statistics"); + }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; + + } - for(x=0;x%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=get_page_stats_diff())==NULL){ + log_msg(LOG_CRIT, "Failed to get paging statistics"); + }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; } - xml_size+=strlen(stats[x]); + snprintf(tmp, size, \ + "%lld%lld", \ + x, \ + y); + + if(strlcat(xml, tmp, size) >= size) goto too_big_error; } - xml_data=malloc(xml_size+1); - xml_data=strcpy(xml_data, stats[0]); - free(stats[0]); - for(x=1;x", 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; + } + + 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; + } - 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); + + /* get networks stats */ + + if((network_stats=get_network_stats_diff(&network_entries))==NULL){ + log_msg(LOG_CRIT, "Failed to get network statistics"); + }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; + } - logmessage(LOG_DEBUG,"Generated XML Data of : %s", xml_data); - return xml_data; -} + snprintf(tmp, size, \ + "", \ + counter, \ + network_stats->interface_name, \ + x, \ + y, \ + counter); -int send_stats(ihost_state_t *ihost_state, char *data_stream){ - struct sockaddr_in addr; - struct in_addr haddr; + strlcat(xml, tmp, size); + network_stats++; + } - int sd; - size_t len; + if(strlcat(xml, "", size) >= size) goto too_big_error; - len=strlen(data_stream); - if(len>UDP_MAX_PACKET_SIZE){ - logmessage(LOG_ERR, "Too big to send to server. Please reconfigure client and server and recompile"); - exit(1); } - logmessage(LOG_DEBUG,"Resolving IP of server"); - if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){ - logmessage(LOG_ERR, "Failed to resolve address %s (%m)", ihost_state->server_fqdn); - return -1; - } - logmessage(LOG_DEBUG,"Creating UDP socket to %s on %d",ihost_state->server_fqdn, ihost_state->server_udp_port); - if((sd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){ - logmessage(LOG_ERR, "failed to create UDP socket (%m)"); - return -1; - } - 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); - logmessage(LOG_INFO,"Sending packet : %s", data_stream); - if((sendto(sd, data_stream, len, 0, (struct sockaddr *) &addr, sizeof(addr))) != len){ - logmessage(LOG_ERR, "Send the wrong number of bytes (%m)"); - return -1; + /* get disk stats */ + + if((disk_stats=get_disk_stats(&disk_entries))==NULL){ + log_msg(LOG_CRIT, "Failed to get disk statistics"); + }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; + } + - close(sd); + if(strlcat(xml, "", size) >= size) goto too_big_error; - return 0; + /*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; } + + void usage(char *progname){ - fprintf(stderr, "Usage %s [options] server port\n", progname); - fprintf(stderr, "Options\n"); - fprintf(stderr, " -v Verbose, the more v flags the more verbose, eg -vv\n"); - fprintf(stderr, " -d Daemon mode, self backgrounding\n"); - fprintf(stderr, " -s Send errors to syslog\n"); - fprintf(stderr, " -V Print version number\n"); - fprintf(stderr, " -h Prints this help page\n"); - exit(1); + fprintf(stderr, "Usage %s [options] server port\n", progname); + fprintf(stderr, "Options\n"); + fprintf(stderr, " -v Verbose mode,-vv would make even more verbose\n"); + fprintf(stderr, " -f Foreground mode, print errors to stderr\n"); + fprintf(stderr, " -V Print version number\n"); + fprintf(stderr, " -h Prints this help page\n"); + 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; - pid_t pid; + udp_sockinfo_t udp_sockinfo; + int cmdopt; extern int optind; - int verbose=0, daemon=0; - extern int syslog_logging; - extern int log_level; - extern int cur_level; + pid_t pid; FILE *f; + int packet_num=0; + int len; - log_level=1; - cur_level=1; - syslog_logging=0; + char packet[MAX_UDP_PACKET_SIZE]; - errf_set_ofunc(log_errors); - /* 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; - ihost_state.my_ip=NULL; + time_t cur_time, sleep_delay, udp_time=0, config_time=0; - 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){ - switch(cmdopt){ - case 'v': - verbose++; - break; - - case 'd': - /* Force syslog logging since stderr will be closed in this case */ - syslog_logging=1; - daemon=1; - break; - - case 's': - syslog_logging=1; - break; - - case 'h': - usage(argv[0]); - break; + /* Blank ihost_state to default settings */ + ihost_state.filtermanager_host=NULL; + ihost_state.host_fqdn=NULL; + ihost_state.host_ip=NULL; + ihost_state.server_fqdn=NULL; + ihost_state.file_list=NULL; + ihost_state.last_modified=NULL; - case 'V': - errf("%s version %s",argv[0], VERSION); - break; + while((cmdopt=getopt(argc, argv, "vfhV")) != -1){ + switch(cmdopt){ + case 'v': + ihost_config.verbose++; + break; - default: - usage(argv[0]); - exit(1); - } - } + case 'f': + /* Force syslog logging since stderr will be closed in this case */ + ihost_config.daemon=0; + break; - if(argc!=optind+2){ - usage(argv[0]); + case 'h': + usage(argv[0]); + break; + + case 'V': + fprintf(stderr, "%s version %s", argv[0], VERSION); + break; + + default: + usage(argv[0]); + exit(1); + } + } + + if(argc!=optind+2){ + usage(argv[0]); + exit(1); + } + + ihost_state.filtermanager_host=strdup(argv[optind]); + ihost_state.filtermanager_port=atoi(argv[optind+1]); + + if(gethostbyname(ihost_state.filtermanager_host)==NULL){ + log_msg(LOG_CRIT, "Failed to lookup hostname. Please check settings"); 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]); + if(ihost_state.filtermanager_port==0){ + log_msg(LOG_ERR, "Invalid port number"); + exit(1); } - if(daemon==1){ + if(ihost_config.daemon){ pid=fork(); if(pid==-1){ - errf("Fork failed, can't background. Exiting"); - exit(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){ - errf("setsid failed (%m)"); + /* 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(LOGFILE_PATH, "a"))==NULL){ + ihost_config.log=stderr; + log_msg(LOG_CRIT, "Failed to open Logfiles %s for writing", LOGFILE_PATH); exit(1); } - fclose(stdin); - fclose(stdout); - fclose(stderr); - } - if(syslog_logging==1){ - openlog(errf_get_progname(),0,LOG_ERR); - setlogmask(LOG_UPTO(LOG_DEBUG)); - } - - switch(verbose){ - case 0: - /* Critical errors + */ - log_level=LOG_ERR; - break; - case 1: - /* Recoverable errors */ - log_level=LOG_WARNING; - break; - case 2: - /* Print stuff like the XML packets */ - log_level=LOG_INFO; - break; - default: - /* Must have lots of v's */ - /* Print out everything its doing */ - log_level=LOG_DEBUG; - break; - } + fclose(stdin); + fclose(stdout); + fclose(stderr); - logmessage(LOG_DEBUG,"Writing PID FILE"); - pid=getpid(); - if((f=fopen(PID_FILE,"w")) == NULL){ - logmessage(LOG_WARNING, "Failed to write PID file (%m)"); - }else{ - if((fprintf(f,"%d",(int)pid)) <= 0 ){ - logmessage(LOG_WARNING, "Failed to write PID file (%m)"); - } - if((fclose(f))!=0){ - logmessage(LOG_ERR, "failed to close PID file"); - exit(1); - } + } + + log_msg(LOG_INFO, "Starting ihost"); + + 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"); + } + } + + /* Get the initial config from the filter manager. Should this fail, + * wait, and then try again. */ + + get_diskio_stats_diff(&packet_num); + packet_num=0; + + while(ihost_getconfig(&ihost_state)!=0){ + log_msg(LOG_ERR, "Failed to get ihost config"); + sleep(10); } - if(ihost_configure(&ihost_state)!=0){ - logmessage(LOG_ERR,"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); + 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); } + config_time=time(NULL)+ihost_state.config_ttl; + + /* Now have config.. collect data and send as often as required */ for(;;){ cur_time=time(NULL); - if(cur_time>=tcp_time){ - logmessage(LOG_DEBUG,"Sending heartbeat"); - heartbeat_exit=heartbeat(&ihost_state); - if(heartbeat_exit==RECONFIGURE_RETURN_CODE){ - logmessage(LOG_INFO,"heartbeat needs to be reconfigured"); - ihost_configure(&ihost_state); - udp_time=0; - } - if(heartbeat_exit==-1){ - logmessage(LOG_ERR,"Heartbeat failed"); - exit(1); - } - tcp_time=time(NULL)+ihost_state.tcp_update_time; - logmessage(LOG_DEBUG,"next tcp time should be %d", tcp_time); - } if(cur_time>=udp_time){ - logmessage(LOG_DEBUG,"Sending udp data"); - /* Work out how long it takes to get the stats for next time round - so the sleep time can be adjusted accordingly */ - stat_grab_time=time(NULL); - if((xml_stats=stat_grab(&ihost_state, counter++)) == NULL){ - logmessage(LOG_ERR,"Failed to get stats (%m)"); - exit(1); + if((get_system_stats(packet_num++, &ihost_state, packet, MAX_UDP_PACKET_SIZE))!=0){ + log_msg(LOG_ERR, "Failed to get system stats"); } - 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; - logmessage(LOG_DEBUG,"next udp time should be %d", udp_time); + + 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); - if(tcp_time0) sleep(sleep_delay); - } - return 0; + } + + return(0); } -