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