--- projects/cms/source/ihost/ihost.c 2004/01/07 11:37:10 1.48
+++ projects/cms/source/ihost/ihost.c 2005/09/24 13:30:40 1.53
@@ -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
@@ -194,22 +229,26 @@ int create_udp_sockinfo(udp_sockinfo_t *udp_sockinfo,
return 0;
}
-FILE *create_tcp_connection(char *hostname, int port){
+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");
+ 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;
+ goto out;
}
if((get_host_addr(hostname, &haddr))!=0){
log_msg(LOG_CRIT, "Failed to lookup name for %s", hostname);
close(sock);
- return NULL;
+ goto out;
}
memset(&addr, 0, sizeof(addr));
@@ -221,9 +260,11 @@ FILE *create_tcp_connection(char *hostname, int port){
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);
- return NULL;
+ goto out;
}
+#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);
@@ -231,8 +272,19 @@ FILE *create_tcp_connection(char *hostname, int port){
}
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);
@@ -241,10 +293,50 @@ int tcp_comm(FILE *f, char *send, char **response, cha
*response=fpgetline(f);
fseek(f, 0, SEEK_CUR);
- if(*response!=NULL) log_msg(LOG_DEBUG, "Recieved %s", *response);
+ 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;
+ 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(strcmp(*response, "ERROR")==0) return -1;
+
if(expected==NULL) return 0;
if((strcmp(expected, *response))==0) return 0;
@@ -252,9 +344,11 @@ int tcp_comm(FILE *f, char *send, char **response, cha
log_msg(LOG_DEBUG, "Did not get expected response");
return -1;
}
+#endif /* WIN32 */
-int tcp_comm_strdup(FILE *f, char *send, char **response, char *expected){
- if((tcp_comm(f, send, response, expected))!=0){
+int tcp_comm_strdup(IHOST_SOCKET f, char *send, char **response, char *expected)
+{
+ if((tcp_comm(f, send, response, expected))!=0){
return -1;
}
@@ -263,15 +357,14 @@ int tcp_comm_strdup(FILE *f, char *send, char **respon
return 0;
}
-
-int ihost_getconfig(ihost_state_t *ihost_state){
- FILE *tcp_con;
+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 *file_list=NULL;
char *last_modified=NULL;
char *host_fqdn=NULL;
char *host_ip=NULL;
@@ -280,28 +373,39 @@ int ihost_getconfig(ihost_state_t *ihost_state){
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){
+ 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){
@@ -320,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;
}
@@ -365,36 +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;
+ }
- 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;
}
@@ -425,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;
@@ -453,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", \
@@ -470,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", \
@@ -500,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", \
@@ -541,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",\
@@ -565,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;
@@ -576,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, \
@@ -616,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, \
@@ -650,14 +769,15 @@ 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;counter", \
+ "", \
counter, \
disk_stats->device_name, \
disk_stats->mnt_point, \
@@ -678,8 +798,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 */
@@ -691,30 +811,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;
@@ -723,167 +1013,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, "vfVn:i:s:p:h")) != -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();
- /* Get the initial config from the filter manager. Should this fail,
+ 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 */
- 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
}
- 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 */
@@ -892,9 +1190,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;
@@ -905,8 +1203,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
}