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, 2 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

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org.uk
4 * 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 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <stdarg.h>
32 #include <errno.h>
33 #include <netdb.h>
34
35 #include "ukcprog.h"
36 #include "statgrab.h"
37
38 #define LOG_CRIT 0
39 #define LOG_ERR 1
40 #define LOG_INFO 2
41 #define LOG_DEBUG 3
42
43 typedef struct{
44 int filtermanager_port;
45 char *filtermanager_host;
46
47 char *host_ip;
48 char *host_fqdn;
49
50 char *server_fqdn;
51 int server_udp_port;
52
53 /* Weird stuff iscream wants sent to it */
54 char *last_modified;
55 char *file_list;
56
57 int udp_update_time;
58 // int config_ttl;
59
60 time_t config_ttl;
61
62 }ihost_state_t;
63
64 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 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 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 }else{
163 fprintf(ihost_config.log, "\n");
164 }
165 }
166 }
167
168 /* 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
175 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
196 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 }
200
201 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
206 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 }
221
222 if((get_host_addr(hostname, &haddr))!=0){
223 log_msg(LOG_CRIT, "Failed to lookup name for %s", hostname);
224 return NULL;
225 }
226
227 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 }
237
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 }
243
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 return -1;
270 }
271
272 *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 if((tcp_con=create_tcp_connection(ihost_state->filtermanager_host, ihost_state->filtermanager_port))==NULL){
295 goto error;
296 }
297
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
311 if((tcp_comm(tcp_con, ihost_state->last_modified, &response, "OK"))==0){
312 if((tcp_comm(tcp_con, "END", &response, "OK"))!=0){
313 goto error;
314 }
315 fclose(tcp_con);
316 return 0;
317 }else{
318 if((strcmp(response, "EXPIRED"))!=0){
319 goto error;
320 }
321 }
322 }
323
324 /* If we got to here, the config must of expired */
325
326 if((tcp_comm(tcp_con, "STARTCONFIG", &response, "OK"))!=0){
327 goto error;
328 }
329
330 if((tcp_comm_strdup(tcp_con, "LASTMODIFIED", &response, NULL))!=0){
331 goto error;
332 }
333 last_modified=response;
334
335 if((tcp_comm_strdup(tcp_con, "FILELIST", &response, NULL))!=0){
336 goto error;
337 }
338 file_list=response;
339
340 if((tcp_comm_strdup(tcp_con, "FQDN", &response, NULL))!=0){
341 goto error;
342 }
343 host_fqdn=response;
344
345 if((tcp_comm_strdup(tcp_con, "IP", &response, NULL))!=0){
346 goto error;
347 }
348 host_ip=response;
349
350 if((tcp_comm(tcp_con, "UDPUpdateTime", &response, NULL))!=0){
351 goto error;
352 }
353 udp_update_time=atoi(response);
354
355 if((tcp_comm(tcp_con, "ConfigTTL", &response, NULL))!=0){
356 goto error;
357 }
358 config_ttl=atoi(response);
359
360 if((tcp_comm(tcp_con, "ENDCONFIG", &response, NULL))!=0){
361 goto error;
362 }
363
364 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 }
391
392 if((tcp_comm(tcp_con, "END", &response, "OK"))!=0){
393 goto error;
394 }
395
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 }
473
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 }
488
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 }
501
502
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 }
516
517
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 }
530
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 }
549
550
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
565 }
566
567
568 /* 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
587
588 /* get diskio stats */
589
590 if((diskio_stats=get_diskio_stats_diff(&diskio_entries))==NULL){
591 log_msg(LOG_CRIT, "Failed to get diskio statistics");
592 }else{
593 strlcat(xml, "<diskio>", size);
594 for(counter=0;counter<diskio_entries;counter++){
595
596 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
612 strlcat(xml, tmp, size);
613 diskio_stats++;
614 }
615
616 if(strlcat(xml, "</diskio>", size) >= size) goto too_big_error;
617
618 }
619
620
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
636 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
644 strlcat(xml, tmp, size);
645 network_stats++;
646 }
647
648 if(strlcat(xml, "</net>", size) >= size) goto too_big_error;
649
650 }
651
652
653 /* 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
674 strlcat(xml, tmp, size);
675
676 disk_stats++;
677 }
678
679 if(strlcat(xml, "</disk>", size) >= size) goto too_big_error;
680
681 }
682
683
684 if(strlcat(xml, "</packet>", size) >= size) goto too_big_error;
685
686 /*If we got to here, it should of all been filled in nicely now */
687 return 0;
688
689 too_big_error:
690 log_msg(LOG_ERR, "UDP Packet is too large. Throwing away the packet");
691 return -1;
692 }
693
694
695
696 void usage(char *progname){
697 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 }
705
706 int main(int argc, char **argv){
707
708 ihost_state_t ihost_state;
709 udp_sockinfo_t udp_sockinfo;
710
711 int cmdopt;
712 extern int optind;
713 pid_t pid;
714 FILE *f;
715 int packet_num=0;
716 int len;
717
718 char packet[MAX_UDP_PACKET_SIZE];
719
720 time_t cur_time, sleep_delay, udp_time=0, config_time=0;
721
722 /* 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 fprintf(stderr, "%s version %s\n", argv[0], VERSION);
753 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
766 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 exit(1);
772 }
773 if(ihost_state.filtermanager_port==0){
774 log_msg(LOG_ERR, "Invalid port number");
775 exit(1);
776 }
777
778 if(ihost_config.daemon){
779 pid=fork();
780 if(pid==-1){
781 log_msg(LOG_CRIT, "Failed to background exiting");
782 exit(1);
783 }else if(pid!=0){
784 /* 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 if((ihost_config.log=fopen(LOG_FILE, "a"))==NULL){
794 ihost_config.log=stderr;
795 log_msg(LOG_CRIT, "Failed to open Logfiles %s for writing", LOG_FILE);
796 exit(1);
797 }
798
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 }
832
833 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 }
838
839 config_time=time(NULL)+ihost_state.config_ttl;
840
841 /* Now have config.. collect data and send as often as required */
842 for(;;){
843 cur_time=time(NULL);
844
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 }
856 udp_time=cur_time+ihost_state.udp_update_time;
857 log_msg(LOG_DEBUG, "Next packet should be sent on %d", udp_time);
858 }
859
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
875 log_msg(LOG_DEBUG, "Config expires on %d\n", ihost_state.config_ttl);
876 }
877 }
878
879 sleep_delay=udp_time-time(NULL);
880 log_msg(LOG_DEBUG, "Sleeping for %d", sleep_delay);
881 if(sleep_delay>0) sleep(sleep_delay);
882 }
883
884 return(0);
885 }