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