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

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org
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 #include <netinet/in.h>
35
36 #include <ukcprog.h>
37 #include <statgrab.h>
38
39 #define LOG_CRIT 0
40 #define LOG_ERR 1
41 #define LOG_INFO 2
42 #define LOG_DEBUG 3
43
44 typedef struct{
45 int filtermanager_port;
46 char *filtermanager_host;
47
48 char *host_ip;
49 char *host_fqdn;
50 int preset_fqdn;
51 int preset_ip;
52
53 char *server_fqdn;
54 int server_udp_port;
55
56 /* Weird stuff iscream wants sent to it */
57 char *last_modified;
58 char *file_list;
59
60 int udp_update_time;
61 // int config_ttl;
62
63 time_t config_ttl;
64
65 }ihost_state_t;
66
67 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 extern int errno;
82
83 /* Taken from the OpenSSH code. Its licence included in function.*/
84 #ifndef HAVE_STRLCAT
85
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
113 /*
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 #endif
152 /* End strlcat function taken from OpenSSH */
153
154 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 }else{
167 fprintf(ihost_config.log, "\n");
168 }
169 fflush(ihost_config.log);
170 }
171 }
172
173 /* 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
180 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
201 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 }
205
206 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
211 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 }
226
227 if((get_host_addr(hostname, &haddr))!=0){
228 log_msg(LOG_CRIT, "Failed to lookup name for %s", hostname);
229 close(sock);
230 return NULL;
231 }
232
233 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 close(sock);
242 return NULL;
243 }
244
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 }
250
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 return -1;
277 }
278
279 *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 if((tcp_con=create_tcp_connection(ihost_state->filtermanager_host, ihost_state->filtermanager_port))==NULL){
302 return -1;
303 }
304
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
318 if((tcp_comm(tcp_con, ihost_state->last_modified, &response, "OK"))==0){
319 if((tcp_comm(tcp_con, "END", &response, "OK"))!=0){
320 goto error;
321 }
322 fclose(tcp_con);
323 return 0;
324 }else{
325 if((strcmp(response, "EXPIRED"))!=0){
326 goto error;
327 }
328 }
329 }
330
331 /* If we got to here, the config must of expired */
332
333 if((tcp_comm(tcp_con, "STARTCONFIG", &response, "OK"))!=0){
334 goto error;
335 }
336
337 if((tcp_comm_strdup(tcp_con, "LASTMODIFIED", &response, NULL))!=0){
338 goto error;
339 }
340 last_modified=response;
341
342 if((tcp_comm_strdup(tcp_con, "FILELIST", &response, NULL))!=0){
343 goto error;
344 }
345 file_list=response;
346
347 if((tcp_comm_strdup(tcp_con, "FQDN", &response, NULL))!=0){
348 goto error;
349 }
350 host_fqdn=response;
351
352 if((tcp_comm_strdup(tcp_con, "IP", &response, NULL))!=0){
353 goto error;
354 }
355 host_ip=response;
356
357 if((tcp_comm(tcp_con, "UDPUpdateTime", &response, NULL))!=0){
358 goto error;
359 }
360 udp_update_time=atoi(response);
361
362 if((tcp_comm(tcp_con, "ConfigTTL", &response, NULL))!=0){
363 goto error;
364 }
365 config_ttl=atoi(response);
366
367 if((tcp_comm(tcp_con, "ENDCONFIG", &response, NULL))!=0){
368 goto error;
369 }
370
371 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 /*printf("string : %s\n", response_ptr);*/
391 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 }
398
399 if((tcp_comm(tcp_con, "END", &response, "OK"))!=0){
400 goto error;
401 }
402
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
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
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 }
491
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 }
506
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 }
519
520
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 }
534
535
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 }
548
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 }
567
568
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
583 }
584
585
586 /* 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 "<pages><pageins>%lld</pageins><pageouts>%lld</pageouts></pages>", \
599 x, \
600 y);
601
602 if(strlcat(xml, tmp, size) >= size) goto too_big_error;
603 }
604
605
606 /* get diskio stats */
607
608 if((diskio_stats=get_diskio_stats_diff(&diskio_entries))==NULL){
609 log_msg(LOG_CRIT, "Failed to get diskio statistics");
610 }else{
611 strlcat(xml, "<diskio>", size);
612 for(counter=0;counter<diskio_entries;counter++){
613
614 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
630 strlcat(xml, tmp, size);
631 diskio_stats++;
632 }
633
634 if(strlcat(xml, "</diskio>", size) >= size) goto too_big_error;
635
636 }
637
638
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
654 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
662 strlcat(xml, tmp, size);
663 network_stats++;
664 }
665
666 if(strlcat(xml, "</net>", size) >= size) goto too_big_error;
667
668 }
669
670
671 /* 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
692 strlcat(xml, tmp, size);
693
694 disk_stats++;
695 }
696
697 if(strlcat(xml, "</disk>", size) >= size) goto too_big_error;
698
699 }
700
701
702 if(strlcat(xml, "</packet>", size) >= size) goto too_big_error;
703
704 /*If we got to here, it should of all been filled in nicely now */
705 return 0;
706
707 too_big_error:
708 log_msg(LOG_ERR, "UDP Packet is too large. Throwing away the packet");
709 return -1;
710 }
711
712
713
714 void usage(char *progname){
715 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 exit(1);
728 }
729
730 int main(int argc, char **argv){
731
732 ihost_state_t ihost_state;
733 udp_sockinfo_t udp_sockinfo;
734
735 int cmdopt;
736 extern int optind;
737 pid_t pid;
738 FILE *f;
739 int packet_num=0;
740 int len;
741
742 char packet[MAX_UDP_PACKET_SIZE];
743
744 time_t cur_time, sleep_delay, udp_time=0, config_time=0;
745
746 /* 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 ihost_state.filtermanager_host=DEF_SERVER_NAME;
754 ihost_state.filtermanager_port=DEF_SERVER_PORT;
755 ihost_state.host_fqdn=NULL;
756 ihost_state.host_ip=NULL;
757 ihost_state.preset_fqdn = 0;
758 ihost_state.preset_ip = 0;
759 ihost_state.server_fqdn=NULL;
760 ihost_state.file_list=NULL;
761 ihost_state.last_modified=NULL;
762
763 while((cmdopt=getopt(argc, argv, "vfhVs:i:")) != -1){
764 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 fprintf(stderr, "%s version %s\n", argv[0], VERSION);
776 break;
777 case 'n':
778 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
795 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 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 exit(1);
813 }
814 if(ihost_state.filtermanager_port==0){
815 log_msg(LOG_ERR, "Invalid port number");
816 exit(1);
817 }
818
819 if(ihost_config.daemon){
820 pid=fork();
821 if(pid==-1){
822 log_msg(LOG_CRIT, "Failed to background exiting");
823 exit(1);
824 }else if(pid!=0){
825 /* 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 if((ihost_config.log=fopen(LOG_FILE, "a"))==NULL){
835 ihost_config.log=stderr;
836 log_msg(LOG_CRIT, "Failed to open Logfiles %s for writing", LOG_FILE);
837 exit(1);
838 }
839
840 fclose(stdin);
841 fclose(stdout);
842 fclose(stderr);
843
844 }
845
846 log_msg(LOG_INFO, "Starting ihost...");
847
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 }
873
874 /*printf("%s\n%d\n", ihost_state.server_fqdn, ihost_state.server_udp_port);*/
875 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 }
879
880 config_time=time(NULL)+ihost_state.config_ttl;
881
882 /* Now have config.. collect data and send as often as required */
883 for(;;){
884 cur_time=time(NULL);
885
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 }
897 udp_time=cur_time+ihost_state.udp_update_time;
898 log_msg(LOG_DEBUG, "Next packet should be sent on %d", udp_time);
899 }
900
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
916 log_msg(LOG_DEBUG, "Config expires on %d\n", ihost_state.config_ttl);
917 }
918 }
919
920 sleep_delay=udp_time-time(NULL);
921 log_msg(LOG_DEBUG, "Sleeping for %d", sleep_delay);
922 if(sleep_delay>0) sleep(sleep_delay);
923 }
924
925 return(0);
926 }