--- projects/cms/source/ihost/ihost.c 2002/05/18 18:15:56 1.11
+++ projects/cms/source/ihost/ihost.c 2003/03/04 10:44:36 1.31
@@ -1,5 +1,6 @@
/*
* i-scream central monitoring system
+ * http://www.i-scream.org.uk
* Copyright (C) 2000-2002 i-scream
*
* This program is free software; you can redistribute it and/or
@@ -17,450 +18,797 @@
* 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
-#include "ukcprog.h"
+#include
+#include
+#include
+#include
+#include
#include
-#include
+
+#include "ukcprog.h"
#include "statgrab.h"
-#define RECONFIGURE_RETURN_CODE 2
-#define UDP_MAX_PACKET_SIZE 8192
+#define LOG_CRIT 0
+#define LOG_ERR 1
+#define LOG_INFO 2
+#define LOG_DEBUG 3
typedef struct{
- int fm_port;
- char *fm_host;
-
- char *my_fqdn;
+ int filtermanager_port;
+ char *filtermanager_host;
+
+ 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;
-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;
- 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;
- if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
- errf("Can't create AF_INET socket (%m)");
- return -1;
- }
+void log_msg(int level, char *format, ...){
+ extern int errno;
+ int cur_errno;
+ va_list ap;
- if (get_host_addr(ihost_state->fm_host, &haddr) != 0){
- errf("Failed to resolve address %s (%m)", ihost_state->fm_host);
- return -1;
+ 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");
+ }
}
+}
- 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);
+/* 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;
- 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;
+ va_start(ap, num_pointers);
+ for(;xsock=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
+ log_msg(LOG_CRIT, "Failed to create UDP socket");
+ 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(&(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;
}
- reply=sock_comm(fm_fd_r, fm_fd_w, "LASTMODIFIED");
- if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){
- errf("Server error (%m)");
- return -1;
+ if((get_host_addr(hostname, &haddr))!=0){
+ log_msg(LOG_CRIT, "Failed to lookup name for %s", hostname);
+ return NULL;
}
- if((ihost_state->last_modified=strdup(reply)) == NULL){
- errf("strdup failed (%m)");
- return -1;
- }
-
- reply=sock_comm(fm_fd_r, fm_fd_w, "FILELIST");
- if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){
- errf("Server error (%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;
}
- if((ihost_state->files_list=strdup(reply)) == NULL){
- errf("strdup failed (%m)");
- return -1;
- }
- reply=sock_comm(fm_fd_r, fm_fd_w, "FQDN");
- if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){
- errf("Server error (%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((ihost_state->my_fqdn=strdup(reply)) == NULL){
- errf("strdup failed (%m)");
+
+ 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;
+
+ if(expected==NULL) return 0;
+
+ if((strcmp(expected, *response))==0) return 0;
+
+ log_msg(LOG_DEBUG, "Did not get expected response");
+ return -1;
+}
+
+int tcp_comm_strdup(FILE *f, char *send, char **response, char *expected){
+ if((tcp_comm(f, send, response, expected))!=0){
return -1;
}
- reply=sock_comm(fm_fd_r, fm_fd_w, "UDPUpdateTime");
- if(reply== NULL){
- errf("Server error (%m)");
- return -1;
+ *response=strdup(*response);
+ if (response==NULL) return -1;
+
+ return 0;
+}
+
+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;
+
+ if((tcp_con=create_tcp_connection(ihost_state->filtermanager_host, ihost_state->filtermanager_port))==NULL){
+ goto error;
}
- if (strncasecmp(reply, "ERROR", 5) != 0){
- ihost_state->udp_update_time=atoi(reply);
- }
- reply=sock_comm(fm_fd_r, fm_fd_w, "TCPUpdateTime");
- if(reply== NULL){
- errf("Server error (%m)");
- return -1;
+ 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){
- errf("Server error (%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)){
- errf("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){
- errf("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){
- errf("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){
- errf("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)){
- errf("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 )){
- errf("Server error (%m)");
- return -1;
+ if((tcp_comm(tcp_con, "ConfigTTL", &response, NULL))!=0){
+ goto error;
}
+ config_ttl=atoi(response);
- if(fclose(fm_fd_r) !=0){
- errf("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){
- errf("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;
+
+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);
+ fclose(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];
+ 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 ((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, 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=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);
- 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;
- }
+
+ /*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;
+ }
- if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){
- errf("Failed to open stream (%m)");
- return -1;
- }
- reply=sock_comm(fm_fd_r, fm_fd_w, "HEARTBEAT");
- if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) {
- errf("Server error");
- return -1;
- }
+ /* 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, "CONFIG");
- if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) {
- errf("Server error");
- return -1;
- }
- 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;
- }
+ /* get user stats */
+
+ if((user_stats=get_user_stats())==NULL){
+ log_msg(LOG_CRIT, "Failed to get user statistics");
+ }else{
- 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;
+ snprintf(tmp, size, \
+ "%s
%d", \
+ user_stats->name_list, \
+ user_stats->num_entries);
+
+ 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);
+ /* 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;
+ }
- 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;
- }
- return exitcode;
-}
+ /* 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;
+
+ }
-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();
+ /* process stats */
+ if((process_stats=get_process_stats())==NULL){
+ log_msg(LOG_CRIT, "Failed to get general statistics");
+ }else{
+ snprintf(tmp, size, \
+ "%d%d%d%d%d",\
+ process_stats->sleeping, \
+ process_stats->running, \
+ process_stats->zombie, \
+ process_stats->stopped, \
+ process_stats->total);
- for(;x= 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{
- xml_data_p=xml_data;
- if((xml_data=strf("%s%s", xml_data, stats[x])) == NULL){
- errf("str failed (%m)");
- return NULL;
- }
- free(xml_data_p);
+ x=page_stats->pages_pagein;
+ y=page_stats->pages_pageout;
}
- free(stats[x]);
+ snprintf(tmp, size, \
+ "%lld%lld", \
+ x, \
+ y);
+
+ if(strlcat(xml, tmp, size) >= size) goto too_big_error;
}
- xml_data_p=xml_data;
- xml_data=strf("%s", counter, ihost_state->my_fqdn, time(NULL), "127.0.0.1", ihost_state->key, xml_data);
- free(xml_data_p);
+
+
+ /* get diskio stats */
- return xml_data;
-}
+ if((diskio_stats=get_diskio_stats_diff(&diskio_entries))==NULL){
+ log_msg(LOG_CRIT, "Failed to get diskio statistics");
+ }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;
+ }
+
+ snprintf(tmp, size, \
+ "", \
+ counter, \
+ diskio_stats->disk_name, \
+ x, \
+ y, \
+ counter);
- int sd;
- size_t len;
+ strlcat(xml, tmp, size);
+ diskio_stats++;
+ }
- 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);
+ if(strlcat(xml, "", size) >= size) goto too_big_error;
+
}
+
- if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){
- errf("Failed to resolve address %s (%m)", ihost_state->fm_host);
- return -1;
- }
+ /* 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;
+ }
- if((sd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
- errf("failed to create UDP socket (%m)");
- return -1;
+ snprintf(tmp, size, \
+ "", \
+ counter, \
+ network_stats->interface_name, \
+ x, \
+ y, \
+ counter);
+
+ strlcat(xml, tmp, size);
+ network_stats++;
+ }
+
+ if(strlcat(xml, "", size) >= size) goto too_big_error;
+
}
- 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);
- if((sendto(sd, data_stream, len, 0, (struct sockaddr *) &addr, sizeof(addr))) != len){
- errf("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 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;
+ udp_sockinfo_t udp_sockinfo;
+
+ int cmdopt;
+ extern int optind;
+ pid_t pid;
+ FILE *f;
+ int packet_num=0;
+ int len;
- /* 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;
+ char packet[MAX_UDP_PACKET_SIZE];
- errf_set_progname(argv[0]);
- if(argc!=3){
- errf_usage(" ");
+ time_t cur_time, sleep_delay, udp_time=0, config_time=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;
+
+ /* 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;
+
+ while((cmdopt=getopt(argc, argv, "vfhV")) != -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 'h':
+ usage(argv[0]);
+ break;
+
+ case 'V':
+ fprintf(stderr, "%s version %s\n", 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);
}
+ if(ihost_state.filtermanager_port==0){
+ log_msg(LOG_ERR, "Invalid port number");
+ exit(1);
+ }
- ihost_state.fm_host=argv[1];
- ihost_state.fm_port=atoi(argv[2]);
+ 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);
+ }
- 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);
+ fclose(stdin);
+ fclose(stdout);
+ fclose(stderr);
+
+ }
+
+ 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);
}
+ 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){
- /*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)");
- 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;
+
+ 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);
}
-