# | Line 1 | Line 1 | |
---|---|---|
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> | |
2 | – | #include <sys/socket.h> |
21 | #include <stdlib.h> | |
22 | + | #include <sys/types.h> |
23 | #include <unistd.h> | |
24 | #include <syslog.h> | |
25 | #include <netinet/in.h> | |
26 | < | #include <ukcprog.h> |
26 | > | #include "ukcprog.h" |
27 | #include <netdb.h> | |
28 | < | #include <strings.h> |
28 | > | #include <string.h> |
29 | > | #include "statgrab.h" |
30 | > | #include <time.h> |
31 | > | #include <sys/socket.h> |
32 | > | #include <netinet/in.h> |
33 | > | #include <arpa/inet.h> |
34 | > | #include <syslog.h> |
35 | ||
36 | + | #define versionNo 0.8 |
37 | #define RECONFIGURE_RETURN_CODE 2 | |
38 | + | #define UDP_MAX_PACKET_SIZE 8192 |
39 | ||
40 | + | #define logmessage(level, ...) do { cur_level = level; errf(__VA_ARGS__); } while (0) |
41 | + | |
42 | typedef struct{ | |
43 | int fm_port; | |
44 | char *fm_host; | |
45 | < | |
45 | > | |
46 | > | char *my_ip; |
47 | char *my_fqdn; | |
48 | char *server_fqdn; | |
49 | int server_udp_port; | |
# | Line 26 | Line 56 | typedef struct{ | |
56 | ||
57 | }ihost_state_t; | |
58 | ||
59 | < | char* sock_comm(FILE *f_r, FILE *f_w, char* sendString){ |
59 | > | static int log_level; |
60 | > | static int cur_level; |
61 | > | static int syslog_logging; |
62 | > | |
63 | > | void log_errors(const char *message){ |
64 | > | if(log_level>=cur_level){ |
65 | > | if (syslog_logging==1){ |
66 | > | syslog(cur_level, "%s\n", message); |
67 | > | }else{ |
68 | > | fprintf(stderr, "%s\n", message); |
69 | > | } |
70 | > | } |
71 | > | } |
72 | > | |
73 | > | char* sock_comm(FILE *f_r, FILE *f_w, char *sendString){ |
74 | char *reply; | |
75 | < | fprintf(f_w, "%s", sendString); |
75 | > | fprintf(f_w, "%s\n", sendString); |
76 | fflush(f_w); | |
77 | reply=fpgetline(f_r); | |
78 | /* Returns pointer to static buffer */ | |
# | Line 38 | Line 82 | char* sock_comm(FILE *f_r, FILE *f_w, char* sendString | |
82 | int ihost_configure(ihost_state_t *ihost_state){ | |
83 | struct sockaddr_in addr; | |
84 | struct in_addr haddr; | |
85 | + | struct sockaddr ip; |
86 | + | int ip_len; |
87 | int sd; | |
88 | FILE *fm_fd_r, *fm_fd_w; | |
89 | char *reply; | |
90 | char *reply_ptr; | |
91 | ||
92 | + | /* Check to see if anything needs to be free'd */ |
93 | + | if (ihost_state->my_fqdn!=NULL) free(ihost_state->my_fqdn); |
94 | + | if (ihost_state->server_fqdn!=NULL) free(ihost_state->server_fqdn); |
95 | + | if (ihost_state->last_modified!=NULL) free(ihost_state->last_modified); |
96 | + | if (ihost_state->files_list!=NULL) free(ihost_state->files_list); |
97 | + | |
98 | + | logmessage(LOG_DEBUG, "Setting up configure socket to %s on port %d", ihost_state->fm_host, ihost_state->fm_port); |
99 | if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { | |
100 | < | errf("Can't create AF_INET socket (%m)"); |
100 | > | logmessage(LOG_ERR, "Can't create AF_INET socket (%m)"); |
101 | return -1; | |
102 | } | |
103 | ||
104 | if (get_host_addr(ihost_state->fm_host, &haddr) != 0){ | |
105 | < | errf("Failed to resolve address %s (%m)", ihost_state->fm_host); |
105 | > | logmessage(LOG_ERR, "Failed to resolve address %s (%m)", ihost_state->fm_host); |
106 | return -1; | |
107 | } | |
108 | ||
109 | < | memset((char *)&addr, 0, sizeof addr); |
109 | > | memset(&addr, 0, sizeof addr); |
110 | addr.sin_family = AF_INET; | |
111 | < | memcpy((char *)&addr.sin_addr, &haddr, sizeof haddr); |
111 | > | memcpy(&addr.sin_addr, &haddr, sizeof haddr); |
112 | addr.sin_port = htons(ihost_state->fm_port); | |
113 | ||
114 | if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) { | |
115 | < | errf("Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port); |
115 | > | logmessage(LOG_ERR, "Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port); |
116 | return -1; | |
117 | } | |
118 | ||
119 | /* Need to open 2 files, one for reading one for writing, as it gets confused if we only use 1 :) */ | |
120 | if ((fm_fd_r=fdopen(sd,"r")) == NULL){ | |
121 | < | errf("Failed to open stream (%m)"); |
121 | > | logmessage(LOG_ERR, "Failed to open read stream (%m)"); |
122 | return -1; | |
123 | } | |
124 | ||
125 | if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){ | |
126 | < | errf("Failed to open stream (%m)"); |
126 | > | logmessage(LOG_ERR, "Failed to open write stream (%m)"); |
127 | return -1; | |
128 | } | |
129 | < | |
130 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "STARTCONFIG\n"); |
129 | > | ip_len=sizeof ip; |
130 | > | memset(&ip, 0, ip_len); |
131 | > | if((getsockname(sd, &ip, &ip_len)) != 0){ |
132 | > | logmessage(LOG_ERR, "Failed to get IP address (%m)"); |
133 | > | return -1; |
134 | > | } |
135 | > | if (ip.sa_family!=AF_INET){ |
136 | > | logmessage(LOG_ERR, "sa family is wrong type"); |
137 | > | return -1; |
138 | > | } |
139 | > | |
140 | > | if((ihost_state->my_ip=inet_ntoa(((struct sockaddr_in *)&ip)->sin_addr))==NULL){ |
141 | > | logmessage(LOG_ERR, "Failed to get IP (%m)"); |
142 | > | return -1; |
143 | > | } |
144 | > | |
145 | > | logmessage(LOG_DEBUG, "Sending STARTCONIG"); |
146 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "STARTCONFIG"); |
147 | if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) { | |
148 | < | errf("Server error"); |
148 | > | logmessage(LOG_ERR, "Server error on STARTCONFIG"); |
149 | return -1; | |
150 | } | |
151 | ||
152 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "LASTMODIFIED\n"); |
152 | > | logmessage(LOG_DEBUG, "Sending LASTMODIFIED"); |
153 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "LASTMODIFIED"); |
154 | if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){ | |
155 | < | errf("Server error (%m)"); |
155 | > | logmessage(LOG_ERR, "Server error on LASTMODIFIED (%m)"); |
156 | return -1; | |
157 | } | |
158 | if((ihost_state->last_modified=strdup(reply)) == NULL){ | |
159 | < | errf("strdup failed (%m)"); |
159 | > | logmessage(LOG_ERR, "strdup failed (%m)"); |
160 | return -1; | |
161 | } | |
162 | < | |
163 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "FILELIST\n"); |
162 | > | |
163 | > | logmessage(LOG_DEBUG, "Sending FILELIST"); |
164 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "FILELIST"); |
165 | if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){ | |
166 | < | errf("Server error (%m)"); |
166 | > | logmessage(LOG_ERR, "Server error on FILELIST (%m)"); |
167 | return -1; | |
168 | } | |
169 | < | if((ihost_state->files_list=strdup(reply)) == NULL){ |
170 | < | errf("strdup failed (%m)"); |
171 | < | return -1; |
172 | < | } |
169 | > | if((ihost_state->files_list=strdup(reply)) == NULL){ |
170 | > | logmessage(LOG_ERR, "strdup failed (%m)"); |
171 | > | return -1; |
172 | > | } |
173 | ||
174 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "FQDN\n"); |
174 | > | logmessage(LOG_DEBUG, "Sending FQDN"); |
175 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "FQDN"); |
176 | if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){ | |
177 | < | errf("Server error (%m)"); |
177 | > | logmessage(LOG_ERR, "Server error on FQDN (%m)"); |
178 | return -1; | |
179 | } | |
180 | if((ihost_state->my_fqdn=strdup(reply)) == NULL){ | |
181 | < | errf("strdup failed (%m)"); |
181 | > | logmessage(LOG_ERR, "strdup failed (%m)"); |
182 | return -1; | |
183 | } | |
184 | ||
185 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "UDPUpdateTime\n"); |
185 | > | logmessage(LOG_DEBUG, "Sending FQDN"); |
186 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "UDPUpdateTime"); |
187 | if(reply== NULL){ | |
188 | < | errf("Server error (%m)"); |
188 | > | logmessage(LOG_ERR, "Server error (%m)"); |
189 | return -1; | |
190 | } | |
191 | if (strncasecmp(reply, "ERROR", 5) != 0){ | |
192 | ihost_state->udp_update_time=atoi(reply); | |
193 | } | |
194 | < | |
195 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "TCPUpdateTime\n"); |
194 | > | |
195 | > | logmessage(LOG_DEBUG, "Sending TCPUpdateTime"); |
196 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "TCPUpdateTime"); |
197 | if(reply== NULL){ | |
198 | < | errf("Server error (%m)"); |
198 | > | logmessage(LOG_ERR, "Server error on TCPUpdateTime (%m)"); |
199 | return -1; | |
200 | } | |
201 | if (strncasecmp(reply, "ERROR", 5) != 0){ | |
202 | ihost_state->tcp_update_time=atoi(reply); | |
203 | } | |
204 | ||
205 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "ENDCONFIG\n"); |
205 | > | logmessage(LOG_DEBUG, "Sending ENDCONFIG"); |
206 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "ENDCONFIG"); |
207 | if(reply== NULL){ | |
208 | < | errf("Server error (%m)"); |
208 | > | logmessage(LOG_ERR, "Server error on ENDCONFIG (%m)"); |
209 | return -1; | |
210 | } | |
211 | ||
212 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "FILTER\n"); |
212 | > | logmessage(LOG_DEBUG, "Sending FILTER"); |
213 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "FILTER"); |
214 | if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){ | |
215 | < | errf("Server error (%m)"); |
215 | > | logmessage(LOG_ERR, "Server error FILTER failed (%m)"); |
216 | return -1; | |
217 | } | |
218 | reply_ptr=strchr(reply,';'); | |
219 | if (reply_ptr==NULL){ | |
220 | < | errf("Incorrect data returned"); |
220 | > | logmessage(LOG_ERR, "Incorrect data returned"); |
221 | return -1; | |
222 | } | |
223 | *reply_ptr='\0'; | |
224 | if((ihost_state->server_fqdn=strdup(reply)) == NULL){ | |
225 | < | errf("strdup failed (%m)"); |
225 | > | logmessage(LOG_ERR, "strdup failed (%m)"); |
226 | return -1; | |
227 | } | |
228 | < | reply=++reply_ptr; |
228 | > | reply=reply_ptr + 1; |
229 | reply_ptr=strchr(reply,';'); | |
230 | if (reply_ptr==NULL){ | |
231 | < | errf("Incorrect data returned 2"); |
231 | > | logmessage(LOG_ERR, "Incorrect data returned 2"); |
232 | return -1; | |
233 | } | |
234 | *reply_ptr='\0'; | |
235 | ihost_state->server_udp_port=atoi(reply); | |
236 | < | reply=++reply_ptr; |
236 | > | reply=reply_ptr+1; |
237 | ihost_state->server_tcp_port=atoi(reply); | |
238 | if ((ihost_state->server_tcp_port==0) || (ihost_state->server_udp_port==0)){ | |
239 | < | errf("Incorrect data returned 3 "); |
239 | > | logmessage(LOG_ERR, "Incorrect data returned 3 "); |
240 | return -1; | |
241 | } | |
242 | ||
243 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "END\n"); |
243 | > | logmessage(LOG_DEBUG, "Sending END"); |
244 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "END"); |
245 | if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){ | |
246 | < | errf("Server error (%m)"); |
246 | > | logmessage(LOG_ERR, "Server error on END (%m)"); |
247 | return -1; | |
248 | } | |
249 | ||
250 | if(fclose(fm_fd_r) !=0){ | |
251 | < | errf("Failed to close FD (%m)"); |
251 | > | logmessage(LOG_ERR, "Failed to close read FD (%m)"); |
252 | return -1; | |
253 | } | |
254 | if(fclose(fm_fd_w) !=0){ | |
255 | < | errf("Failed to close FD (%m)"); |
255 | > | logmessage(LOG_ERR, "Failed to close write FD (%m)"); |
256 | return -1; | |
257 | } | |
258 | ||
# | Line 190 | Line 267 | int heartbeat(ihost_state_t *ihost_state){ | |
267 | char *reply; | |
268 | int exitcode=0; | |
269 | ||
270 | + | logmessage(LOG_DEBUG, "Setting up configure socket to %s on port %d", ihost_state->server_fqdn, ihost_state->server_tcp_port); |
271 | if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { | |
272 | < | errf("Can't create AF_INET socket (%m)"); |
272 | > | logmessage(LOG_ERR, "Can't create AF_INET socket (%m)"); |
273 | return -1; | |
274 | } | |
275 | ||
276 | if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){ | |
277 | < | errf("Failed to resolve address %s (%m)", ihost_state->fm_host); |
277 | > | logmessage(LOG_ERR, "Failed to resolve address %s (%m)", ihost_state->server_fqdn); |
278 | return -1; | |
279 | } | |
280 | ||
281 | < | memset((char *)&addr, 0, sizeof addr); |
281 | > | memset(&addr, 0, sizeof addr); |
282 | addr.sin_family = AF_INET; | |
283 | < | memcpy((char *)&addr.sin_addr, &haddr, sizeof haddr); |
283 | > | memcpy(&addr.sin_addr, &haddr, sizeof haddr); |
284 | addr.sin_port = htons(ihost_state->server_tcp_port); | |
285 | ||
286 | if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) { | |
287 | < | errf("Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port); |
287 | > | logmessage(LOG_ERR, "Failed to connect to %s on port %d (%m)", ihost_state->server_fqdn, ihost_state->server_tcp_port); |
288 | return -1; | |
289 | } | |
290 | ||
291 | /* Need to open 2 files, one for reading one for writing, as it gets confused if we only use 1 :) */ | |
292 | if ((fm_fd_r=fdopen(sd,"r")) == NULL){ | |
293 | < | errf("Failed to open stream (%m)"); |
293 | > | logmessage(LOG_ERR, "Failed to open stream (%m)"); |
294 | return -1; | |
295 | } | |
296 | ||
297 | if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){ | |
298 | < | errf("Failed to open stream (%m)"); |
298 | > | logmessage(LOG_ERR, "Failed to open stream (%m)"); |
299 | return -1; | |
300 | } | |
301 | ||
302 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "HEARTBEAT\n"); |
303 | < | if ((reply==NULL) || (strncasecmp(reply, "ERROR", 2) == 0) ) { |
304 | < | errf("Server error"); |
302 | > | logmessage(LOG_DEBUG, "Sending HEARTBEAT"); |
303 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "HEARTBEAT"); |
304 | > | if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) { |
305 | > | logmessage(LOG_ERR, "Server error on HEARTBEAT"); |
306 | return -1; | |
307 | } | |
308 | ||
309 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "CONFIG\n"); |
310 | < | if ((reply==NULL) || (strncasecmp(reply, "ERROR", 2) == 0) ) { |
311 | < | errf("Server error"); |
309 | > | logmessage(LOG_DEBUG, "Sending CONFIG"); |
310 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "CONFIG"); |
311 | > | if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) { |
312 | > | logmessage(LOG_ERR, "Server error on CONFIG"); |
313 | return -1; | |
314 | } | |
315 | ||
316 | + | logmessage(LOG_DEBUG, "Sending %s", ihost_state->files_list); |
317 | reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->files_list); | |
318 | if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) { | |
319 | < | errf("Server error"); |
319 | > | logmessage(LOG_ERR, "Server error on fileslist"); |
320 | return -1; | |
321 | } | |
322 | ||
323 | + | logmessage(LOG_DEBUG, "Sending %s", ihost_state->last_modified); |
324 | reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->last_modified); | |
325 | if (reply==NULL) { | |
326 | < | errf("Server error"); |
326 | > | logmessage(LOG_ERR, "Server error NULL recieved on lastmodified"); |
327 | return -1; | |
328 | } | |
329 | < | if (strncasecmp(reply, "ERROR", 2) == 0){ |
329 | > | if (strncasecmp(reply, "ERROR", 5) == 0){ |
330 | /* Means the config has changed */ | |
331 | + | logmessage(LOG_INFO, "Recieved ERROR from server for a reconfigure required"); |
332 | exitcode=RECONFIGURE_RETURN_CODE; | |
333 | } | |
334 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "KEY\n"); |
335 | < | if ((reply==NULL) || (strncasecmp(reply, "ERROR", 2) == 0) ) { |
336 | < | errf("Server error"); |
334 | > | |
335 | > | logmessage(LOG_DEBUG,"Sending KEY"); |
336 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "KEY"); |
337 | > | if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) { |
338 | > | logmessage(LOG_ERR, "Server error on KEY"); |
339 | return -1; | |
340 | } | |
341 | < | |
341 | > | if (ihost_state->key!=NULL) free(ihost_state->key); |
342 | > | |
343 | if((ihost_state->key=strdup(reply)) == NULL){ | |
344 | < | errf("strdup failed (%m)"); |
344 | > | logmessage(LOG_ERR, "strdup failed (%m)"); |
345 | return -1; | |
346 | } | |
347 | ||
348 | < | reply=sock_comm(fm_fd_r, fm_fd_w, "END\n"); |
348 | > | logmessage(LOG_DEBUG,"Sending ENDHEARTBEAT"); |
349 | > | reply=sock_comm(fm_fd_r, fm_fd_w, "ENDHEARTBEAT"); |
350 | if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){ | |
351 | < | errf("Server error (%m)"); |
351 | > | logmessage(LOG_ERR, "Server error on ENDHEARTBEAT (%m)"); |
352 | return -1; | |
353 | } | |
354 | ||
355 | + | fflush(fm_fd_r); |
356 | + | fflush(fm_fd_w); |
357 | + | |
358 | + | if(fclose(fm_fd_r) !=0){ |
359 | + | logmessage(LOG_ERR, "Failed to close read FD (%m)"); |
360 | + | return -1; |
361 | + | } |
362 | + | if(fclose(fm_fd_w) !=0){ |
363 | + | logmessage(LOG_ERR, "Failed to close write FD (%m)"); |
364 | + | return -1; |
365 | + | } |
366 | + | |
367 | return exitcode; | |
368 | } | |
369 | ||
370 | + | char *stat_grab(ihost_state_t *ihost_state, int counter){ |
371 | + | #define NUM_STATS 9 |
372 | + | char *stats[NUM_STATS]; |
373 | + | char *xml_data=NULL; |
374 | + | char *xml_data_p; |
375 | + | int x=0; |
376 | ||
377 | + | logmessage(LOG_DEBUG,"get_cpu_stats"); |
378 | + | stats[0]=get_cpu_stats(); |
379 | + | logmessage(LOG_DEBUG,"get_disk_stats"); |
380 | + | stats[1]=get_disk_stats(); |
381 | + | logmessage(LOG_DEBUG,"get_load_stats"); |
382 | + | stats[2]=get_load_stats(); |
383 | + | logmessage(LOG_DEBUG,"get_memory_stats"); |
384 | + | stats[3]=get_memory_stats(); |
385 | + | logmessage(LOG_DEBUG,"get_os_info"); |
386 | + | stats[4]=get_os_info(); |
387 | + | logmessage(LOG_DEBUG,"get_page_stats"); |
388 | + | stats[5]=get_page_stats(); |
389 | + | logmessage(LOG_DEBUG,"get_process_stats"); |
390 | + | stats[6]=get_process_stats(); |
391 | + | logmessage(LOG_DEBUG,"get_swap_stats"); |
392 | + | stats[7]=get_swap_stats(); |
393 | + | logmessage(LOG_DEBUG,"get_user_stats"); |
394 | + | stats[8]=get_user_stats(); |
395 | + | |
396 | + | for(;x<NUM_STATS;x++){ |
397 | + | if(stats[x]==NULL){ |
398 | + | logmessage(LOG_ERR,"Function returned NULL"); |
399 | + | return NULL; |
400 | + | } |
401 | + | if(xml_data==NULL){ |
402 | + | if((xml_data=strf("%s", stats[x])) == NULL){ |
403 | + | logmessage(LOG_ERR, "str failed (%m)"); |
404 | + | return NULL; |
405 | + | } |
406 | + | }else{ |
407 | + | xml_data_p=xml_data; |
408 | + | if((xml_data=strf("%s%s", xml_data, stats[x])) == NULL){ |
409 | + | logmessage(LOG_ERR, "str failed (%m)"); |
410 | + | return NULL; |
411 | + | } |
412 | + | free(xml_data_p); |
413 | + | } |
414 | + | free(stats[x]); |
415 | + | } |
416 | + | xml_data_p=xml_data; |
417 | + | 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); |
418 | + | free(xml_data_p); |
419 | + | |
420 | + | logmessage(LOG_DEBUG,"Generated XML Data of : %s", xml_data); |
421 | + | return xml_data; |
422 | + | } |
423 | + | |
424 | + | int send_stats(ihost_state_t *ihost_state, char *data_stream){ |
425 | + | struct sockaddr_in addr; |
426 | + | struct in_addr haddr; |
427 | + | |
428 | + | int sd; |
429 | + | size_t len; |
430 | + | |
431 | + | len=strlen(data_stream); |
432 | + | if(len>UDP_MAX_PACKET_SIZE){ |
433 | + | logmessage(LOG_ERR, "Too big to send to server. Please reconfigure client and server and recompile"); |
434 | + | exit(1); |
435 | + | } |
436 | + | logmessage(LOG_DEBUG,"Resolving IP of server"); |
437 | + | if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){ |
438 | + | logmessage(LOG_ERR, "Failed to resolve address %s (%m)", ihost_state->server_fqdn); |
439 | + | return -1; |
440 | + | } |
441 | + | logmessage(LOG_DEBUG,"Creating UDP connection to %s on %d",ihost_state->server_fqdn, ihost_state->server_udp_port); |
442 | + | if((sd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){ |
443 | + | logmessage(LOG_ERR, "failed to create UDP socket (%m)"); |
444 | + | return -1; |
445 | + | } |
446 | + | |
447 | + | memset(&addr, 0, sizeof(addr)); |
448 | + | addr.sin_family=AF_INET; |
449 | + | memcpy((char *)&addr.sin_addr, &haddr, sizeof haddr); |
450 | + | addr.sin_port = htons(ihost_state->server_udp_port); |
451 | + | |
452 | + | logmessage(LOG_INFO,"Sending packet : %s", data_stream); |
453 | + | if((sendto(sd, data_stream, len, 0, (struct sockaddr *) &addr, sizeof(addr))) != len){ |
454 | + | logmessage(LOG_ERR, "Send the wrong number of bytes (%m)"); |
455 | + | return -1; |
456 | + | } |
457 | + | |
458 | + | close(sd); |
459 | + | |
460 | + | return 0; |
461 | + | } |
462 | + | |
463 | + | void usage(char *progname){ |
464 | + | fprintf(stderr, "Usage %s [options] server port\n", progname); |
465 | + | fprintf(stderr, "Options\n"); |
466 | + | fprintf(stderr, " -v Verbose, the more v flags the more verbose, eg -vv\n"); |
467 | + | fprintf(stderr, " -d Daemon mode, self backgrounding\n"); |
468 | + | fprintf(stderr, " -s Send errors to syslog\n"); |
469 | + | fprintf(stderr, " -V Print version number\n"); |
470 | + | fprintf(stderr, " -h Prints this help page\n"); |
471 | + | exit(1); |
472 | + | } |
473 | + | |
474 | int main(int argc, char **argv){ | |
475 | ihost_state_t ihost_state; | |
476 | + | int heartbeat_exit; |
477 | + | int counter=0; |
478 | + | long udp_time=0, tcp_time=0, stat_grab_time=0, cur_time=0; |
479 | + | int sleep_delay=0; |
480 | + | char *xml_stats; |
481 | + | pid_t pid; |
482 | + | int cmdopt; |
483 | + | extern int optind; |
484 | + | int verbose=0, daemon=0; |
485 | + | extern int syslog_logging; |
486 | + | extern int log_level; |
487 | + | extern int cur_level; |
488 | + | |
489 | + | log_level=1; |
490 | + | cur_level=1; |
491 | + | syslog_logging=0; |
492 | + | |
493 | + | errf_set_ofunc(log_errors); |
494 | + | /* NULL'ify so i can tell if i need to free it or not */ |
495 | + | ihost_state.fm_host=NULL; |
496 | + | ihost_state.my_fqdn=NULL; |
497 | + | ihost_state.server_fqdn=NULL; |
498 | + | ihost_state.last_modified=NULL; |
499 | + | ihost_state.files_list=NULL; |
500 | + | ihost_state.key=NULL; |
501 | + | |
502 | errf_set_progname(argv[0]); | |
503 | < | if(argc!=3){ |
504 | < | errf_usage("<host> <port>"); |
503 | > | |
504 | > | |
505 | > | while((cmdopt=getopt(argc, argv, "vdshV")) != -1){ |
506 | > | switch(cmdopt){ |
507 | > | case 'v': |
508 | > | verbose++; |
509 | > | break; |
510 | > | |
511 | > | case 'd': |
512 | > | /* Force syslog logging since stderr will be closed in this case */ |
513 | > | syslog_logging=1; |
514 | > | daemon=1; |
515 | > | break; |
516 | > | |
517 | > | case 's': |
518 | > | syslog_logging=1; |
519 | > | break; |
520 | > | |
521 | > | case 'h': |
522 | > | usage(argv[0]); |
523 | > | break; |
524 | > | |
525 | > | case 'V': |
526 | > | errf("%s version %f",argv[0], versionNo); |
527 | > | break; |
528 | > | |
529 | > | default: |
530 | > | usage(argv[0]); |
531 | > | exit(1); |
532 | > | } |
533 | > | } |
534 | > | |
535 | > | if(argc!=optind+2){ |
536 | > | usage(argv[0]); |
537 | exit(1); | |
538 | } | |
539 | + | ihost_state.fm_host=argv[optind]; |
540 | + | ihost_state.fm_port=atoi(argv[optind+1]); |
541 | + | if(ihost_state.fm_port==0){ |
542 | + | errf("Invalid port number"); |
543 | + | usage(argv[0]); |
544 | + | } |
545 | ||
546 | < | ihost_state.fm_host=argv[1]; |
547 | < | ihost_state.fm_port=atoi(argv[2]); |
546 | > | if(daemon==1){ |
547 | > | pid=fork(); |
548 | > | if(pid==-1){ |
549 | > | errf("Fork failed, can't background. Exiting"); |
550 | > | exit(1); |
551 | > | }else if(pid!=0){ |
552 | > | /* Parent process */ |
553 | > | return 0; |
554 | > | } |
555 | > | /* We should now be in the background*/ |
556 | > | if(setsid()==-1){ |
557 | > | errf("setsid failed (%m)"); |
558 | > | exit(1); |
559 | > | } |
560 | > | fclose(stdin); |
561 | > | fclose(stdout); |
562 | > | fclose(stderr); |
563 | > | } |
564 | ||
565 | + | if(syslog_logging==1){ |
566 | + | openlog(errf_get_progname(),0,LOG_ERR); |
567 | + | setlogmask(LOG_UPTO(LOG_DEBUG)); |
568 | + | } |
569 | + | |
570 | + | switch(verbose){ |
571 | + | case 0: |
572 | + | /* Critical errors + */ |
573 | + | log_level=LOG_ERR; |
574 | + | break; |
575 | + | case 1: |
576 | + | /* Recoverable errors */ |
577 | + | log_level=LOG_WARNING; |
578 | + | break; |
579 | + | case 2: |
580 | + | /* Print stuff like the XML packets */ |
581 | + | log_level=LOG_INFO; |
582 | + | break; |
583 | + | default: |
584 | + | /* Must have lots of v's */ |
585 | + | /* Print out everything its doing */ |
586 | + | log_level=LOG_DEBUG; |
587 | + | break; |
588 | + | } |
589 | + | |
590 | if(ihost_configure(&ihost_state)!=0){ | |
591 | < | errf("configure failed"); |
591 | > | logmessage(LOG_ERR,"configure failed"); |
592 | > | /* Ok, ideally we prob should have 2 copies of the structure and carry on if this |
593 | > | happens.. But we dont :) (at the moment) */ |
594 | > | exit(1); |
595 | } | |
596 | ||
597 | + | for(;;){ |
598 | + | cur_time=time(NULL); |
599 | + | if(cur_time>=tcp_time){ |
600 | + | logmessage(LOG_DEBUG,"Sending heartbeat"); |
601 | + | heartbeat_exit=heartbeat(&ihost_state); |
602 | + | if(heartbeat_exit==RECONFIGURE_RETURN_CODE){ |
603 | + | logmessage(LOG_INFO,"heartbeat needs to be reconfigured"); |
604 | + | ihost_configure(&ihost_state); |
605 | + | udp_time=0; |
606 | + | } |
607 | + | if(heartbeat_exit==-1){ |
608 | + | logmessage(LOG_ERR,"Heartbeat failed"); |
609 | + | exit(1); |
610 | + | } |
611 | + | tcp_time=time(NULL)+ihost_state.tcp_update_time; |
612 | + | logmessage(LOG_DEBUG,"next tcp time should be %d", tcp_time); |
613 | + | } |
614 | + | |
615 | + | if(cur_time>=udp_time){ |
616 | + | logmessage(LOG_DEBUG,"Sending udp data"); |
617 | + | |
618 | + | stat_grab_time=time(NULL); |
619 | + | if((xml_stats=stat_grab(&ihost_state, counter++)) == NULL){ |
620 | + | logmessage(LOG_ERR,"Failed to get stats (%m)"); |
621 | + | exit(1); |
622 | + | } |
623 | + | stat_grab_time=time(NULL)-stat_grab_time; |
624 | + | send_stats(&ihost_state, xml_stats); |
625 | + | free(xml_stats); |
626 | + | udp_time=time(NULL)+ihost_state.udp_update_time-stat_grab_time; |
627 | + | logmessage(LOG_DEBUG,"next udp time should be %d", udp_time); |
628 | + | } |
629 | + | |
630 | + | if(tcp_time<udp_time){ |
631 | + | sleep_delay=tcp_time-time(NULL); |
632 | + | }else{ |
633 | + | sleep_delay=udp_time-time(NULL); |
634 | + | } |
635 | + | logmessage(LOG_DEBUG,"Sleeping for %d", sleep_delay); |
636 | + | if(sleep_delay>0) sleep(sleep_delay); |
637 | + | } |
638 | return 0; | |
639 | } | |
640 |
– | Removed lines |
+ | Added lines |
< | Changed lines |
> | Changed lines |