1 /*----------------------------------------------------------------------------*/
2 /* Xymon message daemon. */
3 /* */
4 /* Client backend module for BBWin/Windoes client */
5 /* */
6 /* Copyright (C) 2006-2011 Henrik Storner <henrik@hswn.dk> */
7 /* Copyright (C) 2007-2008 Francois Lacroix */
8 /* Copyright (C) 2007-2008 Etienne Grignon <etienne.grignon@gmail.com> */
9 /* */
10 /* This program is released under the GNU General Public License (GPL), */
11 /* version 2. See the file "COPYING" for details. */
12 /* */
13 /*----------------------------------------------------------------------------*/
14
15 static char bbwin_rcsid[] = "$Id: bbwin.c 7886 2016-02-02 20:16:19Z jccleaver $";
16
bbwin_uptime_report(char * hostname,char * clientclass,enum ostype_t os,void * hinfo,char * fromline,char * timestr,char * uptimestr)17 static void bbwin_uptime_report(char *hostname, char *clientclass, enum ostype_t os,
18 void *hinfo, char *fromline, char *timestr,
19 char *uptimestr)
20 {
21 char *p, *myuptimestr = NULL;
22 float loadyellow, loadred;
23 int recentlimit, ancientlimit, uptimecolor, maxclockdiff, clockdiffcolor;
24 long uptimesecs = -1;
25 int upcolor = COL_GREEN;
26 char msgline[4096];
27 strbuffer_t *upmsg;
28
29 if (!want_msgtype(hinfo, MSG_CPU)) return;
30 if (!uptimestr) return;
31
32 dbgprintf("Uptime check host %s\n", hostname);
33
34 uptimesecs = 0;
35
36 /* Parse to check data */
37 p = strstr(uptimestr, "sec:");
38 if (p) {
39 p += strcspn(p, "0123456789\r\n");
40 uptimesecs = atol(p);
41 dbgprintf("uptimestr [%d]\n", uptimesecs); /* DEBUG TODO REMOVE */
42 }
43 /* Parse to show a nice msg */
44 myuptimestr = strchr(uptimestr, '\n');
45 if (myuptimestr) {
46 ++myuptimestr;
47 }
48 get_cpu_thresholds(hinfo, clientclass, &loadyellow, &loadred, &recentlimit, &ancientlimit, &uptimecolor, &maxclockdiff, &clockdiffcolor);
49 dbgprintf("DEBUG recentlimit: [%d] ancienlimit: [%d]\n", recentlimit, ancientlimit); /* DEBUG TODO REMOVE */
50
51 upmsg = newstrbuffer(0);
52 if ((uptimesecs != -1) && (recentlimit != -1) && (uptimesecs < recentlimit)) {
53 if (upcolor != COL_RED) upcolor = uptimecolor;
54 sprintf(msgline, "&%s Machine recently rebooted\n", colorname(uptimecolor));
55 addtobuffer(upmsg, msgline);
56 }
57 if ((uptimesecs != -1) && (ancientlimit != -1) && (uptimesecs > ancientlimit)) {
58 if (upcolor != COL_RED) upcolor = uptimecolor;
59 sprintf(msgline, "&%s Machine has been up more than %d days\n", colorname(uptimecolor), (ancientlimit / 86400));
60 addtobuffer(upmsg, msgline);
61 }
62
63 init_status(upcolor);
64 sprintf(msgline, "status %s.uptime %s %s %s\n",
65 commafy(hostname), colorname(upcolor),
66 (timestr ? timestr : "<No timestamp data>"),
67 ((upcolor == COL_GREEN) ? "OK" : "NOT ok"));
68
69 addtostatus(msgline);
70 /* And add the info if pb */
71 if (STRBUFLEN(upmsg)) {
72 addtostrstatus(upmsg);
73 addtostatus("\n");
74 }
75 /* And add the msg we recevied */
76 if (myuptimestr) {
77 addtostatus(myuptimestr);
78 addtostatus("\n");
79 }
80
81 dbgprintf("msgline %s", msgline); /* DEBUG TODO REMOVE */
82
83 if (fromline && !localmode) addtostatus(fromline);
84 finish_status();
85
86 freestrbuffer(upmsg);
87 }
88
89
bbwin_cpu_report(char * hostname,char * clientclass,enum ostype_t os,void * hinfo,char * fromline,char * timestr,char * cpuutilstr)90 static void bbwin_cpu_report(char *hostname, char *clientclass, enum ostype_t os,
91 void *hinfo, char *fromline, char *timestr,
92 char *cpuutilstr)
93 {
94 char *p, *topstr;
95 float load1, loadyellow, loadred;
96 int recentlimit, ancientlimit, uptimecolor, maxclockdiff, clockdiffcolor;
97 int cpucolor = COL_GREEN;
98
99 char msgline[4096];
100 strbuffer_t *cpumsg;
101
102 if (!want_msgtype(hinfo, MSG_CPU)) return;
103 if (!cpuutilstr) return;
104
105 dbgprintf("CPU check host %s\n", hostname);
106
107 load1 = 0;
108
109 p = strstr(cpuutilstr, "load=");
110 if (p) {
111 p += strcspn(p, "0123456789%\r\n");
112 load1 = atol(p);
113 dbgprintf("load1 [%d]\n", load1); /* DEBUG TODO REMOVE */
114 }
115 topstr = strstr(cpuutilstr, "CPU states");
116 if (topstr) {
117 *(topstr - 1) = '\0';
118 }
119
120 get_cpu_thresholds(hinfo, clientclass, &loadyellow, &loadred, &recentlimit, &ancientlimit, &uptimecolor, &maxclockdiff, &clockdiffcolor);
121 dbgprintf("loadyellow: %d, loadred: %d\n", loadyellow, loadred);
122
123 cpumsg = newstrbuffer(0);
124 if (load1 > loadred) {
125 cpucolor = COL_RED;
126 addtobuffer(cpumsg, "&red Load is CRITICAL\n");
127 }
128 else if (load1 > loadyellow) {
129 cpucolor = COL_YELLOW;
130 addtobuffer(cpumsg, "&yellow Load is HIGH\n");
131 }
132 init_status(cpucolor);
133 sprintf(msgline, "status %s.cpu %s %s %s",
134 commafy(hostname), colorname(cpucolor),
135 (timestr ? timestr : "<No timestamp data>"),
136 cpuutilstr);
137
138 addtostatus(msgline);
139 /* And add the info if pb */
140 if (STRBUFLEN(cpumsg)) {
141 addtostrstatus(cpumsg);
142 addtostatus("\n");
143 }
144 /* And add the msg we recevied */
145 if (topstr) {
146 addtostatus(topstr);
147 addtostatus("\n");
148 }
149
150 dbgprintf("msgline %s", msgline); /* DEBUG TODO REMOVE */
151
152 if (fromline && !localmode) addtostatus(fromline);
153 finish_status();
154
155 freestrbuffer(cpumsg);
156 }
157
bbwin_clock_report(char * hostname,char * clientclass,enum ostype_t os,void * hinfo,char * fromline,char * timestr,char * clockstr,char * msgcachestr)158 static void bbwin_clock_report(char *hostname, char *clientclass, enum ostype_t os,
159 void *hinfo, char *fromline, char *timestr,
160 char *clockstr, char *msgcachestr)
161 {
162 char *myclockstr;
163 int clockcolor = COL_GREEN;
164 float loadyellow, loadred;
165 int recentlimit, ancientlimit, uptimecolor, maxclockdiff, clockdiffcolor;
166 char msgline[4096];
167 strbuffer_t *clockmsg;
168
169 if (!want_msgtype(hinfo, MSG_CPU)) return;
170 if (!clockstr) return;
171
172 dbgprintf("Clock check host %s\n", hostname);
173
174 clockmsg = newstrbuffer(0);
175
176 myclockstr = strstr(clockstr, "local");
177 if (myclockstr) {
178 *(myclockstr - 1) = '\0';
179 }
180
181 get_cpu_thresholds(hinfo, clientclass, &loadyellow, &loadred, &recentlimit, &ancientlimit, &uptimecolor, &maxclockdiff, &clockdiffcolor);
182
183 if (clockstr) {
184 char *p;
185 struct timeval clockval;
186
187 p = strstr(clockstr, "epoch:");
188 if (!p) {
189 /* No epoch reported */
190 }
191 else {
192 struct timeval clockdiff;
193 struct timezone tz;
194 int cachedelay = 0;
195
196 /* The clock may be reported with a decimal part. But not always */
197 p += 6; /* Skip "epoch:" */
198 clockval.tv_sec = atol(p);
199
200 /* See if there's a decimal part */
201 p += strspn(p, "0123456789");
202 if (*p == '.') {
203 p++;
204 clockval.tv_usec = atol(p);
205 }
206 else {
207 clockval.tv_usec = 0;
208 }
209
210 if (msgcachestr) {
211 /* Message passed through msgcache, so adjust for the cache delay */
212 p = strstr(msgcachestr, "Cachedelay:");
213 if (p) cachedelay = atoi(p+11);
214 }
215
216 gettimeofday(&clockdiff, &tz);
217 clockdiff.tv_sec -= (clockval.tv_sec + cachedelay);
218 clockdiff.tv_usec -= clockval.tv_usec;
219 if (clockdiff.tv_usec < 0) {
220 clockdiff.tv_usec += 1000000;
221 clockdiff.tv_sec -= 1;
222 }
223
224 if ((maxclockdiff > 0) && (abs(clockdiff.tv_sec) > maxclockdiff)) {
225 if (clockcolor != COL_RED) clockcolor = clockdiffcolor;
226 sprintf(msgline, "&%s System clock is %ld seconds off (max %ld)\n",
227 colorname(clockdiffcolor), (long) clockdiff.tv_sec, (long) maxclockdiff);
228 addtobuffer(clockmsg, msgline);
229 }
230 else {
231 sprintf(msgline, "System clock is %ld seconds off\n", (long) clockdiff.tv_sec);
232 addtobuffer(clockmsg, msgline);
233 }
234 }
235 }
236
237 init_status(clockcolor);
238 sprintf(msgline, "status %s.timediff %s %s %s\n",
239 commafy(hostname), colorname(clockcolor),
240 (timestr ? timestr : "<No timestamp data>"),
241 ((clockcolor == COL_GREEN) ? "OK" : "NOT ok"));
242
243 addtostatus(msgline);
244 /* And add the info if pb */
245 if (STRBUFLEN(clockmsg)) {
246 addtostrstatus(clockmsg);
247 addtostatus("\n");
248 }
249 /* And add the msg we recevied */
250 if (myclockstr) {
251 addtostatus(myclockstr);
252 addtostatus("\n");
253 }
254
255 dbgprintf("msgline %s", msgline); /* DEBUG TODO REMOVE */
256
257 if (fromline && !localmode) addtostatus(fromline);
258 finish_status();
259
260 freestrbuffer(clockmsg);
261 }
262
bbwin_who_report(char * hostname,char * clientclass,enum ostype_t os,void * hinfo,char * fromline,char * timestr,char * whostr)263 void bbwin_who_report(char *hostname, char *clientclass, enum ostype_t os,
264 void *hinfo, char *fromline, char *timestr, char *whostr)
265 {
266 int whocolor = COL_GREEN;
267 char msgline[4096];
268 strbuffer_t *whomsg;
269
270 if (!want_msgtype(hinfo, MSG_WHO)) return;
271 if (!whostr) return;
272
273 dbgprintf("Who check host %s\n", hostname);
274
275 whomsg = newstrbuffer(0);
276
277 init_status(whocolor);
278 sprintf(msgline, "status %s.who %s %s %s\n",
279 commafy(hostname), colorname(whocolor),
280 (timestr ? timestr : "<No timestamp data>"),
281 ((whocolor == COL_GREEN) ? "OK" : "NOT ok"));
282
283 addtostatus(msgline);
284 /* And add the info if pb */
285 if (STRBUFLEN(whomsg)) {
286 addtostrstatus(whomsg);
287 addtostatus("\n");
288 }
289 /* And add the msg we recevied */
290 if (whostr) {
291 addtostatus(whostr);
292 addtostatus("\n");
293 }
294
295 dbgprintf("msgline %s", msgline); /* DEBUG TODO REMOVE */
296
297 if (fromline && !localmode) addtostatus(fromline);
298 finish_status();
299
300 freestrbuffer(whomsg);
301 }
302
bbwin_svcs_report(char * hostname,char * clientclass,enum ostype_t os,void * hinfo,char * fromline,char * timestr,int namecol,int startupcol,int statecol,char * svcstr,char * svcauto)303 void bbwin_svcs_report(char *hostname, char *clientclass, enum ostype_t os,
304 void *hinfo, char *fromline, char *timestr,
305 int namecol, int startupcol, int statecol, char *svcstr, char *svcauto)
306 {
307 int svccolor = -1;
308 int schecks;
309 char msgline[4096];
310 static strbuffer_t *monmsg = NULL;
311 char *group;
312
313 if (!want_msgtype(hinfo, MSG_SVCS)) return;
314 if (!svcstr) return;
315
316 if (!monmsg) monmsg = newstrbuffer(0);
317
318 dbgprintf("Services check host %s\n", hostname);
319
320 clearalertgroups();
321 schecks = clear_svc_counts(hinfo, clientclass);
322 dbgprintf("schecks: [%d]\n", schecks); /* DEBUG TODO REMOVE */
323
324 if (schecks > 0) {
325 /* Count how many instances of each monitored condition are found */
326 char *sname, *bol, *nl;
327 int scount, scolor;
328 char *namestr, *startupstr, *statestr;
329
330 bol = svcstr;
331 while (bol) {
332 char *p;
333
334 nl = strchr(bol, '\n'); if (nl) *nl = '\0';
335
336 /* Data lines */
337
338 p = strdup(bol); namestr = getcolumn(p, namecol);
339 strcpy(p, bol); startupstr = getcolumn(p, startupcol);
340 strcpy(p, bol); statestr = getcolumn(p, statecol);
341
342 add_svc_count(namestr, startupstr, statestr);
343
344 xfree(p);
345
346 if (nl) { *nl = '\n'; bol = nl+1; } else bol = NULL;
347 }
348
349 /* Check the status and state found for each monitored svc */
350 while ((sname = check_svc_count(&scount, &scolor, &group)) != NULL) {
351
352 if (scolor > svccolor) svccolor = scolor;
353
354 if (scolor == COL_GREEN) {
355 sprintf(msgline, "&green %s\n", sname);
356 addtobuffer(monmsg, msgline);
357 }
358 else {
359 sprintf(msgline, "&%s %s\n",
360 colorname(scolor), sname);
361 addtobuffer(monmsg, msgline);
362 addalertgroup(group);
363 }
364 }
365 }
366
367 if ((svccolor == -1) && sendclearsvcs) {
368 /* Nothing to check */
369 addtobuffer(monmsg, "No Services checks defined\n");
370 svccolor = noreportcolor;
371 }
372
373 if (svccolor != -1) {
374 if (svcauto && strlen(svcauto) > 1 &&
375 (svccolor == COL_GREEN || svccolor == noreportcolor))
376 svccolor = COL_YELLOW;
377
378 /* Now we know the result, so generate a status message */
379 init_status(svccolor);
380
381 group = getalertgroups();
382 if (group) sprintf(msgline, "status/group:%s ", group); else strcpy(msgline, "status ");
383 addtostatus(msgline);
384
385 sprintf(msgline, "%s.svcs %s %s - Services %s\n",
386 commafy(hostname), colorname(svccolor),
387 (timestr ? timestr : "<No timestamp data>"),
388 ((svccolor == COL_GREEN) ? "OK" : "NOT ok"));
389 addtostatus(msgline);
390
391 /* And add the info about what's wrong */
392 addtostrstatus(monmsg);
393 addtostatus("\n");
394 clearstrbuffer(monmsg);
395
396 /* Add AutoRestart status */
397 if (svcauto && strlen(svcauto) > 1) {
398 addtostatus(svcauto); addtostatus("\n\n");
399 }
400
401 /* And the full svc output for those who want it */
402 if (svclistinsvcs) addtostatus(svcstr);
403
404 if (fromline) addtostatus(fromline);
405 finish_status();
406 }
407 else {
408 clearstrbuffer(monmsg);
409 }
410 }
411
handle_win32_bbwin_client(char * hostname,char * clienttype,enum ostype_t os,void * hinfo,char * sender,time_t timestamp,char * clientdata)412 void handle_win32_bbwin_client(char *hostname, char *clienttype, enum ostype_t os,
413 void *hinfo, char *sender, time_t timestamp,
414 char *clientdata)
415 {
416 char *timestr;
417 char *cpuutilstr;
418 char *uptimestr;
419 char *clockstr;
420 char *msgcachestr;
421 char *diskstr;
422 char *procsstr;
423 char *msgsstr;
424 char *portsstr;
425 char *memorystr;
426 char *netstatstr;
427 char *ifstatstr;
428 char *svcstr;
429 char *svcauto;
430 char *whostr;
431
432 char fromline[1024];
433
434 sprintf(fromline, "\nStatus message received from %s\n", sender);
435
436 splitmsg(clientdata);
437
438 /* Get all data by section timestr is the date time for all status */
439 timestr = getdata("date");
440 if (!timestr) return;
441
442 uptimestr = getdata("uptime");
443 clockstr = getdata("clock");
444 msgcachestr = getdata("msgcache"); /* TODO check when it is usefull */
445 cpuutilstr = getdata("cpu");
446 procsstr = getdata("procs");
447 diskstr = getdata("disk");
448 portsstr = getdata("ports");
449 memorystr = getdata("memory");
450 msgsstr = getdata("msg");
451 netstatstr = getdata("netstat");
452 ifstatstr = getdata("ifstat");
453 svcstr = getdata("svcs");
454 svcauto = getdata("svcautorestart");
455 whostr = getdata("who");
456
457 bbwin_uptime_report(hostname, clienttype, os, hinfo, fromline, timestr, uptimestr);
458 bbwin_clock_report(hostname, clienttype, os, hinfo, fromline, timestr, clockstr, msgcachestr);
459 bbwin_cpu_report(hostname, clienttype, os, hinfo, fromline, timestr, cpuutilstr);
460 unix_procs_report(hostname, clienttype, os, hinfo, fromline, timestr, "Name", NULL, procsstr);
461 unix_ports_report(hostname, clienttype, os, hinfo, fromline, timestr, 1, 2, 3, portsstr);
462 unix_disk_report(hostname, clienttype, os, hinfo, fromline, timestr, "Avail", "Capacity", "Filesystem", diskstr);
463 bbwin_svcs_report(hostname, clienttype, os, hinfo, fromline, timestr, 0, 1, 2, svcstr, svcauto);
464 bbwin_who_report(hostname, clienttype, os, hinfo, fromline, timestr, whostr);
465
466 msgs_report(hostname, clienttype, os, hinfo, fromline, timestr, msgsstr);
467 file_report(hostname, clienttype, os, hinfo, fromline, timestr);
468 linecount_report(hostname, clienttype, os, hinfo, fromline, timestr);
469 deltacount_report(hostname, clienttype, os, hinfo, fromline, timestr);
470
471 /* Data status */
472 unix_netstat_report(hostname, clienttype, os, hinfo, fromline, timestr, netstatstr);
473 unix_ifstat_report(hostname, clienttype, os, hinfo, fromline, timestr, ifstatstr);
474
475 if (memorystr) {
476 char *p;
477 long memphystotal, memphysused,
478 memactused, memacttotal,
479 memswaptotal, memswapused;
480
481 memphystotal = memswaptotal = memphysused = memswapused = memactused = memacttotal = -1;
482 p = strstr(memorystr, "\nphysical:");
483 if (p) sscanf(p, "\nphysical: %ld %ld", &memphystotal, &memphysused);
484 p = strstr(memorystr, "\npage:");
485 if (p) sscanf(p, "\npage: %ld %ld", &memswaptotal, &memswapused);
486 p = strstr(memorystr, "\nvirtual:");
487 if (p) sscanf(p, "\nvirtual: %ld %ld", &memacttotal, &memactused);
488 dbgprintf("DEBUG Memory %ld %ld %ld %ld %ld %ld\n", memphystotal, memphysused, memacttotal, memactused, memswaptotal, memswapused); /* DEBUG TODO Remove*/
489 unix_memory_report(hostname, clienttype, os, hinfo, fromline, timestr,
490 memphystotal, memphysused, memacttotal, memactused, memswaptotal, memswapused);
491 }
492
493 splitmsg_done();
494 }
495