ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/ihost/ihost.c
Revision: 1.17
Committed: Mon May 20 12:28:46 2002 UTC (22 years ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.16: +52 -5 lines
Log Message:
Proper command line parsing, however doesn't do anything with the options yet :)

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * Copyright (C) 2000-2002 i-scream
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <syslog.h>
24 #include <netinet/in.h>
25 #include "ukcprog.h"
26 #include <netdb.h>
27 #include <string.h>
28 #include "statgrab.h"
29 #include <time.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33
34 #define versionNo 0.8
35 #define RECONFIGURE_RETURN_CODE 2
36 #define UDP_MAX_PACKET_SIZE 8192
37
38 typedef struct{
39 int fm_port;
40 char *fm_host;
41
42 char *my_ip;
43 char *my_fqdn;
44 char *server_fqdn;
45 int server_udp_port;
46 int server_tcp_port;
47 char *last_modified;
48 char *files_list;
49 char *key;
50 int udp_update_time;
51 int tcp_update_time;
52
53 }ihost_state_t;
54
55 char* sock_comm(FILE *f_r, FILE *f_w, char *sendString){
56 char *reply;
57 fprintf(f_w, "%s\n", sendString);
58 fflush(f_w);
59 reply=fpgetline(f_r);
60 /* Returns pointer to static buffer */
61 return reply;
62 }
63
64 int ihost_configure(ihost_state_t *ihost_state){
65 struct sockaddr_in addr;
66 struct in_addr haddr;
67 struct sockaddr ip;
68 int ip_len;
69 int sd;
70 FILE *fm_fd_r, *fm_fd_w;
71 char *reply;
72 char *reply_ptr;
73
74 /* Check to see if anything needs to be free'd */
75 if (ihost_state->my_fqdn!=NULL) free(ihost_state->my_fqdn);
76 if (ihost_state->server_fqdn!=NULL) free(ihost_state->server_fqdn);
77 if (ihost_state->last_modified!=NULL) free(ihost_state->last_modified);
78 if (ihost_state->files_list!=NULL) free(ihost_state->files_list);
79
80 if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
81 errf("Can't create AF_INET socket (%m)");
82 return -1;
83 }
84
85 if (get_host_addr(ihost_state->fm_host, &haddr) != 0){
86 errf("Failed to resolve address %s (%m)", ihost_state->fm_host);
87 return -1;
88 }
89
90 memset(&addr, 0, sizeof addr);
91 addr.sin_family = AF_INET;
92 memcpy(&addr.sin_addr, &haddr, sizeof haddr);
93 addr.sin_port = htons(ihost_state->fm_port);
94
95 if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) {
96 errf("Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port);
97 return -1;
98 }
99
100 /* Need to open 2 files, one for reading one for writing, as it gets confused if we only use 1 :) */
101 if ((fm_fd_r=fdopen(sd,"r")) == NULL){
102 errf("Failed to open read stream (%m)");
103 return -1;
104 }
105
106 if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){
107 errf("Failed to open write stream (%m)");
108 return -1;
109 }
110 ip_len=sizeof ip;
111 memset(&ip, 0, ip_len);
112 if((getsockname(sd, &ip, &ip_len)) != 0){
113 errf("Failed to get IP address (%m)");
114 return -1;
115 }
116 if (ip.sa_family!=AF_INET){
117 errf("sa family is wrong type");
118 return -1;
119 }
120
121 if((ihost_state->my_ip=inet_ntoa(((struct sockaddr_in *)&ip)->sin_addr))==NULL){
122 errf("Failed to get IP (%m)");
123 return -1;
124 }
125
126 reply=sock_comm(fm_fd_r, fm_fd_w, "STARTCONFIG");
127 if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) {
128 errf("Server error");
129 return -1;
130 }
131
132 reply=sock_comm(fm_fd_r, fm_fd_w, "LASTMODIFIED");
133 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){
134 errf("Server error (%m)");
135 return -1;
136 }
137 if((ihost_state->last_modified=strdup(reply)) == NULL){
138 errf("strdup failed (%m)");
139 return -1;
140 }
141
142 reply=sock_comm(fm_fd_r, fm_fd_w, "FILELIST");
143 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){
144 errf("Server error (%m)");
145 return -1;
146 }
147 if((ihost_state->files_list=strdup(reply)) == NULL){
148 errf("strdup failed (%m)");
149 return -1;
150 }
151
152 reply=sock_comm(fm_fd_r, fm_fd_w, "FQDN");
153 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){
154 errf("Server error (%m)");
155 return -1;
156 }
157 if((ihost_state->my_fqdn=strdup(reply)) == NULL){
158 errf("strdup failed (%m)");
159 return -1;
160 }
161
162 reply=sock_comm(fm_fd_r, fm_fd_w, "UDPUpdateTime");
163 if(reply== NULL){
164 errf("Server error (%m)");
165 return -1;
166 }
167 if (strncasecmp(reply, "ERROR", 5) != 0){
168 ihost_state->udp_update_time=atoi(reply);
169 }
170
171 reply=sock_comm(fm_fd_r, fm_fd_w, "TCPUpdateTime");
172 if(reply== NULL){
173 errf("Server error (%m)");
174 return -1;
175 }
176 if (strncasecmp(reply, "ERROR", 5) != 0){
177 ihost_state->tcp_update_time=atoi(reply);
178 }
179
180 reply=sock_comm(fm_fd_r, fm_fd_w, "ENDCONFIG");
181 if(reply== NULL){
182 errf("Server error (%m)");
183 return -1;
184 }
185
186 reply=sock_comm(fm_fd_r, fm_fd_w, "FILTER");
187 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){
188 errf("Server error FILTER failed (%m)");
189 return -1;
190 }
191 reply_ptr=strchr(reply,';');
192 if (reply_ptr==NULL){
193 errf("Incorrect data returned");
194 return -1;
195 }
196 *reply_ptr='\0';
197 if((ihost_state->server_fqdn=strdup(reply)) == NULL){
198 errf("strdup failed (%m)");
199 return -1;
200 }
201 reply=reply_ptr + 1;
202 reply_ptr=strchr(reply,';');
203 if (reply_ptr==NULL){
204 errf("Incorrect data returned 2");
205 return -1;
206 }
207 *reply_ptr='\0';
208 ihost_state->server_udp_port=atoi(reply);
209 reply=reply_ptr+1;
210 ihost_state->server_tcp_port=atoi(reply);
211 if ((ihost_state->server_tcp_port==0) || (ihost_state->server_udp_port==0)){
212 errf("Incorrect data returned 3 ");
213 return -1;
214 }
215
216 reply=sock_comm(fm_fd_r, fm_fd_w, "END");
217 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){
218 errf("Server error (%m)");
219 return -1;
220 }
221
222 if(fclose(fm_fd_r) !=0){
223 errf("Failed to close read FD (%m)");
224 return -1;
225 }
226 if(fclose(fm_fd_w) !=0){
227 errf("Failed to close write FD (%m)");
228 return -1;
229 }
230
231 return 0;
232 }
233
234 int heartbeat(ihost_state_t *ihost_state){
235 struct sockaddr_in addr;
236 struct in_addr haddr;
237 int sd;
238 FILE *fm_fd_r, *fm_fd_w;
239 char *reply;
240 int exitcode=0;
241
242 if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
243 errf("Can't create AF_INET socket (%m)");
244 return -1;
245 }
246
247 if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){
248 errf("Failed to resolve address %s (%m)", ihost_state->fm_host);
249 return -1;
250 }
251
252 memset(&addr, 0, sizeof addr);
253 addr.sin_family = AF_INET;
254 memcpy(&addr.sin_addr, &haddr, sizeof haddr);
255 addr.sin_port = htons(ihost_state->server_tcp_port);
256
257 if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) {
258 errf("Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port);
259 return -1;
260 }
261
262 /* Need to open 2 files, one for reading one for writing, as it gets confused if we only use 1 :) */
263 if ((fm_fd_r=fdopen(sd,"r")) == NULL){
264 errf("Failed to open stream (%m)");
265 return -1;
266 }
267
268 if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){
269 errf("Failed to open stream (%m)");
270 return -1;
271 }
272
273 reply=sock_comm(fm_fd_r, fm_fd_w, "HEARTBEAT");
274 if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) {
275 errf("Server error");
276 return -1;
277 }
278
279 reply=sock_comm(fm_fd_r, fm_fd_w, "CONFIG");
280 if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) {
281 errf("Server error");
282 return -1;
283 }
284
285 reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->files_list);
286 if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) {
287 errf("Server error");
288 return -1;
289 }
290
291 reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->last_modified);
292 if (reply==NULL) {
293 errf("Server error");
294 return -1;
295 }
296 if (strncasecmp(reply, "ERROR", 5) == 0){
297 /* Means the config has changed */
298 exitcode=RECONFIGURE_RETURN_CODE;
299 }
300 reply=sock_comm(fm_fd_r, fm_fd_w, "KEY");
301 if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) {
302 errf("Server error");
303 return -1;
304 }
305 if (ihost_state->key!=NULL) free(ihost_state->key);
306
307 if((ihost_state->key=strdup(reply)) == NULL){
308 errf("strdup failed (%m)");
309 return -1;
310 }
311
312 reply=sock_comm(fm_fd_r, fm_fd_w, "ENDHEARTBEAT");
313 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){
314 errf("Server error (%m)");
315 return -1;
316 }
317
318 fflush(fm_fd_r);
319 fflush(fm_fd_w);
320
321 if(fclose(fm_fd_r) !=0){
322 errf("Failed to close read FD (%m)");
323 return -1;
324 }
325 if(fclose(fm_fd_w) !=0){
326 errf("Failed to close write FD (%m)");
327 return -1;
328 }
329
330 return exitcode;
331 }
332
333 char *stat_grab(ihost_state_t *ihost_state, int counter){
334 #define NUM_STATS 9
335 char *stats[NUM_STATS];
336 char *xml_data=NULL;
337 char *xml_data_p;
338 int x=0;
339
340 stats[0]=get_cpu_stats();
341 stats[1]=get_disk_stats();
342 stats[2]=get_load_stats();
343 stats[3]=get_memory_stats();
344 stats[4]=get_os_info();
345 stats[5]=get_page_stats();
346 stats[6]=get_process_stats();
347 stats[7]=get_swap_stats();
348 stats[8]=get_user_stats();
349
350 for(;x<NUM_STATS;x++){
351 if(stats[x]==NULL){
352 return NULL;
353 }
354 if(xml_data==NULL){
355 if((xml_data=strf("%s", stats[x])) == NULL){
356 errf("str failed (%m)");
357 return NULL;
358 }
359 }else{
360 xml_data_p=xml_data;
361 if((xml_data=strf("%s%s", xml_data, stats[x])) == NULL){
362 errf("str failed (%m)");
363 return NULL;
364 }
365 free(xml_data_p);
366 }
367 free(stats[x]);
368 }
369 xml_data_p=xml_data;
370 xml_data=strf("<packet seq_no=\"%d\" machine_name=\"%s\" date=\"%ld\" type=\"data\" ip=\"%s\" key=\"%s\">%s</packet>", counter, ihost_state->my_fqdn, time(NULL), ihost_state->my_ip, ihost_state->key, xml_data);
371 free(xml_data_p);
372
373 return xml_data;
374 }
375
376 int send_stats(ihost_state_t *ihost_state, char *data_stream){
377 struct sockaddr_in addr;
378 struct in_addr haddr;
379
380 int sd;
381 size_t len;
382
383 len=strlen(data_stream);
384 if(len>UDP_MAX_PACKET_SIZE){
385 errf("Too big to send to server. Please reconfigure client and server and recompile");
386 exit(1);
387 }
388
389 if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){
390 errf("Failed to resolve address %s (%m)", ihost_state->fm_host);
391 return -1;
392 }
393
394 if((sd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
395 errf("failed to create UDP socket (%m)");
396 return -1;
397 }
398
399 memset(&addr, 0, sizeof(addr));
400 addr.sin_family=AF_INET;
401 memcpy((char *)&addr.sin_addr, &haddr, sizeof haddr);
402 addr.sin_port = htons(ihost_state->server_udp_port);
403
404 if((sendto(sd, data_stream, len, 0, (struct sockaddr *) &addr, sizeof(addr))) != len){
405 errf("Send the wrong number of bytes (%m)");
406 return -1;
407 }
408
409 close(sd);
410
411 return 0;
412 }
413
414 void usage(char *progname){
415 fprintf(stderr, "Usage %s [options] server port\n", progname);
416 fprintf(stderr, "Options\n");
417 fprintf(stderr, " -v Verbose, the more v flags the more verbose, eg -vv\n");
418 fprintf(stderr, " -d Daemon mode, self backgrounding\n");
419 fprintf(stderr, " -s Send errors to syslog\n");
420 fprintf(stderr, " -V Print version number\n");
421 fprintf(stderr, " -h Prints this help page\n");
422 exit(1);
423 }
424
425 int main(int argc, char **argv){
426 ihost_state_t ihost_state;
427 int heartbeat_exit;
428 int counter=0;
429 long udp_time=0, tcp_time=0, stat_grab_time=0, cur_time=0;
430 int sleep_delay=0;
431 char *xml_stats;
432
433 int cmdopt;
434 extern int optind;
435 int verbose=0, daemon=0, syslog=0 ;
436
437 /* NULL'ify so i can tell if i need to free it or not */
438 ihost_state.fm_host=NULL;
439 ihost_state.my_fqdn=NULL;
440 ihost_state.server_fqdn=NULL;
441 ihost_state.last_modified=NULL;
442 ihost_state.files_list=NULL;
443 ihost_state.key=NULL;
444
445 errf_set_progname(argv[0]);
446
447 while((cmdopt=getopt(argc, argv, "vdshV")) != -1){
448 switch(cmdopt){
449 case 'v':
450 verbose++;
451 break;
452
453 case 'd':
454 daemon=1;
455 break;
456
457 case 's':
458 syslog=1;
459 break;
460
461 case 'h':
462 usage(argv[0]);
463 break;
464 case 'V':
465 errf("%s version %f",argv[0], versionNo);
466 break;
467 default:
468 usage(argv[0]);
469 exit(1);
470 }
471 }
472
473 if(argc!=optind+2){
474 usage(argv[0]);
475 exit(1);
476 }
477 ihost_state.fm_host=argv[optind];
478 ihost_state.fm_port=atoi(argv[optind+1]);
479 if(ihost_state.fm_port==0){
480 errf("Invalid port number");
481 usage(argv[0]);
482 }
483 printf("%s\n%d\n",ihost_state.fm_host, ihost_state.fm_port);
484
485 if(ihost_configure(&ihost_state)!=0){
486 errf("configure failed");
487 /* Ok, ideally we prob should have 2 copies of the structure and carry on if this
488 happens.. But we dont :) (at the moment) */
489 exit(1);
490 }
491
492 for(;;){
493 cur_time=time(NULL);
494 if(cur_time>=tcp_time){
495 /*printf("sending TCP\n");*/
496 heartbeat_exit=heartbeat(&ihost_state);
497 if(heartbeat_exit==RECONFIGURE_RETURN_CODE){
498 /*errf("heartbeat needs to be reconfigured");*/
499 ihost_configure(&ihost_state);
500 /* So udp doesn't wait til next sending before updating */
501 udp_time=0;
502 }
503 if(heartbeat_exit==-1){
504 errf("ah crap");
505 exit(1);
506 }
507 tcp_time=time(NULL)+ihost_state.tcp_update_time;
508 }
509
510 if(cur_time>=udp_time){
511 /*printf("sending UDP\n");*/
512 stat_grab_time=time(NULL);
513 if((xml_stats=stat_grab(&ihost_state, counter++)) == NULL){
514 errf("Failed to get stats (%m)");
515 exit(1);
516 }
517 stat_grab_time=time(NULL)-stat_grab_time;
518 send_stats(&ihost_state, xml_stats);
519 free(xml_stats);
520 udp_time=time(NULL)+ihost_state.udp_update_time-stat_grab_time;
521 }
522
523 if(tcp_time<udp_time){
524 sleep_delay=tcp_time-time(NULL);
525 }else{
526 sleep_delay=udp_time-time(NULL);
527 }
528
529 /*printf("tcp epoc: %ld \t udp epoc: %ld\ntime:%ld \tsleeping: %d\n", tcp_time, udp_time, time(NULL), sleep_delay);*/
530 if(sleep_delay>0) sleep(sleep_delay);
531 }
532 return 0;
533 }
534