ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/ihost/ihost.c
Revision: 1.43
Committed: Sun Oct 5 12:52:12 2003 UTC (21 years, 2 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.42: +27 -25 lines
Log Message:
Tweak the option parsing. Made ihost a bit like idar; the server and
port are given as options, and have defaults at compile time.

Also tided up the usage and removed some debugging (?) printf's.

Can someone check this bit of code:

ihost_state.filtermanager_host=strdup(optarg);

I copied that strdup from the existing line of code, but in idar it
wasn't needed. Is it necessary here?

File Contents

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