ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/ihost/ihost.c
Revision: 1.33
Committed: Sat Mar 8 20:41:46 2003 UTC (21 years, 9 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.32: +72 -1 lines
Log Message:
Created a strlcpy function to get it working with OS's that do not have it.
This function was lifted straight out of openssh code, and its licence for that
function is in the comment for it. I also moved errno around so strlcpy will work
with it.
I've left the
#ifndef HAVE_STRLCAT
line commented out for now until tim modifys the configure stuff to check for it
or not :)

File Contents

# User Rev Content
1 tdb 1.11 /*
2     * i-scream central monitoring system
3 tdb 1.23 * http://www.i-scream.org.uk
4 tdb 1.11 * Copyright (C) 2000-2002 i-scream
5     *
6     * This program is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU General Public License
8     * as published by the Free Software Foundation; either version 2
9     * of the License, or (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19     */
20    
21 tdb 1.26 #ifdef HAVE_CONFIG_H
22     #include "config.h"
23     #endif
24    
25 pajs 1.1 #include <stdio.h>
26     #include <stdlib.h>
27 pajs 1.28 #include <unistd.h>
28     #include <string.h>
29 pajs 1.18 #include <sys/types.h>
30 pajs 1.28 #include <sys/socket.h>
31     #include <stdarg.h>
32     #include <errno.h>
33 pajs 1.1 #include <netdb.h>
34 pajs 1.28
35 tdb 1.29 #include "ukcprog.h"
36 pajs 1.9 #include "statgrab.h"
37 pajs 1.1
38 pajs 1.28 #define LOG_CRIT 0
39     #define LOG_ERR 1
40     #define LOG_INFO 2
41     #define LOG_DEBUG 3
42    
43 pajs 1.1 typedef struct{
44 pajs 1.28 int filtermanager_port;
45     char *filtermanager_host;
46    
47     char *host_ip;
48     char *host_fqdn;
49 pajs 1.16
50 pajs 1.1 char *server_fqdn;
51     int server_udp_port;
52 pajs 1.28
53     /* Weird stuff iscream wants sent to it */
54 pajs 1.4 char *last_modified;
55 pajs 1.28 char *file_list;
56    
57 pajs 1.1 int udp_update_time;
58 pajs 1.28 // int config_ttl;
59    
60     time_t config_ttl;
61 pajs 1.1
62     }ihost_state_t;
63    
64 pajs 1.28 typedef struct{
65     int verbose;
66     int daemon;
67    
68     FILE *log;
69     }ihost_config_t;
70    
71     typedef struct{
72     struct sockaddr_in addr;
73     int sock;
74     }udp_sockinfo_t;
75    
76     ihost_config_t ihost_config;
77    
78 pajs 1.33 extern int errno;
79    
80     /* Taken from the openssh code. Its licence included in function.*/
81     //#ifndef HAVE_STRLCAT
82    
83     /*
84     * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
85     * All rights reserved.
86     *
87     * Redistribution and use in source and binary forms, with or without
88     * modification, are permitted provided that the following conditions
89     * are met:
90     * 1. Redistributions of source code must retain the above copyright
91     * notice, this list of conditions and the following disclaimer.
92     * 2. Redistributions in binary form must reproduce the above copyright
93     * notice, this list of conditions and the following disclaimer in the
94     * documentation and/or other materials provided with the distribution.
95     * 3. The name of the author may not be used to endorse or promote products
96     * derived from this software without specific prior written permission.
97     *
98     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
99     * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
100     * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
101     * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
102     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
103     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
104     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
105     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
106     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
107     * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
108     */
109     /*
110     * Appends src to string dst of size siz (unlike strncat, siz is the
111     * full size of dst, not space left). At most siz-1 characters
112     * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
113     * Returns strlen(src) + MIN(siz, strlen(initial dst)).
114     * If retval >= siz, truncation occurred.
115     */
116     size_t
117     strlcat(dst, src, siz)
118     char *dst;
119     const char *src;
120     size_t siz;
121     {
122     register char *d = dst;
123     register const char *s = src;
124     register size_t n = siz;
125     size_t dlen;
126    
127     /* Find the end of dst and adjust bytes left but don't go past end */
128     while (n-- != 0 && *d != '\0')
129     d++;
130     dlen = d - dst;
131     n = siz - dlen;
132    
133     if (n == 0)
134     return(dlen + strlen(s));
135     while (*s != '\0') {
136     if (n != 1) {
137     *d++ = *s;
138     n--;
139     }
140     s++;
141     }
142     *d = '\0';
143    
144     return(dlen + (s - src)); /* count does not include NUL */
145     }
146    
147     //#endif
148    
149    
150 pajs 1.28 void log_msg(int level, char *format, ...){
151     int cur_errno;
152     va_list ap;
153    
154     cur_errno=errno;
155    
156     if(level<=ihost_config.verbose){
157     va_start(ap, format);
158     vfprintf(ihost_config.log, format, ap);
159     va_end(ap);
160     if(level==LOG_CRIT){
161     fprintf(ihost_config.log, " (%s)\n", strerror(cur_errno));
162 pajs 1.18 }else{
163 pajs 1.28 fprintf(ihost_config.log, "\n");
164 pajs 1.18 }
165 pajs 1.28 }
166 pajs 1.18 }
167    
168 pajs 1.28 /* Takes many pointers, checks if they are NULL or not, and then free's them */
169     /* Deprciated - and i only wrote it today! :)
170     void m_free(int num_pointers, ...){
171     int x=0;
172     va_list ap;
173     void *p;
174 pajs 1.1
175 pajs 1.28 va_start(ap, num_pointers);
176     for(;x<num_pointers;x++){
177     p=va_arg(ap, void*);
178     if(p!=NULL){
179     free(p);
180     }
181     }
182     va_end(ap);
183     }
184     */
185    
186     int create_udp_sockinfo(udp_sockinfo_t *udp_sockinfo, char *hostname, int port){
187    
188     struct in_addr haddr;
189    
190     log_msg(LOG_DEBUG, "Resolving name for udp connection");
191     if(get_host_addr(hostname, &haddr) != 0){
192     log_msg(LOG_CRIT, "Failed to lookup name");
193     return 1;
194     }
195 pajs 1.1
196 pajs 1.28 if((udp_sockinfo->sock=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
197     log_msg(LOG_CRIT, "Failed to create UDP socket");
198     return 1;
199 pajs 1.1 }
200    
201 pajs 1.28 memset(&(udp_sockinfo->addr), 0, sizeof(struct sockaddr_in));
202     udp_sockinfo->addr.sin_family=AF_INET;
203     memcpy((char *)&(udp_sockinfo->addr.sin_addr), &haddr, sizeof(haddr));
204     udp_sockinfo->addr.sin_port = htons(port);
205 pajs 1.1
206 pajs 1.28 log_msg(LOG_DEBUG, "Socket created");
207     return 0;
208     }
209    
210     FILE *create_tcp_connection(char *hostname, int port){
211     int sock;
212     struct sockaddr_in addr;
213     struct in_addr haddr;
214     FILE *f;
215    
216     log_msg(LOG_DEBUG, "Creating tcp socket");
217     if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0){
218     log_msg(LOG_CRIT, "Failed to make TCP Socket");
219     return NULL;
220 pajs 1.1 }
221    
222 pajs 1.28 if((get_host_addr(hostname, &haddr))!=0){
223     log_msg(LOG_CRIT, "Failed to lookup name for %s", hostname);
224     return NULL;
225 pajs 1.2 }
226    
227 pajs 1.28 memset(&addr, 0, sizeof(addr));
228     addr.sin_family = AF_INET;
229     memcpy(&addr.sin_addr, &haddr, sizeof(haddr));
230     addr.sin_port = htons(port);
231    
232     log_msg(LOG_DEBUG, "Creating a tcp connection");
233     if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) !=0){
234     log_msg(LOG_CRIT, "Failed to connect to hostname %s on port %d", hostname, port);
235     return NULL;
236 pajs 1.1 }
237 pajs 1.28
238     if((f=fdopen(sock, "r+"))==NULL){
239     log_msg(LOG_CRIT, "Failed to connect to open filedescriptor on tcp connection");
240     close(sock);
241     return NULL;
242 pajs 1.16 }
243 pajs 1.28
244     return f;
245     }
246    
247     int tcp_comm(FILE *f, char *send, char **response, char *expected){
248    
249     log_msg(LOG_DEBUG, "Sending %s", send);
250     fprintf(f, "%s\n", send);
251     fflush(f);
252     *response=fpgetline(f);
253     fseek(f, 0, SEEK_CUR);
254    
255     if(*response!=NULL) log_msg(LOG_DEBUG, "Recieved %s", *response);
256    
257     if( (*response==NULL) || (strcmp(*response, "ERROR")==0) ) return -1;
258    
259     if(expected==NULL) return 0;
260    
261     if((strcmp(expected, *response))==0) return 0;
262    
263     log_msg(LOG_DEBUG, "Did not get expected response");
264     return -1;
265     }
266    
267     int tcp_comm_strdup(FILE *f, char *send, char **response, char *expected){
268     if((tcp_comm(f, send, response, expected))!=0){
269 pajs 1.16 return -1;
270     }
271 pajs 1.25
272 pajs 1.28 *response=strdup(*response);
273     if (response==NULL) return -1;
274    
275     return 0;
276     }
277    
278     int ihost_getconfig(ihost_state_t *ihost_state){
279    
280     FILE *tcp_con;
281     char *response;
282     char *response_ptr;
283    
284     /* Keep these in case of a failure and so it can keep running on the old config */
285     char *file_list=NULL;
286     char *last_modified=NULL;
287     char *host_fqdn=NULL;
288     char *host_ip=NULL;
289     int udp_update_time=0;
290     char *server_fqdn=NULL;
291     int server_udp_port=0;
292     time_t config_ttl=0;
293    
294 pajs 1.30 if((tcp_con=create_tcp_connection(ihost_state->filtermanager_host, ihost_state->filtermanager_port))==NULL){
295     goto error;
296     }
297 pajs 1.28
298     if(ihost_state->file_list!=NULL || ihost_state->last_modified!=NULL){
299     if(tcp_con==NULL){
300     goto error;
301     }
302    
303     if((tcp_comm(tcp_con, "CHECKCONFIG", &response, "OK"))!=0){
304     goto error;
305     }
306    
307     if((tcp_comm(tcp_con, ihost_state->file_list, &response, "OK"))!=0){
308     goto error;
309     }
310 pajs 1.18
311 pajs 1.28 if((tcp_comm(tcp_con, ihost_state->last_modified, &response, "OK"))==0){
312 pajs 1.32 if((tcp_comm(tcp_con, "END", &response, "OK"))!=0){
313 pajs 1.28 goto error;
314     }
315     fclose(tcp_con);
316     return 0;
317     }else{
318     if((strcmp(response, "EXPIRED"))!=0){
319     goto error;
320     }
321     }
322 pajs 1.1 }
323    
324 pajs 1.28 /* If we got to here, the config must of expired */
325 pajs 1.18
326 pajs 1.28 if((tcp_comm(tcp_con, "STARTCONFIG", &response, "OK"))!=0){
327     goto error;
328 pajs 1.1 }
329    
330 pajs 1.28 if((tcp_comm_strdup(tcp_con, "LASTMODIFIED", &response, NULL))!=0){
331     goto error;
332 pajs 1.1 }
333 pajs 1.28 last_modified=response;
334    
335     if((tcp_comm_strdup(tcp_con, "FILELIST", &response, NULL))!=0){
336     goto error;
337 pajs 1.1 }
338 pajs 1.28 file_list=response;
339 pajs 1.1
340 pajs 1.28 if((tcp_comm_strdup(tcp_con, "FQDN", &response, NULL))!=0){
341     goto error;
342 pajs 1.1 }
343 pajs 1.28 host_fqdn=response;
344    
345     if((tcp_comm_strdup(tcp_con, "IP", &response, NULL))!=0){
346     goto error;
347 pajs 1.1 }
348 pajs 1.28 host_ip=response;
349    
350     if((tcp_comm(tcp_con, "UDPUpdateTime", &response, NULL))!=0){
351     goto error;
352 pajs 1.1 }
353 pajs 1.28 udp_update_time=atoi(response);
354    
355     if((tcp_comm(tcp_con, "ConfigTTL", &response, NULL))!=0){
356     goto error;
357 pajs 1.1 }
358 pajs 1.28 config_ttl=atoi(response);
359 pajs 1.1
360 pajs 1.28 if((tcp_comm(tcp_con, "ENDCONFIG", &response, NULL))!=0){
361     goto error;
362 pajs 1.1 }
363    
364 pajs 1.28 if((tcp_comm(tcp_con, "FILTER", &response, NULL))!=0){
365     goto error;
366     }else{
367     response_ptr=strchr(response,';');
368     if(response_ptr==NULL){
369     log_msg(LOG_ERR, "Incorrect data sent by server");
370     goto error;
371     }
372     *response_ptr='\0';
373     server_fqdn=strdup(response);
374     if(server_fqdn==NULL){
375     goto error;
376     }
377     response_ptr++;
378     if(response_ptr==NULL){
379     log_msg(LOG_ERR, "Incorrect data sent by server");
380     goto error;
381     }
382    
383     printf("string : %s\n", response_ptr);
384     server_udp_port=atoi(response_ptr);
385    
386     if (server_udp_port==0){
387     log_msg(LOG_ERR, "Incorrect data sent by server");
388     goto error;
389     }
390 pajs 1.2 }
391 pajs 1.28
392     if((tcp_comm(tcp_con, "END", &response, "OK"))!=0){
393     goto error;
394 pajs 1.2 }
395 pajs 1.28
396     fclose(tcp_con);
397    
398     /* We have the data we need, and its all been read correctly */
399    
400     /* Free the old data before pointing them to the new data. m_free copes should
401     * this already be NULL */
402     if(ihost_state->file_list!=NULL) free(ihost_state->file_list);
403     if(ihost_state->last_modified!=NULL) free(ihost_state->last_modified);
404     if(ihost_state->host_fqdn!=NULL) free(ihost_state->host_fqdn);
405     if(ihost_state->server_fqdn!=NULL) free(ihost_state->server_fqdn);
406     if(ihost_state->host_ip!=NULL) free(ihost_state->host_ip);
407    
408     ihost_state->file_list=file_list;
409     ihost_state->last_modified=last_modified;
410     ihost_state->host_fqdn=host_fqdn;
411     ihost_state->host_ip=host_ip;
412     ihost_state->server_fqdn=server_fqdn;
413     ihost_state->server_udp_port=server_udp_port;
414     ihost_state->udp_update_time=udp_update_time;
415     ihost_state->config_ttl=config_ttl;
416    
417     log_msg(LOG_DEBUG, "UDP Update time %d", udp_update_time);
418     log_msg(LOG_DEBUG, "Configure ttl %d", config_ttl);
419    
420     return 0;
421    
422     error:
423    
424     if(file_list!=NULL) free(file_list);
425     if(last_modified!=NULL) free(last_modified);
426     if(host_fqdn!=NULL) free(host_fqdn);
427     if(server_fqdn!=NULL) free(server_fqdn);
428     if(host_ip!=NULL) free(host_ip);
429     fclose(tcp_con);
430    
431     return -1;
432     }
433    
434     int get_system_stats(int seq_no, ihost_state_t *ihost_state, char *xml, int size){
435     char tmp[size];
436     cpu_percent_t *cpu_percent;
437     mem_stat_t *mem_stats;
438     load_stat_t *load_stats;
439     user_stat_t *user_stats;
440     swap_stat_t *swap_stats;
441     general_stat_t *general_stats;
442     disk_stat_t *disk_stats;
443     diskio_stat_t *diskio_stats;
444     process_stat_t *process_stats;
445     network_stat_t *network_stats;
446     page_stat_t *page_stats;
447     int disk_entries=0;
448     int diskio_entries=0;
449     int network_entries=0;
450    
451     int counter;
452     long long x;
453     long long y;
454    
455     /* Print start of the packet we want */
456     snprintf(xml, size, "<packet seq_no=\"%d\" machine_name=\"%s\" date=\"%ld\" type=\"data\" ip=\"%s\">", \
457     seq_no, ihost_state->host_fqdn, time(NULL), ihost_state->host_ip);
458    
459     /* Get cpu stats, check it is correct, then fill in its entry for the xml */
460     if((cpu_percent=cpu_percent_usage())==NULL){
461     log_msg(LOG_CRIT, "Failed to get cpu statistics");
462     }else{
463     snprintf(tmp, size, \
464     "<cpu><user>%3.2f</user><kernel>%3.2f</kernel><idle>%3.2f</idle><iowait>%3.2f</iowait><swap>%3.2f</swap></cpu>", \
465     cpu_percent->user, \
466     cpu_percent->kernel, \
467     cpu_percent->idle, \
468     cpu_percent->iowait, \
469     cpu_percent->swap);
470    
471     if(strlcat(xml, tmp, size) >= size) goto too_big_error;
472 pajs 1.2 }
473 pajs 1.28
474    
475     /*Get mem stats, and fill in xml */
476     if((mem_stats=get_memory_stats())==NULL){
477     log_msg(LOG_CRIT, "Failed to get memory statistics");
478     }else{
479     snprintf(tmp, size, \
480     "<memory><total>%lld</total><free>%lld</free><used>%lld</used><cache>%lld</cache></memory>", \
481     mem_stats->total, \
482     mem_stats->free, \
483     mem_stats->used, \
484     mem_stats->cache);
485    
486     if(strlcat(xml, tmp, size) >= size) goto too_big_error;
487 pajs 1.2 }
488 pajs 1.28
489    
490     /* Get load stats */
491     if((load_stats=get_load_stats())==NULL){
492     log_msg(LOG_CRIT, "Failed to get load statistics");
493     }else{
494     snprintf(tmp, size, \
495     "<load><load1>%.2lf</load1><load5>%.2lf</load5><load15>%.2lf</load15></load>", \
496     load_stats->min1, \
497     load_stats->min5, \
498     load_stats->min15);
499     if(strlcat(xml, tmp, size) >= size) goto too_big_error;
500 pajs 1.2 }
501    
502 pajs 1.28
503     /* get user stats */
504    
505     if((user_stats=get_user_stats())==NULL){
506     log_msg(LOG_CRIT, "Failed to get user statistics");
507     }else{
508    
509     snprintf(tmp, size, \
510     "<users><list>%s</list><count>%d</count></users>", \
511     user_stats->name_list, \
512     user_stats->num_entries);
513    
514     if(strlcat(xml, tmp, size) >= size) goto too_big_error;
515 pajs 1.2 }
516 pajs 1.1
517 pajs 1.28
518     /* swap stats */
519     if((swap_stats=get_swap_stats())==NULL){
520     log_msg(LOG_CRIT, "Failed to get swap statistics");
521     }else{
522     snprintf(tmp, size, \
523     "<swap><total>%lld</total><used>%lld</used><free>%lld</free></swap>",\
524     swap_stats->total, \
525     swap_stats->used, \
526     swap_stats->free);
527    
528     if(strlcat(xml, tmp, size) >= size) goto too_big_error;
529 pajs 1.2 }
530 pajs 1.28
531    
532     /* general stats */
533    
534     if((general_stats=get_general_stats())==NULL){
535     log_msg(LOG_CRIT, "Failed to get general statistics");
536     }else{
537     snprintf(tmp, size, \
538     "<os><name>%s</name><release>%s</release><version>%s</version><sysname>%s</sysname><platform>%s</platform><uptime>%ld</uptime></os>", \
539     general_stats->os_name, \
540     general_stats->os_release, \
541     general_stats->os_version, \
542     general_stats->hostname, \
543     general_stats->platform, \
544     (long)general_stats->uptime);
545    
546     if(strlcat(xml, tmp, size) >= size) goto too_big_error;
547    
548 pajs 1.2 }
549 pajs 1.1
550 pajs 1.28
551     /* process stats */
552     if((process_stats=get_process_stats())==NULL){
553     log_msg(LOG_CRIT, "Failed to get general statistics");
554     }else{
555     snprintf(tmp, size, \
556     "<processes><sleeping>%d</sleeping><cpu>%d</cpu><zombie>%d</zombie><stopped>%d</stopped><total>%d</total></processes>",\
557     process_stats->sleeping, \
558     process_stats->running, \
559     process_stats->zombie, \
560     process_stats->stopped, \
561     process_stats->total);
562    
563     if(strlcat(xml, tmp, size) >= size) goto too_big_error;
564 pajs 1.4
565 pajs 1.28 }
566 pajs 1.4
567    
568 pajs 1.28 /* Get paging stats */
569     if((page_stats=get_page_stats_diff())==NULL){
570     log_msg(LOG_CRIT, "Failed to get paging statistics");
571     }else{
572     if(page_stats->systime!=0){
573     x=page_stats->pages_pagein / page_stats->systime;
574     y=page_stats->pages_pageout / page_stats->systime;
575     }else{
576     x=page_stats->pages_pagein;
577     y=page_stats->pages_pageout;
578     }
579     snprintf(tmp, size, \
580     "<pages><swapins>%lld</swapins><swapouts>%lld</swapouts></pages>", \
581     x, \
582     y);
583    
584     if(strlcat(xml, tmp, size) >= size) goto too_big_error;
585     }
586 pajs 1.4
587    
588 pajs 1.28 /* get diskio stats */
589    
590     if((diskio_stats=get_diskio_stats_diff(&diskio_entries))==NULL){
591 pajs 1.31 log_msg(LOG_CRIT, "Failed to get diskio statistics");
592 pajs 1.28 }else{
593     strlcat(xml, "<diskio>", size);
594     for(counter=0;counter<diskio_entries;counter++){
595 pajs 1.4
596 pajs 1.28 if(diskio_stats->systime!=0){
597     x=diskio_stats->read_bytes / diskio_stats->systime;
598     y=diskio_stats->write_bytes / diskio_stats->systime;
599     }else{
600     x=diskio_stats->read_bytes;
601     y=diskio_stats->write_bytes;
602     }
603    
604     snprintf(tmp, size, \
605     "<p%d name=\"%s\" rbytes=\"%lld\" wbytes=\"%lld\"></p%d>", \
606     counter, \
607     diskio_stats->disk_name, \
608     x, \
609     y, \
610     counter);
611 pajs 1.9
612 pajs 1.28 strlcat(xml, tmp, size);
613     diskio_stats++;
614     }
615 pajs 1.4
616 pajs 1.28 if(strlcat(xml, "</diskio>", size) >= size) goto too_big_error;
617 pajs 1.4
618     }
619 pajs 1.18
620 pajs 1.28
621     /* get networks stats */
622    
623     if((network_stats=get_network_stats_diff(&network_entries))==NULL){
624     log_msg(LOG_CRIT, "Failed to get network statistics");
625     }else{
626     strlcat(xml, "<net>", size);
627     for(counter=0;counter<network_entries;counter++){
628     if(network_stats->systime!=0){
629     x=network_stats->rx / network_stats->systime;
630     y=network_stats->tx / network_stats->systime;
631     }else{
632     x=network_stats->rx;
633     y=network_stats->tx;
634     }
635 pajs 1.4
636 pajs 1.28 snprintf(tmp, size, \
637     "<p%d name=\"%s\" rx=\"%lld\" tx=\"%lld\"></p%d>", \
638     counter, \
639     network_stats->interface_name, \
640     x, \
641     y, \
642     counter);
643 pajs 1.4
644 pajs 1.28 strlcat(xml, tmp, size);
645     network_stats++;
646     }
647 pajs 1.10
648 pajs 1.28 if(strlcat(xml, "</net>", size) >= size) goto too_big_error;
649 pajs 1.6
650 pajs 1.28 }
651 pajs 1.4
652 pajs 1.18
653 pajs 1.28 /* get disk stats */
654    
655     if((disk_stats=get_disk_stats(&disk_entries))==NULL){
656     log_msg(LOG_CRIT, "Failed to get disk statistics");
657     }else{
658     strlcat(xml, "<disk>", size);
659     for(counter=0;counter<disk_entries;counter++){
660     snprintf(tmp, size, \
661     "<p%d name=\"%s\" mount=\"%s\" fstype=\"%s\" total=\"%lld\" used=\"%lld\" avail=\"%lld\" totalinodes=\"%lld\" usedinodes=\"%lld\" freeinodes=\"%lld\"></p%d>", \
662     counter, \
663     disk_stats->device_name, \
664     disk_stats->mnt_point, \
665     disk_stats->fs_type, \
666     disk_stats->size, \
667     disk_stats->used, \
668     disk_stats->avail, \
669     disk_stats->total_inodes, \
670     disk_stats->used_inodes, \
671     disk_stats->free_inodes, \
672     counter);
673 pajs 1.18
674 pajs 1.28 strlcat(xml, tmp, size);
675 pajs 1.9
676 pajs 1.28 disk_stats++;
677     }
678 pajs 1.9
679 pajs 1.28 if(strlcat(xml, "</disk>", size) >= size) goto too_big_error;
680 pajs 1.9
681     }
682 pajs 1.28
683 pajs 1.9
684 pajs 1.28 if(strlcat(xml, "</packet>", size) >= size) goto too_big_error;
685 pajs 1.9
686 pajs 1.28 /*If we got to here, it should of all been filled in nicely now */
687     return 0;
688 pajs 1.10
689 pajs 1.28 too_big_error:
690     log_msg(LOG_ERR, "UDP Packet is too large. Throwing away the packet");
691     return -1;
692 pajs 1.9 }
693 pajs 1.1
694 pajs 1.28
695    
696 pajs 1.17 void usage(char *progname){
697 pajs 1.28 fprintf(stderr, "Usage %s [options] server port\n", progname);
698     fprintf(stderr, "Options\n");
699     fprintf(stderr, " -v Verbose mode,-vv would make even more verbose\n");
700     fprintf(stderr, " -f Foreground mode, print errors to stderr\n");
701     fprintf(stderr, " -V Print version number\n");
702     fprintf(stderr, " -h Prints this help page\n");
703     exit(1);
704 pajs 1.17 }
705    
706 pajs 1.3 int main(int argc, char **argv){
707 pajs 1.28
708 pajs 1.2 ihost_state_t ihost_state;
709 pajs 1.28 udp_sockinfo_t udp_sockinfo;
710    
711 pajs 1.17 int cmdopt;
712     extern int optind;
713 pajs 1.28 pid_t pid;
714 pajs 1.19 FILE *f;
715 pajs 1.28 int packet_num=0;
716     int len;
717 pajs 1.18
718 pajs 1.28 char packet[MAX_UDP_PACKET_SIZE];
719 pajs 1.18
720 pajs 1.28 time_t cur_time, sleep_delay, udp_time=0, config_time=0;
721 pajs 1.18
722 pajs 1.28 /* Set default settings */
723     ihost_config.verbose=1;
724     ihost_config.daemon=1;
725     /* Set all errors to go down stderr until told otherwise */
726     ihost_config.log=stderr;
727    
728     /* Blank ihost_state to default settings */
729     ihost_state.filtermanager_host=NULL;
730     ihost_state.host_fqdn=NULL;
731     ihost_state.host_ip=NULL;
732     ihost_state.server_fqdn=NULL;
733     ihost_state.file_list=NULL;
734     ihost_state.last_modified=NULL;
735    
736     while((cmdopt=getopt(argc, argv, "vfhV")) != -1){
737     switch(cmdopt){
738     case 'v':
739     ihost_config.verbose++;
740     break;
741    
742     case 'f':
743     /* Force syslog logging since stderr will be closed in this case */
744     ihost_config.daemon=0;
745     break;
746    
747     case 'h':
748     usage(argv[0]);
749     break;
750    
751     case 'V':
752 tdb 1.29 fprintf(stderr, "%s version %s\n", argv[0], VERSION);
753 pajs 1.28 break;
754    
755     default:
756     usage(argv[0]);
757     exit(1);
758     }
759     }
760    
761     if(argc!=optind+2){
762     usage(argv[0]);
763     exit(1);
764     }
765 pajs 1.17
766 pajs 1.28 ihost_state.filtermanager_host=strdup(argv[optind]);
767     ihost_state.filtermanager_port=atoi(argv[optind+1]);
768    
769     if(gethostbyname(ihost_state.filtermanager_host)==NULL){
770     log_msg(LOG_CRIT, "Failed to lookup hostname. Please check settings");
771 pajs 1.3 exit(1);
772     }
773 pajs 1.28 if(ihost_state.filtermanager_port==0){
774     log_msg(LOG_ERR, "Invalid port number");
775     exit(1);
776 pajs 1.17 }
777 pajs 1.18
778 pajs 1.28 if(ihost_config.daemon){
779 pajs 1.18 pid=fork();
780     if(pid==-1){
781 pajs 1.28 log_msg(LOG_CRIT, "Failed to background exiting");
782     exit(1);
783 pajs 1.18 }else if(pid!=0){
784 pajs 1.28 /* Parent process */
785     return 0;
786     }
787     /* We should now be in the background*/
788     if(setsid()==-1){
789     log_msg(LOG_CRIT, "setsid failed");
790     exit(1);
791     }
792    
793 tdb 1.29 if((ihost_config.log=fopen(LOG_FILE, "a"))==NULL){
794 pajs 1.28 ihost_config.log=stderr;
795 tdb 1.29 log_msg(LOG_CRIT, "Failed to open Logfiles %s for writing", LOG_FILE);
796 pajs 1.18 exit(1);
797     }
798 pajs 1.28
799     fclose(stdin);
800     fclose(stdout);
801     fclose(stderr);
802    
803     }
804    
805     log_msg(LOG_INFO, "Starting ihost");
806    
807     log_msg(LOG_DEBUG,"Writing PID FILE");
808    
809     pid=getpid();
810    
811     if((f=fopen(PID_FILE,"w")) == NULL){
812     log_msg(LOG_CRIT, "Failed to write PID file");
813     }else{
814     if((fprintf(f,"%d",(int)pid)) <= 0 ){
815     log_msg(LOG_CRIT, "Failed to write PID file");
816     }
817     if((fclose(f))!=0){
818     log_msg(LOG_CRIT, "failed to close PID file");
819     }
820     }
821    
822     /* Get the initial config from the filter manager. Should this fail,
823     * wait, and then try again. */
824    
825     get_diskio_stats_diff(&packet_num);
826     packet_num=0;
827    
828     while(ihost_getconfig(&ihost_state)!=0){
829     log_msg(LOG_ERR, "Failed to get ihost config");
830     sleep(10);
831 pajs 1.18 }
832    
833 pajs 1.28 printf("%s\n%d\n", ihost_state.server_fqdn, ihost_state.server_udp_port);
834     while((create_udp_sockinfo(&udp_sockinfo, ihost_state.server_fqdn, ihost_state.server_udp_port))!=0){
835     log_msg(LOG_ERR, "Failed to create udp socket");
836     sleep(10);
837 pajs 1.18 }
838 pajs 1.2
839 pajs 1.28 config_time=time(NULL)+ihost_state.config_ttl;
840 pajs 1.5
841 pajs 1.28 /* Now have config.. collect data and send as often as required */
842 pajs 1.9 for(;;){
843     cur_time=time(NULL);
844 pajs 1.28
845     if(cur_time>=udp_time){
846     if((get_system_stats(packet_num++, &ihost_state, packet, MAX_UDP_PACKET_SIZE))!=0){
847     log_msg(LOG_ERR, "Failed to get system stats");
848     }
849    
850     len=strlen(packet);
851     log_msg(LOG_DEBUG, "Packet size: %d\nPacket: %s\n", len, packet);
852    
853     if((sendto(udp_sockinfo.sock, packet, len, 0, (struct sockaddr *) &udp_sockinfo.addr, sizeof(udp_sockinfo.addr)))!=len){
854     log_msg(LOG_CRIT, "Failed to send packet");
855 pajs 1.9 }
856 pajs 1.28 udp_time=cur_time+ihost_state.udp_update_time;
857     log_msg(LOG_DEBUG, "Next packet should be sent on %d", udp_time);
858 pajs 1.9 }
859 pajs 1.28
860     if(cur_time>=config_time){
861     if(ihost_getconfig(&ihost_state)!=0){
862     /* If we can't get the config, try again 5 minutes time */
863     log_msg(LOG_ERR, "Failed to get config, try again 5 minutes time");
864     config_time=time(NULL)+300;
865     }else{
866     close(udp_sockinfo.sock);
867    
868     while((create_udp_sockinfo(&udp_sockinfo, ihost_state.server_fqdn, ihost_state.server_udp_port))!=0){
869     log_msg(LOG_CRIT, "Failed to create udp socket");
870     sleep(10);
871     }
872    
873     config_time=time(NULL)+ihost_state.config_ttl;
874 pajs 1.10
875 pajs 1.28 log_msg(LOG_DEBUG, "Config expires on %d\n", ihost_state.config_ttl);
876 pajs 1.9 }
877     }
878 pajs 1.10
879 pajs 1.28 sleep_delay=udp_time-time(NULL);
880     log_msg(LOG_DEBUG, "Sleeping for %d", sleep_delay);
881 pajs 1.10 if(sleep_delay>0) sleep(sleep_delay);
882 pajs 1.28 }
883    
884     return(0);
885 pajs 1.1 }