1 /*----------------------------------------------------------------------------*/
2 /* Xymon message daemon. */
3 /* */
4 /* Client backend module */
5 /* This file has routines that load the xymond_client configuration and */
6 /* finds the rules relevant for a particular test when applied. */
7 /* */
8 /* Copyright (C) 2005-2011 Henrik Storner <henrik@hswn.dk> */
9 /* "PORT" handling (C) Mirko Saam */
10 /* */
11 /* This program is released under the GNU General Public License (GPL), */
12 /* version 2. See the file "COPYING" for details. */
13 /* */
14 /*----------------------------------------------------------------------------*/
15
16 static char rcsid[] = "$Id: client_config.c 8068 2019-07-23 14:46:23Z jccleaver $";
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/time.h>
23 #include <signal.h>
24 #include <time.h>
25 #include <ctype.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <limits.h>
29 #include <errno.h>
30
31 #include <pcre.h>
32
33 #include "libxymon.h"
34 #include "client_config.h"
35
36 typedef struct exprlist_t {
37 char *pattern;
38 pcre *exp;
39 struct exprlist_t *next;
40 } exprlist_t;
41
42 typedef struct c_load_t {
43 float warnlevel, paniclevel;
44 } c_load_t;
45
46 typedef struct c_uptime_t {
47 int recentlimit, ancientlimit, color;
48 } c_uptime_t;
49
50 typedef struct c_clock_t {
51 int maxdiff, color;
52 } c_clock_t;
53
54 typedef struct c_disk_t {
55 exprlist_t *fsexp;
56 long warnlevel, paniclevel;
57 int abswarn, abspanic;
58 int dmin, dmax, dcount;
59 int color;
60 int ignored;
61 } c_disk_t;
62
63 typedef struct c_inode_t {
64 exprlist_t *fsexp;
65 long warnlevel, paniclevel;
66 int abswarn, abspanic;
67 int imin, imax, icount;
68 int color;
69 int ignored;
70 } c_inode_t;
71
72 typedef struct c_mem_t {
73 enum { C_MEM_PHYS, C_MEM_SWAP, C_MEM_ACT } memtype;
74 int warnlevel, paniclevel;
75 } c_mem_t;
76
77 typedef struct c_zos_mem_t {
78 enum { C_MEM_CSA, C_MEM_ECSA, C_MEM_SQA, C_MEM_ESQA } zos_memtype;
79 int warnlevel, paniclevel;
80 } c_zos_mem_t;
81
82 typedef struct c_zvse_vsize_t {
83 int warnlevel, paniclevel;
84 } c_zvse_vsize_t;
85
86 typedef struct c_zvse_getvis_t {
87 exprlist_t *partid;
88 int warnlevel, paniclevel;
89 int anywarnlevel, anypaniclevel;
90 } c_zvse_getvis_t;
91
92 typedef struct c_cics_t {
93 exprlist_t *applid; /* CICS Application Identifier */
94 int dsawarnlevel, dsapaniclevel;
95 int edsawarnlevel, edsapaniclevel;
96 } c_cics_t;
97
98 typedef struct c_asid_t {
99 enum { C_ASID_MAXUSER, C_ASID_NPARTS } asidtype;
100 int warnlevel, paniclevel;
101 } c_asid_t;
102
103 typedef struct c_proc_t {
104 exprlist_t *procexp;
105 int pmin, pmax, pcount;
106 int color;
107 } c_proc_t;
108
109 typedef struct c_log_t {
110 exprlist_t *logfile;
111 exprlist_t *matchexp, *matchone, *ignoreexp;
112 int color;
113 } c_log_t;
114
115 typedef struct c_paging_t {
116 int warnlevel, paniclevel;
117 } c_paging_t;
118
119 #define FCHK_NOEXIST (1 << 0)
120 #define FCHK_TYPE (1 << 1)
121 #define FCHK_MODE (1 << 2)
122 #define FCHK_MINLINKS (1 << 3)
123 #define FCHK_MAXLINKS (1 << 4)
124 #define FCHK_EQLLINKS (1 << 5)
125 #define FCHK_MINSIZE (1 << 6)
126 #define FCHK_MAXSIZE (1 << 7)
127 #define FCHK_EQLSIZE (1 << 8)
128 #define FCHK_OWNERID (1 << 10)
129 #define FCHK_OWNERSTR (1 << 11)
130 #define FCHK_GROUPID (1 << 12)
131 #define FCHK_GROUPSTR (1 << 13)
132 #define FCHK_CTIMEMIN (1 << 16)
133 #define FCHK_CTIMEMAX (1 << 17)
134 #define FCHK_CTIMEEQL (1 << 18)
135 #define FCHK_MTIMEMIN (1 << 19)
136 #define FCHK_MTIMEMAX (1 << 20)
137 #define FCHK_MTIMEEQL (1 << 21)
138 #define FCHK_ATIMEMIN (1 << 22)
139 #define FCHK_ATIMEMAX (1 << 23)
140 #define FCHK_ATIMEEQL (1 << 24)
141 #define FCHK_MD5 (1 << 25)
142 #define FCHK_SHA1 (1 << 26)
143 #define FCHK_SHA256 (1 << 27)
144 #define FCHK_SHA512 (1 << 28)
145 #define FCHK_SHA224 (1 << 29)
146 #define FCHK_SHA384 (1 << 30)
147 #define FCHK_RMD160 (1 << 31)
148
149 #define CHK_OPTIONAL (1 << 0)
150 #define CHK_TRACKIT (1 << 1)
151
152 typedef struct c_file_t {
153 exprlist_t *filename;
154 int color;
155 int ftype;
156 off_t minsize, maxsize, eqlsize;
157 unsigned int minlinks, maxlinks, eqllinks;
158 unsigned int fmode;
159 int ownerid, groupid;
160 char *ownerstr, *groupstr;
161 unsigned int minctimedif, maxctimedif, ctimeeql;
162 unsigned int minmtimedif, maxmtimedif, mtimeeql;
163 unsigned int minatimedif, maxatimedif, atimeeql;
164 char *md5hash, *sha1hash, *sha256hash, *sha512hash, *sha224hash, *sha384hash, *rmd160hash;
165 } c_file_t;
166
167 typedef struct c_dir_t {
168 exprlist_t *filename;
169 int color;
170 unsigned long maxsize, minsize;
171 } c_dir_t;
172
173 typedef struct c_port_t {
174 exprlist_t *localexp;
175 exprlist_t *exlocalexp;
176 exprlist_t *remoteexp;
177 exprlist_t *exremoteexp;
178 exprlist_t *stateexp;
179 exprlist_t *exstateexp;
180 int pmin, pmax, pcount;
181 int color;
182 } c_port_t;
183
184 typedef struct c_svc_t {
185 exprlist_t *svcexp;
186 exprlist_t *stateexp;
187 exprlist_t *startupexp;
188 char *svcname, *startup, *state;
189 int scount;
190 int color;
191 } c_svc_t;
192
193 #define MIBCHK_MINVALUE (1 << 0)
194 #define MIBCHK_MAXVALUE (1 << 1)
195 #define MIBCHK_MATCH (1 << 2)
196 typedef struct c_mibval_t {
197 exprlist_t *mibvalexp; /* Key composed of the mib name and the value name */
198 exprlist_t *keyexp; /* Match pattern for the mib table key */
199 int color;
200 long minval, maxval;
201 exprlist_t *matchexp;
202
203 /*
204 * For optimization, we build a tree of c_rule_t pointers, indexed by a key
205 * which is combined from the mib-, key- and value-names. This tree is updated
206 * and/or used whenever an actual lookup happens for the thresholds.
207 * So when doing a lookup, we first check to see if the combination is in the
208 * tree; if not, then we scan the list by matching against the keyexp pattern
209 * and update the tree with the result.
210 */
211 int havetree;
212 void * valdeftree;
213 } c_mibval_t;
214
215 #define RRDDSCHK_GT (1 << 0)
216 #define RRDDSCHK_GE (1 << 1)
217 #define RRDDSCHK_LT (1 << 2)
218 #define RRDDSCHK_LE (1 << 3)
219 #define RRDDSCHK_EQ (1 << 4)
220 #define RRDDSCHK_INTVL (1 << 29)
221 typedef struct c_rrdds_t {
222 exprlist_t *rrdkey; /* Pattern match for filename of the RRD file */
223 char *rrdds; /* DS name */
224 char *column; /* Status column modified by this check */
225 int color;
226 /* For absolute min/max values of the data item */
227 double limitval, limitval2;
228 } c_rrdds_t;
229
230
231 typedef struct c_mq_queue_t {
232 exprlist_t *qmgrname, *qname;
233 int warnlen, critlen;
234 int warnage, critage;
235 } c_mq_queue_t;
236
237 typedef struct c_mq_channel_t {
238 exprlist_t *qmgrname, *chnname, *warnstates, *alertstates;
239 } c_mq_channel_t;
240
241 typedef enum { C_LOAD, C_UPTIME, C_CLOCK, C_DISK, C_INODE, C_MEM, C_PROC, C_LOG, C_FILE, C_DIR, C_PORT, C_SVC, C_CICS, C_PAGING, C_MEM_GETVIS, C_MEM_VSIZE, C_ASID, C_RRDDS, C_MQ_QUEUE, C_MQ_CHANNEL, C_MIBVAL } ruletype_t;
242
243 typedef struct c_rule_t {
244 exprlist_t *hostexp;
245 exprlist_t *exhostexp;
246 exprlist_t *pageexp;
247 exprlist_t *expageexp;
248 exprlist_t *dgexp;
249 exprlist_t *exdgexp;
250 exprlist_t *classexp;
251 exprlist_t *exclassexp;
252 char *timespec, *extimespec, *statustext, *rrdidstr, *groups;
253 ruletype_t ruletype;
254 int cfid;
255 uint32_t flags;
256 uint32_t chkflags;
257 struct c_rule_t *next;
258 union {
259 c_load_t load;
260 c_uptime_t uptime;
261 c_clock_t clock;
262 c_disk_t disk;
263 c_inode_t inode;
264 c_mem_t mem;
265 c_zos_mem_t zos_mem;
266 c_zvse_vsize_t zvse_vsize;
267 c_zvse_getvis_t zvse_getvis;
268 c_cics_t cics;
269 c_asid_t asid;
270 c_proc_t proc;
271 c_log_t log;
272 c_file_t fcheck;
273 c_dir_t dcheck;
274 c_port_t port;
275 c_svc_t svc;
276 c_paging_t paging;
277 c_mibval_t mibval;
278 c_rrdds_t rrdds;
279 c_mq_queue_t mqqueue;
280 c_mq_channel_t mqchannel;
281 } rule;
282 } c_rule_t;
283
284 static c_rule_t *rulehead = NULL;
285 static c_rule_t *ruletail = NULL;
286 static exprlist_t *exprhead = NULL;
287
288 /* ruletree is a tree indexed by hostname of the rules. */
289 typedef struct ruleset_t {
290 c_rule_t *rule;
291 struct ruleset_t *next;
292 } ruleset_t;
293 static int havetree = 0;
294 static void * ruletree;
295
296
filesize_value(char * s)297 static off_t filesize_value(char *s)
298 {
299 /* s is the size in BYTES */
300 char *modifier;
301 off_t result;
302
303 modifier = (s + strspn(s, " 0123456789"));
304
305 #ifdef _LARGEFILE_SOURCE
306 result = (off_t) str2ll(s, NULL);
307 #else
308 result = (off_t) atol(s);
309 #endif
310
311 switch (*modifier) {
312 case 'K': case 'k':
313 result = (result << 10);
314 break;
315
316 case 'M': case 'm':
317 result = (result << 20);
318 break;
319
320 case 'G': case 'g':
321 result = (result << 30);
322 break;
323
324 case 'T': case 't':
325 result = (result << 40);
326 break;
327
328 default:
329 break;
330 }
331
332 return result;
333 }
334
ruleset(char * hostname,char * pagename,char * classname)335 static ruleset_t *ruleset(char *hostname, char *pagename, char *classname)
336 {
337 /*
338 * This routine manages a list of rules that apply to a particular host.
339 *
340 * We maintain a tree indexed by hostname. Each node in the tree contains
341 * a list of c_rule_t records, which point to individual rules in the full
342 * list of rules. So instead of walking the entire list of rules for all hosts,
343 * we can just go through those rules that are relevant for a given host.
344 * This should speed up client-rule matching tremendously, since all of
345 * the expensive pagename/hostname matches are only performed initially
346 * when the list of rules for the host is decided.
347 */
348 xtreePos_t handle;
349 c_rule_t *rwalk;
350 ruleset_t *head, *tail, *itm;
351 char *pagenamecopy, *pgtok;
352 int pgmatchres, pgexclres;
353
354 handle = xtreeFind(ruletree, hostname);
355 if (handle != xtreeEnd(ruletree)) {
356 /* We have the tree for this host */
357 return (ruleset_t *)xtreeData(ruletree, handle);
358 }
359
360 pagenamecopy = strdup(pagename);
361
362 /* We must build the list of rules for this host */
363 head = tail = NULL;
364 for (rwalk = rulehead; (rwalk); rwalk = rwalk->next) {
365 if (rwalk->exclassexp && namematch(classname, rwalk->exclassexp->pattern, rwalk->exclassexp->exp)) continue;
366 if (rwalk->classexp && !namematch(classname, rwalk->classexp->pattern, rwalk->classexp->exp)) continue;
367 if (rwalk->exhostexp && namematch(hostname, rwalk->exhostexp->pattern, rwalk->exhostexp->exp)) continue;
368 if (rwalk->hostexp && !namematch(hostname, rwalk->hostexp->pattern, rwalk->hostexp->exp)) continue;
369 if (rwalk->exdgexp && namematch(hostname, rwalk->exdgexp->pattern, rwalk->exdgexp->exp)) continue;
370 if (rwalk->dgexp && !namematch(hostname, rwalk->dgexp->pattern, rwalk->dgexp->exp)) continue;
371
372 pgmatchres = pgexclres = -1;
373 pgtok = strtok(pagenamecopy, ",");
374 while (pgtok) {
375 if (rwalk->pageexp && (pgmatchres != 1))
376 pgmatchres = (namematch(pgtok, rwalk->pageexp->pattern, rwalk->pageexp->exp) ? 1 : 0);
377
378 if (rwalk->expageexp && (pgexclres != 1))
379 pgexclres = (namematch(pgtok, rwalk->expageexp->pattern, rwalk->expageexp->exp) ? 1 : 0);
380
381 pgtok = strtok(NULL, ",");
382 }
383 if (pgexclres == 1) continue;
384 if (pgmatchres == 0) continue;
385
386 /* All criteria match - add this rule to the list of rules for this host */
387 itm = (ruleset_t *)calloc(1, sizeof(ruleset_t));
388 itm->rule = rwalk;
389 itm->next = NULL;
390 if (head == NULL) {
391 head = tail = itm;
392 }
393 else {
394 tail->next = itm;
395 tail = itm;
396 }
397 }
398
399 /* Add the list to the tree */
400 xtreeAdd(ruletree, strdup(hostname), head);
401
402 xfree(pagenamecopy);
403
404 return head;
405 }
406
setup_expr(char * ptn,int multiline)407 static exprlist_t *setup_expr(char *ptn, int multiline)
408 {
409 exprlist_t *newitem = (exprlist_t *)calloc(1, sizeof(exprlist_t));
410
411 newitem->pattern = strdup(ptn);
412 if (*ptn == '%') {
413 if (multiline)
414 newitem->exp = multilineregex(ptn+1);
415 else
416 newitem->exp = compileregex(ptn+1);
417 }
418 newitem->next = exprhead;
419 exprhead = newitem;
420
421 return newitem;
422 }
423
setup_rule(ruletype_t ruletype,exprlist_t * curhost,exprlist_t * curexhost,exprlist_t * curpage,exprlist_t * curexpage,exprlist_t * curdg,exprlist_t * curexdg,exprlist_t * curclass,exprlist_t * curexclass,char * curtime,char * curextime,char * curtext,char * curgroup,int cfid)424 static c_rule_t *setup_rule(ruletype_t ruletype,
425 exprlist_t *curhost, exprlist_t *curexhost,
426 exprlist_t *curpage, exprlist_t *curexpage,
427 exprlist_t *curdg, exprlist_t *curexdg,
428 exprlist_t *curclass, exprlist_t *curexclass,
429 char *curtime, char *curextime, char *curtext, char *curgroup,
430 int cfid)
431 {
432 c_rule_t *newitem = (c_rule_t *)calloc(1, sizeof(c_rule_t));
433 if (ruletail) { ruletail->next = newitem; ruletail = newitem; }
434 else rulehead = ruletail = newitem;
435
436 newitem->ruletype = ruletype;
437 newitem->hostexp = curhost;
438 newitem->exhostexp = curexhost;
439 newitem->pageexp = curpage;
440 newitem->expageexp = curexpage;
441 newitem->dgexp = curdg;
442 newitem->exdgexp = curexdg;
443 newitem->classexp = curclass;
444 newitem->exclassexp = curexclass;
445 if (curtime) newitem->timespec = strdup(curtime);
446 if (curextime) newitem->extimespec = strdup(curextime);
447 if (curtext) newitem->statustext = strdup(curtext);
448 if (curgroup) newitem->groups = strdup(curgroup);
449 newitem->cfid = cfid;
450
451 return newitem;
452 }
453
454
isqual(char * token)455 static int isqual(char *token)
456 {
457 if (!token) return 1;
458
459 if ( (strncasecmp(token, "HOST=", 5) == 0) ||
460 (strncasecmp(token, "EXHOST=", 7) == 0) ||
461 (strncasecmp(token, "PAGE=", 5) == 0) ||
462 (strncasecmp(token, "EXPAGE=", 7) == 0) ||
463 (strncasecmp(token, "DISPLAYGROUP=", 13) == 0) ||
464 (strncasecmp(token, "EXDISPLAYGROUP=", 15) == 0) ||
465 (strncasecmp(token, "CLASS=", 6) == 0) ||
466 (strncasecmp(token, "EXCLASS=", 8) == 0) ||
467 (strncasecmp(token, "TEXT=", 5) == 0) ||
468 (strncasecmp(token, "GROUP=", 6) == 0) ||
469 (strncasecmp(token, "TIME=", 5) == 0) ||
470 (strncasecmp(token, "EXTIME=", 7) == 0) ) return 1;
471
472 return 0;
473 }
474
ftypestr(unsigned int ftype)475 static char *ftypestr(unsigned int ftype)
476 {
477 if (ftype == S_IFSOCK) return "socket";
478 else if (ftype == S_IFREG) return "file";
479 else if (ftype == S_IFBLK) return "block";
480 else if (ftype == S_IFCHR) return "char";
481 else if (ftype == S_IFDIR) return "dir";
482 else if (ftype == S_IFIFO) return "fifo";
483 else if (ftype == S_IFLNK) return "symlink";
484
485 return "";
486 }
487
488 static char *grouplist = NULL;
clearalertgroups(void)489 void clearalertgroups(void)
490 {
491 if (grouplist) xfree(grouplist);
492 }
493
getalertgroups(void)494 char *getalertgroups(void)
495 {
496 if (grouplist) {
497 *(grouplist + strlen(grouplist) - 1) = '\0';
498 return grouplist+1;
499 }
500 else return NULL;
501 }
502
addalertgroup(char * group)503 void addalertgroup(char *group)
504 {
505 char *key;
506 int curlen;
507
508 if (group == NULL) return;
509
510 key = (char *)malloc(strlen(group)+3);
511 sprintf(key, ",%s,", group);
512
513 if (!grouplist) {
514 grouplist = key;
515 return;
516 }
517
518 if (strstr(grouplist, key)) {
519 xfree(key);
520 return;
521 }
522
523 curlen = strlen(grouplist);
524 grouplist = (char *)realloc(grouplist, curlen + strlen(key) + 2);
525 sprintf(grouplist + curlen, "%s,", key);
526 }
527
load_client_config(char * configfn)528 int load_client_config(char *configfn)
529 {
530 /* (Re)load the configuration file without leaking memory */
531 static void *configfiles = NULL;
532 char fn[PATH_MAX];
533 FILE *fd;
534 strbuffer_t *inbuf;
535 char *tok;
536 exprlist_t *curhost, *curpage, *curclass, *curexhost, *curexpage, *curexclass, *curdg, *curexdg;
537 char *curtime, *curextime, *curtext, *curgroup;
538 c_rule_t *currule = NULL;
539 int cfid = 0;
540
541 MEMDEFINE(fn);
542
543 if (configfn) strcpy(fn, configfn); else sprintf(fn, "%s/etc/analysis.cfg", xgetenv("XYMONHOME"));
544
545 /* First check if there were no modifications at all */
546 if (configfiles) {
547 if (!stackfmodified(configfiles)){
548 dbgprintf("No files modified, skipping reload of %s\n", fn);
549 return 0;
550 }
551 else {
552 stackfclist(&configfiles);
553 configfiles = NULL;
554 }
555 }
556
557 fd = stackfopen(fn, "r", &configfiles);
558 if (!fd) {
559 errprintf("Cannot load config file %s: %s\n", fn, strerror(errno));
560 MEMUNDEFINE(fn);
561 return 0;
562 }
563
564 /* First free the old list, if any */
565 while (rulehead) {
566 c_rule_t *tmp = rulehead;
567 rulehead = rulehead->next;
568 if (tmp->groups) xfree(tmp->groups);
569 if (tmp->timespec) xfree(tmp->timespec);
570 if (tmp->extimespec) xfree(tmp->extimespec);
571 if (tmp->statustext) xfree(tmp->statustext);
572 if (tmp->rrdidstr) xfree(tmp->rrdidstr);
573
574 switch (tmp->ruletype) {
575 case C_MIBVAL:
576 if (tmp->rule.mibval.havetree) xtreeDestroy(tmp->rule.mibval.valdeftree);
577 break;
578
579 case C_RRDDS:
580 if (tmp->rule.rrdds.rrdds) xfree(tmp->rule.rrdds.rrdds);
581 if (tmp->rule.rrdds.column) xfree(tmp->rule.rrdds.column);
582 break;
583
584 default:
585 break;
586 }
587 xfree(tmp);
588 }
589 rulehead = ruletail = NULL;
590 while (exprhead) {
591 exprlist_t *tmp = exprhead;
592 exprhead = exprhead->next;
593 if (tmp->pattern) xfree(tmp->pattern);
594 if (tmp->exp) pcre_free(tmp->exp);
595 xfree(tmp);
596 }
597 exprhead = NULL;
598
599 if (havetree) {
600 xtreePos_t handle;
601 char *key;
602 ruleset_t *head, *itm;
603
604 handle = xtreeFirst(ruletree);
605 while (handle != xtreeEnd(ruletree)) {
606 key = (char *)xtreeKey(ruletree, handle);
607 head = (ruleset_t *)xtreeData(ruletree, handle);
608 xfree(key);
609 while (head) {
610 itm = head; head = head->next; xfree(itm);
611 }
612 handle = xtreeNext(ruletree, handle);
613 }
614 xtreeDestroy(ruletree);
615 havetree = 0;
616 }
617
618 #define NEWRULE(X) (setup_rule(X, curhost, curexhost, curpage, curexpage, curdg, curexdg, curclass, curexclass, curtime, curextime, curtext, curgroup, cfid));
619
620 curhost = curpage = curclass = curexhost = curexpage = curexclass = curdg = curexdg = NULL;
621 curtime = curextime = curtext = curgroup = NULL;
622 inbuf = newstrbuffer(0);
623 while (stackfgets(inbuf, NULL)) {
624 exprlist_t *newhost, *newpage, *newexhost, *newexpage, *newclass, *newexclass, *newdg, *newexdg;
625 char *newtime, *newextime, *newtext, *newgroup;
626 int unknowntok = 0;
627
628 cfid++;
629 sanitize_input(inbuf, 1, 0); if (STRBUFLEN(inbuf) == 0) continue;
630
631 newhost = newpage = newexhost = newexpage = newclass = newexclass = newdg = newexdg = NULL;
632 newtime = newextime = newtext = newgroup = NULL;
633 currule = NULL;
634
635 tok = wstok(STRBUF(inbuf));
636 while (tok) {
637 if (strncasecmp(tok, "HOST=", 5) == 0) {
638 char *p = strchr(tok, '=');
639 newhost = setup_expr(p+1, 0);
640 if (currule) currule->hostexp = newhost;
641 tok = wstok(NULL); continue;
642 }
643 else if (strncasecmp(tok, "EXHOST=", 7) == 0) {
644 char *p = strchr(tok, '=');
645 newexhost = setup_expr(p+1, 0);
646 if (currule) currule->exhostexp = newexhost;
647 tok = wstok(NULL); continue;
648 }
649 else if (strncasecmp(tok, "PAGE=", 5) == 0) {
650 char *p = strchr(tok, '=');
651 newpage = setup_expr(p+1, 0);
652 if (currule) currule->pageexp = newpage;
653 tok = wstok(NULL); continue;
654 }
655 else if (strncasecmp(tok, "EXPAGE=", 7) == 0) {
656 char *p = strchr(tok, '=');
657 newexpage = setup_expr(p+1, 0);
658 if (currule) currule->expageexp = newexpage;
659 tok = wstok(NULL); continue;
660 }
661 else if (strncasecmp(tok, "DISPLAYGROUP=", 13) == 0) {
662 char *p = strchr(tok, '=');
663 newdg = setup_expr(p+1, 0);
664 if (currule) currule->dgexp = newdg;
665 tok = wstok(NULL); continue;
666 }
667 else if (strncasecmp(tok, "EXDISPLAYGROUP=", 15) == 0) {
668 char *p = strchr(tok, '=');
669 newexdg = setup_expr(p+1, 0);
670 if (currule) currule->exdgexp = newexdg;
671 tok = wstok(NULL); continue;
672 }
673 else if (strncasecmp(tok, "CLASS=", 6) == 0) {
674 char *p = strchr(tok, '=');
675 newclass = setup_expr(p+1, 0);
676 if (currule) currule->classexp = newclass;
677 tok = wstok(NULL); continue;
678 }
679 else if (strncasecmp(tok, "EXCLASS=", 8) == 0) {
680 char *p = strchr(tok, '=');
681 newexclass = setup_expr(p+1, 0);
682 if (currule) currule->exclassexp = newexclass;
683 tok = wstok(NULL); continue;
684 }
685 else if (strncasecmp(tok, "TIME=", 5) == 0) {
686 char *p = strchr(tok, '=');
687 if (currule) currule->timespec = strdup(p+1);
688 else newtime = strdup(p+1);
689 tok = wstok(NULL); continue;
690 }
691 else if (strncasecmp(tok, "EXTIME=", 7) == 0) {
692 char *p = strchr(tok, '=');
693 if (currule) currule->extimespec = strdup(p+1);
694 else newextime = strdup(p+1);
695 tok = wstok(NULL); continue;
696 }
697 else if (strncasecmp(tok, "TEXT=", 5) == 0) {
698 char *p = strchr(tok, '=');
699 if (currule) currule->statustext = strdup(p+1);
700 else newtext = strdup(p+1);
701 tok = wstok(NULL); continue;
702 }
703 else if (strncasecmp(tok, "GROUP=", 6) == 0) {
704 char *p = strchr(tok, '=');
705 if (currule) currule->groups = strdup(p+1);
706 else newgroup = strdup(p+1);
707 tok = wstok(NULL); continue;
708 }
709 else if (strncasecmp(tok, "DEFAULT", 6) == 0) {
710 currule = NULL;
711 }
712 else if (strcasecmp(tok, "UP") == 0) {
713 currule = NEWRULE(C_UPTIME)
714 currule->rule.uptime.recentlimit = 3600;
715 currule->rule.uptime.ancientlimit = -1;
716 currule->rule.uptime.color = COL_YELLOW;
717
718 tok = wstok(NULL); if (isqual(tok)) continue;
719 currule->rule.uptime.recentlimit = 60*durationvalue(tok);
720 tok = wstok(NULL); if (isqual(tok)) continue;
721 currule->rule.uptime.ancientlimit = 60*durationvalue(tok);
722 tok = wstok(NULL); if (isqual(tok)) continue;
723 if (tok) currule->rule.uptime.color = parse_color(tok);
724 }
725 else if (strcasecmp(tok, "CLOCK") == 0) {
726 currule = NEWRULE(C_CLOCK);
727 currule->rule.clock.maxdiff = 60;
728 currule->rule.clock.color = COL_YELLOW;
729 tok = wstok(NULL); if (isqual(tok)) continue;
730 currule->rule.clock.maxdiff = atoi(tok);
731 tok = wstok(NULL); if (isqual(tok)) continue;
732 if (tok) currule->rule.clock.color = parse_color(tok);
733 }
734 else if (strcasecmp(tok, "LOAD") == 0) {
735 currule = NEWRULE(C_LOAD);
736 currule->rule.load.warnlevel = 5.0;
737 currule->rule.load.paniclevel = atof(tok);
738
739 tok = wstok(NULL); if (isqual(tok)) continue;
740 currule->rule.load.warnlevel = atof(tok);
741 tok = wstok(NULL); if (isqual(tok)) continue;
742 currule->rule.load.paniclevel = atof(tok);
743 }
744 else if (strcasecmp(tok, "DISK") == 0) {
745 currule = NEWRULE(C_DISK);
746 currule->rule.disk.abswarn = 0;
747 currule->rule.disk.warnlevel = 90;
748 currule->rule.disk.abspanic = 0;
749 currule->rule.disk.paniclevel = 95;
750 currule->rule.disk.dmin = 0;
751 currule->rule.disk.dmax = -1;
752 currule->rule.disk.color = COL_RED;
753 currule->rule.disk.ignored = 0;
754
755 tok = wstok(NULL); if (isqual(tok)) continue;
756 currule->rule.disk.fsexp = setup_expr(tok, 0);
757
758 tok = wstok(NULL); if (isqual(tok)) continue;
759 if (strcasecmp(tok, "ignore") == 0) {
760 currule->rule.disk.ignored = 1;
761 tok = wstok(NULL);
762 continue;
763 }
764 currule->rule.disk.warnlevel = atol(tok);
765 switch (*(tok + strspn(tok, "0123456789"))) {
766 case 'U':
767 case 'u': currule->rule.disk.abswarn = 1; break;
768 case '%': currule->rule.disk.abswarn = 0; break;
769 default : currule->rule.disk.abswarn = (currule->rule.disk.warnlevel > 200 ? 1 : 0); break;
770 }
771
772 tok = wstok(NULL); if (isqual(tok)) continue;
773 currule->rule.disk.paniclevel = atol(tok);
774 switch (*(tok + strspn(tok, "0123456789"))) {
775 case 'U':
776 case 'u': currule->rule.disk.abspanic = 1; break;
777 case '%': currule->rule.disk.abspanic = 0; break;
778 default : currule->rule.disk.abspanic = (currule->rule.disk.paniclevel > 200 ? 1 : 0); break;
779 }
780
781 tok = wstok(NULL); if (isqual(tok)) continue;
782 currule->rule.disk.dmin = atoi(tok);
783 tok = wstok(NULL); if (isqual(tok)) continue;
784 currule->rule.disk.dmax = atoi(tok);
785 tok = wstok(NULL); if (isqual(tok)) continue;
786 currule->rule.disk.color = parse_color(tok);
787 }
788 else if (strcasecmp(tok, "INODE") == 0) {
789 currule = NEWRULE(C_INODE);
790 currule->rule.inode.abswarn = 0;
791 currule->rule.inode.warnlevel = 70;
792 currule->rule.inode.abspanic = 0;
793 currule->rule.inode.paniclevel = 90;
794 currule->rule.inode.imin = 0;
795 currule->rule.inode.imax = -1;
796 currule->rule.inode.color = COL_RED;
797 currule->rule.inode.ignored = 0;
798
799 tok = wstok(NULL); if (isqual(tok)) continue;
800 currule->rule.inode.fsexp = setup_expr(tok, 0);
801
802 tok = wstok(NULL); if (isqual(tok)) continue;
803 if (strcasecmp(tok, "ignore") == 0) {
804 currule->rule.inode.ignored = 1;
805 tok = wstok(NULL);
806 continue;
807 }
808 currule->rule.inode.warnlevel = atol(tok);
809 switch (*(tok + strspn(tok, "0123456789"))) {
810 case 'U':
811 case 'u': currule->rule.inode.abswarn = 1; break;
812 case '%': currule->rule.inode.abswarn = 0; break;
813 default : currule->rule.inode.abswarn = (currule->rule.inode.warnlevel > 200 ? 1 : 0); break;
814 }
815
816 tok = wstok(NULL); if (isqual(tok)) continue;
817 currule->rule.inode.paniclevel = atol(tok);
818 switch (*(tok + strspn(tok, "0123456789"))) {
819 case 'U':
820 case 'u': currule->rule.inode.abspanic = 1; break;
821 case '%': currule->rule.inode.abspanic = 0; break;
822 default : currule->rule.inode.abspanic = (currule->rule.inode.paniclevel > 200 ? 1 : 0); break;
823 }
824
825 tok = wstok(NULL); if (isqual(tok)) continue;
826 currule->rule.inode.imin = atoi(tok);
827 tok = wstok(NULL); if (isqual(tok)) continue;
828 currule->rule.inode.imax = atoi(tok);
829 tok = wstok(NULL); if (isqual(tok)) continue;
830 currule->rule.inode.color = parse_color(tok);
831 }
832
833 else if ((strcasecmp(tok, "MEMREAL") == 0) || (strcasecmp(tok, "MEMPHYS") == 0) || (strcasecmp(tok, "PHYS") == 0)) {
834 currule = NEWRULE(C_MEM);
835 currule->rule.mem.memtype = C_MEM_PHYS;
836 currule->rule.mem.warnlevel = 100;
837 currule->rule.mem.paniclevel = 101;
838
839 tok = wstok(NULL); if (isqual(tok)) continue;
840 currule->rule.mem.warnlevel = atoi(tok);
841 tok = wstok(NULL); if (isqual(tok)) continue;
842 currule->rule.mem.paniclevel = atoi(tok);
843 }
844 else if ((strcasecmp(tok, "MEMSWAP") == 0) || (strcasecmp(tok, "SWAP") == 0)) {
845 currule = NEWRULE(C_MEM);
846 currule->rule.mem.memtype = C_MEM_SWAP;
847 currule->rule.mem.warnlevel = 50;
848 currule->rule.mem.paniclevel = 80;
849
850 tok = wstok(NULL); if (isqual(tok)) continue;
851 currule->rule.mem.warnlevel = atoi(tok);
852 tok = wstok(NULL); if (isqual(tok)) continue;
853 currule->rule.mem.paniclevel = atoi(tok);
854 }
855 else if ((strcasecmp(tok, "MEMACT") == 0) || (strcasecmp(tok, "ACTUAL") == 0) || (strcasecmp(tok, "ACT") == 0)) {
856 currule = NEWRULE(C_MEM);
857 currule->rule.mem.memtype = C_MEM_ACT;
858 currule->rule.mem.warnlevel = 90;
859 currule->rule.mem.paniclevel = 97;
860
861 tok = wstok(NULL); if (isqual(tok)) continue;
862 currule->rule.mem.warnlevel = atoi(tok);
863 tok = wstok(NULL); if (isqual(tok)) continue;
864 currule->rule.mem.paniclevel = atoi(tok);
865 }
866 else if (strcasecmp(tok, "MEMCSA") == 0) {
867 currule = NEWRULE(C_MEM);
868 currule->rule.zos_mem.zos_memtype = C_MEM_CSA;
869 currule->rule.zos_mem.warnlevel = 90;
870 currule->rule.zos_mem.paniclevel = 95;
871
872 tok = wstok(NULL); if (isqual(tok)) continue;
873 currule->rule.zos_mem.warnlevel = atoi(tok);
874 tok = wstok(NULL); if (isqual(tok)) continue;
875 currule->rule.zos_mem.paniclevel = atoi(tok);
876 }
877 else if (strcasecmp(tok, "MEMECSA") == 0) {
878 currule = NEWRULE(C_MEM);
879 currule->rule.zos_mem.zos_memtype = C_MEM_ECSA;
880 currule->rule.zos_mem.warnlevel = 90;
881 currule->rule.zos_mem.paniclevel = 95;
882
883 tok = wstok(NULL); if (isqual(tok)) continue;
884 currule->rule.zos_mem.warnlevel = atoi(tok);
885 tok = wstok(NULL); if (isqual(tok)) continue;
886 currule->rule.zos_mem.paniclevel = atoi(tok);
887 }
888 else if (strcasecmp(tok, "MEMSQA") == 0) {
889 currule = NEWRULE(C_MEM);
890 currule->rule.zos_mem.zos_memtype = C_MEM_SQA;
891 currule->rule.zos_mem.warnlevel = 90;
892 currule->rule.zos_mem.paniclevel = 95;
893
894 tok = wstok(NULL); if (isqual(tok)) continue;
895 currule->rule.zos_mem.warnlevel = atoi(tok);
896 tok = wstok(NULL); if (isqual(tok)) continue;
897 currule->rule.zos_mem.paniclevel = atoi(tok);
898 }
899 else if (strcasecmp(tok, "MEMESQA") == 0) {
900 currule = NEWRULE(C_MEM);
901 currule->rule.zos_mem.zos_memtype = C_MEM_ESQA;
902 currule->rule.zos_mem.warnlevel = 90;
903 currule->rule.zos_mem.paniclevel = 95;
904
905 tok = wstok(NULL); if (isqual(tok)) continue;
906 currule->rule.zos_mem.warnlevel = atoi(tok);
907 tok = wstok(NULL); if (isqual(tok)) continue;
908 currule->rule.zos_mem.paniclevel = atoi(tok);
909 }
910 else if (strcasecmp(tok, "CICS") == 0) {
911 currule = NEWRULE(C_CICS);
912 currule->rule.cics.dsawarnlevel = 90;
913 currule->rule.cics.dsapaniclevel = 95;
914 currule->rule.cics.edsawarnlevel = 90;
915 currule->rule.cics.edsapaniclevel = 95;
916
917 tok = wstok(NULL); if (isqual(tok)) continue;
918 currule->rule.cics.applid = setup_expr(tok, 0);
919
920 tok = wstok(NULL); if (isqual(tok)) continue;
921 if (strcasecmp(tok, "DSA") == 0) {
922 tok = wstok(NULL); if (isqual(tok)) continue;
923 currule->rule.cics.dsawarnlevel = atoi(tok);
924 tok = wstok(NULL); if (isqual(tok)) continue;
925 currule->rule.cics.dsapaniclevel = atoi(tok);
926 }
927 else if (strcasecmp(tok, "EDSA") == 0) {
928 tok = wstok(NULL); if (isqual(tok)) continue;
929 currule->rule.cics.edsawarnlevel = atoi(tok);
930 tok = wstok(NULL); if (isqual(tok)) continue;
931 currule->rule.cics.edsapaniclevel = atoi(tok);
932 }
933
934 tok = wstok(NULL); if (isqual(tok)) continue;
935 if (strcasecmp(tok, "DSA") == 0) {
936 tok = wstok(NULL); if (isqual(tok)) continue;
937 currule->rule.cics.dsawarnlevel = atoi(tok);
938 tok = wstok(NULL); if (isqual(tok)) continue;
939 currule->rule.cics.dsapaniclevel = atoi(tok);
940 }
941 else if (strcasecmp(tok, "EDSA") == 0) {
942 tok = wstok(NULL); if (isqual(tok)) continue;
943 currule->rule.cics.edsawarnlevel = atoi(tok);
944 tok = wstok(NULL); if (isqual(tok)) continue;
945 currule->rule.cics.edsapaniclevel = atoi(tok);
946 }
947 }
948 else if (strcasecmp(tok, "PROC") == 0) {
949 int idx = 0;
950
951 tok = wstok(NULL);
952 if (tok == NULL) {
953 errprintf("Syntax error line %d: PROC with no definition\n", cfid);
954 unknowntok = 1;
955 break;
956 }
957
958 currule = NEWRULE(C_PROC);
959 currule->rule.proc.pmin = 1;
960 currule->rule.proc.pmax = -1;
961 currule->rule.proc.color = COL_RED;
962
963 currule->rule.proc.procexp = setup_expr(tok, 0);
964
965 do {
966 tok = wstok(NULL); if (!tok || isqual(tok)) { idx = -1; continue; }
967
968 if (strncasecmp(tok, "min=", 4) == 0) {
969 currule->rule.proc.pmin = atoi(tok+4);
970 }
971 else if (strncasecmp(tok, "max=", 4) == 0) {
972 currule->rule.proc.pmax = atoi(tok+4);
973 /* When we have an explicit max, minimum should not be higher */
974 if (currule->rule.proc.pmax < currule->rule.proc.pmin) {
975 currule->rule.proc.pmin = currule->rule.proc.pmax;
976 }
977 }
978 else if (strncasecmp(tok, "color=", 6) == 0) {
979 currule->rule.proc.color = parse_color(tok+6);
980 }
981 else if (strncasecmp(tok, "track", 5) == 0) {
982 currule->chkflags |= CHK_TRACKIT;
983 if (*(tok+5) == '=') currule->rrdidstr = strdup(tok+6);
984 }
985 else if (idx == 0) {
986 currule->rule.proc.pmin = atoi(tok);
987 idx++;
988 }
989 else if (idx == 1) {
990 currule->rule.proc.pmax = atoi(tok);
991 idx++;
992 }
993 else if (idx == 2) {
994 currule->rule.proc.color = parse_color(tok);
995 idx++;
996 }
997 } while (tok && (!isqual(tok)));
998
999 /* It's easy to set max=0 when you only want to define a minimum */
1000 if (currule->rule.proc.pmin && (currule->rule.proc.pmax == 0)) {
1001 currule->rule.proc.pmax = -1;
1002 }
1003 }
1004 else if (strcasecmp(tok, "LOG") == 0) {
1005 int idx = 0;
1006
1007 currule = NEWRULE(C_LOG);
1008 currule->rule.log.logfile = NULL;
1009 currule->rule.log.matchexp = NULL;
1010 currule->rule.log.matchone = NULL;
1011 currule->rule.log.ignoreexp = NULL;
1012 currule->rule.log.color = COL_RED;
1013
1014 do {
1015 tok = wstok(NULL); if (!tok || isqual(tok)) { idx = -1; continue; }
1016
1017 if (strncasecmp(tok, "file=", 5) == 0) {
1018 currule->rule.log.logfile = setup_expr(tok+5, 0);
1019 }
1020 else if (strncasecmp(tok, "match=", 6) == 0) {
1021 currule->rule.log.matchexp = setup_expr(tok+6, 1);
1022 currule->rule.log.matchone = setup_expr(tok+6, 0);
1023 }
1024 else if (strncasecmp(tok, "ignore=", 7) == 0) {
1025 currule->rule.log.ignoreexp = setup_expr(tok+7, 1);
1026 }
1027 else if (strncasecmp(tok, "color=", 6) == 0) {
1028 currule->rule.log.color = parse_color(tok+6);
1029 }
1030 else if (strcasecmp(tok, "optional") == 0) {
1031 currule->chkflags |= CHK_OPTIONAL;
1032 }
1033 else if (idx == 0) {
1034 currule->rule.log.logfile = setup_expr(tok, 0);
1035 idx++;
1036 }
1037 else if (idx == 1) {
1038 currule->rule.log.matchexp = setup_expr(tok, 1);
1039 currule->rule.log.matchone = setup_expr(tok, 0);
1040 idx++;
1041 }
1042 else if (idx == 2) {
1043 currule->rule.log.color = parse_color(tok);
1044 idx++;
1045 }
1046 else if (idx == 3) {
1047 currule->rule.log.ignoreexp = setup_expr(tok, 1);
1048 idx++;
1049 }
1050 } while (tok && (!isqual(tok)));
1051 }
1052 else if (strcasecmp(tok, "FILE") == 0) {
1053 currule = NEWRULE(C_FILE);
1054 currule->rule.fcheck.filename = NULL;
1055 currule->rule.fcheck.color = COL_RED;
1056
1057 tok = wstok(NULL);
1058 currule->rule.fcheck.filename = setup_expr(tok, 0);
1059 do {
1060 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1061
1062 if (strcasecmp(tok, "noexist") == 0) {
1063 currule->flags |= FCHK_NOEXIST;
1064 }
1065 else if (strncasecmp(tok, "type=", 5) == 0) {
1066 currule->flags |= FCHK_TYPE;
1067 if (strcasecmp(tok+5, "socket") == 0) currule->rule.fcheck.ftype = S_IFSOCK;
1068 else if (strcasecmp(tok+5, "file") == 0) currule->rule.fcheck.ftype = S_IFREG;
1069 else if (strcasecmp(tok+5, "block") == 0) currule->rule.fcheck.ftype = S_IFBLK;
1070 else if (strcasecmp(tok+5, "char") == 0) currule->rule.fcheck.ftype = S_IFCHR;
1071 else if (strcasecmp(tok+5, "dir") == 0) currule->rule.fcheck.ftype = S_IFDIR;
1072 else if (strcasecmp(tok+5, "fifo") == 0) currule->rule.fcheck.ftype = S_IFIFO;
1073 else if (strcasecmp(tok+5, "symlink") == 0) currule->rule.fcheck.ftype = S_IFLNK;
1074 }
1075 else if (strncasecmp(tok, "size>", 5) == 0) {
1076 currule->flags |= FCHK_MINSIZE;
1077 currule->rule.fcheck.minsize = filesize_value(tok+5);
1078 }
1079 else if (strncasecmp(tok, "size<", 5) == 0) {
1080 currule->flags |= FCHK_MAXSIZE;
1081 currule->rule.fcheck.maxsize = filesize_value(tok+5);
1082 }
1083 else if (strncasecmp(tok, "size=", 5) == 0) {
1084 currule->flags |= FCHK_EQLSIZE;
1085 currule->rule.fcheck.eqlsize = filesize_value(tok+5);
1086 }
1087 else if (strncasecmp(tok, "links>", 6) == 0) {
1088 currule->flags |= FCHK_MINLINKS;
1089 currule->rule.fcheck.minlinks = atol(tok+6);
1090 }
1091 else if (strncasecmp(tok, "links<", 6) == 0) {
1092 currule->flags |= FCHK_MAXLINKS;
1093 currule->rule.fcheck.maxlinks = atol(tok+6);
1094 }
1095 else if (strncasecmp(tok, "links=", 6) == 0) {
1096 currule->flags |= FCHK_EQLLINKS;
1097 currule->rule.fcheck.eqllinks = atol(tok+6);
1098 }
1099 else if (strncasecmp(tok, "mode=", 5) == 0) {
1100 currule->flags |= FCHK_MODE;
1101 currule->rule.fcheck.fmode = strtol(tok+5, NULL, 8);
1102 }
1103 else if ((strncasecmp(tok, "owner=", 6) == 0) ||
1104 (strncasecmp(tok, "ownerid=", 8) == 0)) {
1105 char *p, *eptr;
1106 int uid;
1107
1108 p = strchr(tok, '=');
1109 uid = strtol(p+1, &eptr, 10);
1110 if (*eptr == '\0') {
1111 /* All numeric */
1112 currule->flags |= FCHK_OWNERID;
1113 currule->rule.fcheck.ownerid = uid;
1114 }
1115 else {
1116 currule->flags |= FCHK_OWNERSTR;
1117 currule->rule.fcheck.ownerstr = strdup(p+1);
1118 }
1119 }
1120 else if (strncasecmp(tok, "groupid=", 8) == 0) {
1121 /* Cannot use "group" because that is reserved */
1122 char *p, *eptr;
1123 int uid;
1124
1125 p = strchr(tok, '=');
1126 uid = strtol(p+1, &eptr, 10);
1127 if (*eptr == '\0') {
1128 /* All numeric */
1129 currule->flags |= FCHK_GROUPID;
1130 currule->rule.fcheck.groupid = uid;
1131 }
1132 else {
1133 currule->flags |= FCHK_GROUPSTR;
1134 currule->rule.fcheck.groupstr = strdup(p+1);
1135 }
1136 }
1137 else if (strncasecmp(tok, "mtime>", 6) == 0) {
1138 currule->flags |= FCHK_MTIMEMIN;
1139 currule->rule.fcheck.minmtimedif = atol(tok+6);
1140 }
1141 else if (strncasecmp(tok, "mtime<", 6) == 0) {
1142 currule->flags |= FCHK_MTIMEMAX;
1143 currule->rule.fcheck.maxmtimedif = atol(tok+6);
1144 }
1145 else if (strncasecmp(tok, "mtime=", 6) == 0) {
1146 currule->flags |= FCHK_MTIMEEQL;
1147 currule->rule.fcheck.mtimeeql = atol(tok+6);
1148 }
1149 else if (strncasecmp(tok, "ctime>", 6) == 0) {
1150 currule->flags |= FCHK_CTIMEMIN;
1151 currule->rule.fcheck.minctimedif = atol(tok+6);
1152 }
1153 else if (strncasecmp(tok, "ctime<", 6) == 0) {
1154 currule->flags |= FCHK_CTIMEMAX;
1155 currule->rule.fcheck.maxctimedif = atol(tok+6);
1156 }
1157 else if (strncasecmp(tok, "ctime=", 6) == 0) {
1158 currule->flags |= FCHK_CTIMEEQL;
1159 currule->rule.fcheck.ctimeeql = atol(tok+6);
1160 }
1161 else if (strncasecmp(tok, "atime>", 6) == 0) {
1162 currule->flags |= FCHK_ATIMEMIN;
1163 currule->rule.fcheck.minatimedif = atol(tok+6);
1164 }
1165 else if (strncasecmp(tok, "atime<", 6) == 0) {
1166 currule->flags |= FCHK_ATIMEMAX;
1167 currule->rule.fcheck.maxatimedif = atol(tok+6);
1168 }
1169 else if (strncasecmp(tok, "atime=", 6) == 0) {
1170 currule->flags |= FCHK_ATIMEEQL;
1171 currule->rule.fcheck.atimeeql = atol(tok+6);
1172 }
1173 else if (strncasecmp(tok, "md5=", 4) == 0) {
1174 currule->flags |= FCHK_MD5;
1175 currule->rule.fcheck.md5hash = strdup(tok+4);
1176 }
1177 else if (strncasecmp(tok, "sha1=", 5) == 0) {
1178 currule->flags |= FCHK_SHA1;
1179 currule->rule.fcheck.sha1hash = strdup(tok+5);
1180 }
1181 else if (strncasecmp(tok, "sha256=", 7) == 0) {
1182 currule->flags |= FCHK_SHA256;
1183 currule->rule.fcheck.sha256hash = strdup(tok+7);
1184 }
1185 else if (strncasecmp(tok, "sha512=", 7) == 0) {
1186 currule->flags |= FCHK_SHA512;
1187 currule->rule.fcheck.sha512hash = strdup(tok+7);
1188 }
1189 else if (strncasecmp(tok, "sha224=", 7) == 0) {
1190 currule->flags |= FCHK_SHA224;
1191 currule->rule.fcheck.sha224hash = strdup(tok+7);
1192 }
1193 else if (strncasecmp(tok, "sha384=", 7) == 0) {
1194 currule->flags |= FCHK_SHA384;
1195 currule->rule.fcheck.sha384hash = strdup(tok+7);
1196 }
1197 else if (strncasecmp(tok, "rmd160=", 7) == 0) {
1198 currule->flags |= FCHK_RMD160;
1199 currule->rule.fcheck.rmd160hash = strdup(tok+7);
1200 }
1201 else if (strncasecmp(tok, "track", 5) == 0) {
1202 currule->chkflags |= CHK_TRACKIT;
1203 if (*(tok+5) == '=') currule->rrdidstr = strdup(tok+6);
1204 }
1205 else if (strcasecmp(tok, "optional") == 0) {
1206 currule->chkflags |= CHK_OPTIONAL;
1207 }
1208 else {
1209 int col = parse_color(tok);
1210 if (col != -1) currule->rule.fcheck.color = col;
1211 }
1212 } while (tok && (!isqual(tok)));
1213 }
1214 else if (strcasecmp(tok, "DIR") == 0) {
1215 currule = NEWRULE(C_DIR);
1216 currule->rule.dcheck.filename = NULL;
1217 currule->rule.dcheck.color = COL_RED;
1218
1219 tok = wstok(NULL);
1220 currule->rule.dcheck.filename = setup_expr(tok, 0);
1221 do {
1222 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1223
1224 if (strncasecmp(tok, "size<", 5) == 0) {
1225 currule->flags |= FCHK_MAXSIZE;
1226 currule->rule.dcheck.maxsize = atol(tok+5);
1227 }
1228 else if (strncasecmp(tok, "size>", 5) == 0) {
1229 currule->flags |= FCHK_MINSIZE;
1230 currule->rule.dcheck.minsize = atol(tok+5);
1231 }
1232 else if (strncasecmp(tok, "track", 5) == 0) {
1233 currule->chkflags |= CHK_TRACKIT;
1234 if (*(tok+5) == '=') currule->rrdidstr = strdup(tok+6);
1235 }
1236 else {
1237 int col = parse_color(tok);
1238 if (col != -1) currule->rule.dcheck.color = col;
1239 }
1240 } while (tok && (!isqual(tok)));
1241 }
1242 else if (strcasecmp(tok, "PORT") == 0) {
1243 currule = NEWRULE(C_PORT);
1244
1245 currule->rule.port.localexp = NULL;
1246 currule->rule.port.exlocalexp = NULL;
1247 currule->rule.port.remoteexp = NULL;
1248 currule->rule.port.exremoteexp = NULL;
1249 currule->rule.port.stateexp = NULL;
1250 currule->rule.port.exstateexp = NULL;
1251 currule->rule.port.pmin = 1;
1252 currule->rule.port.pmax = -1;
1253 currule->rule.port.color = COL_RED;
1254
1255 /* parse syntax [local=ADDR] [remote=ADDR] [state=STATE] [min=mincount] [max=maxcount] [col=color] */
1256 do {
1257 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1258
1259 if (strncasecmp(tok, "local=", 6) == 0) {
1260 currule->rule.port.localexp = setup_expr(tok+6, 0);
1261 }
1262 else if (strncasecmp(tok, "exlocal=", 8) == 0) {
1263 currule->rule.port.exlocalexp = setup_expr(tok+8, 0);
1264 }
1265 else if (strncasecmp(tok, "remote=", 7) == 0) {
1266 currule->rule.port.remoteexp = setup_expr(tok+7, 0);
1267 }
1268 else if (strncasecmp(tok, "exremote=", 9) == 0) {
1269 currule->rule.port.exremoteexp = setup_expr(tok+9, 0);
1270 }
1271 else if (strncasecmp(tok, "state=", 6) == 0) {
1272 currule->rule.port.stateexp = setup_expr(tok+6, 0);
1273 }
1274 else if (strncasecmp(tok, "exstate=", 8) == 0) {
1275 currule->rule.port.exstateexp = setup_expr(tok+8, 0);
1276 }
1277 else if (strncasecmp(tok, "min=", 4) == 0) {
1278 currule->rule.port.pmin = atoi(tok+4);
1279 }
1280 else if (strncasecmp(tok, "max=", 4) == 0) {
1281 currule->rule.port.pmax = atoi(tok+4);
1282
1283 /* When we have an explicit max, minimum should not be higher */
1284 if (currule->rule.port.pmax < currule->rule.port.pmin) {
1285 currule->rule.port.pmin = currule->rule.port.pmax;
1286 }
1287 }
1288 else if (strncasecmp(tok, "col=", 4) == 0) {
1289 currule->rule.port.color = parse_color(tok+4);
1290 }
1291 else if (strncasecmp(tok, "color=", 6) == 0) {
1292 currule->rule.port.color = parse_color(tok+6);
1293 }
1294 else if (strncasecmp(tok, "track", 5) == 0) {
1295 currule->chkflags |= CHK_TRACKIT;
1296 if (*(tok+5) == '=') currule->rrdidstr = strdup(tok+6);
1297 }
1298 } while (tok && (!isqual(tok)));
1299 }
1300 else if (strcasecmp(tok, "PAGING") == 0) {
1301 currule = NEWRULE(C_PAGING);
1302
1303 currule->rule.paging.warnlevel = 5;
1304 currule->rule.paging.paniclevel = 10;
1305
1306 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1307 currule->rule.paging.warnlevel = atoi(tok);
1308
1309 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1310 currule->rule.paging.paniclevel = atoi(tok);
1311 }
1312 else if (strcasecmp(tok, "GETVIS") == 0) {
1313 currule = NEWRULE(C_MEM_GETVIS);
1314 currule->rule.zvse_getvis.warnlevel = 90;
1315 currule->rule.zvse_getvis.paniclevel = 95;
1316 currule->rule.zvse_getvis.anywarnlevel = 90;
1317 currule->rule.zvse_getvis.anypaniclevel = 95;
1318
1319 tok = wstok(NULL); if (isqual(tok)) continue;
1320 currule->rule.zvse_getvis.partid = setup_expr(tok, 0);
1321
1322 tok = wstok(NULL); if (isqual(tok)) continue;
1323 currule->rule.zvse_getvis.warnlevel = atoi(tok);
1324 tok = wstok(NULL); if (isqual(tok)) continue;
1325 currule->rule.zvse_getvis.paniclevel = atoi(tok);
1326
1327 tok = wstok(NULL); if (isqual(tok)) continue;
1328 currule->rule.zvse_getvis.anywarnlevel = atoi(tok);
1329 tok = wstok(NULL); if (isqual(tok)) continue;
1330 currule->rule.zvse_getvis.anypaniclevel = atoi(tok);
1331 }
1332 else if (strcasecmp(tok, "VSIZE") == 0) {
1333 currule = NEWRULE(C_MEM_VSIZE);
1334 currule->rule.zvse_vsize.warnlevel = 90;
1335 currule->rule.zvse_vsize.paniclevel = 95;
1336
1337 tok = wstok(NULL); if (isqual(tok)) continue;
1338 currule->rule.zvse_vsize.warnlevel = atoi(tok);
1339 tok = wstok(NULL); if (isqual(tok)) continue;
1340 currule->rule.zvse_vsize.paniclevel = atoi(tok);
1341 }
1342 else if (strcasecmp(tok, "MAXUSER") == 0) {
1343 currule = NEWRULE(C_ASID);
1344 currule->rule.asid.asidtype = C_ASID_MAXUSER;
1345
1346 currule->rule.asid.warnlevel = 101;
1347 currule->rule.asid.paniclevel = 101;
1348
1349 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1350 currule->rule.asid.warnlevel = atoi(tok);
1351
1352 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1353 currule->rule.asid.paniclevel = atoi(tok);
1354 }
1355 else if (strcasecmp(tok, "NPARTS") == 0) {
1356 currule = NEWRULE(C_ASID);
1357 currule->rule.asid.asidtype = C_ASID_NPARTS;
1358
1359 currule->rule.asid.warnlevel = 101;
1360 currule->rule.asid.paniclevel = 101;
1361
1362 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1363 currule->rule.asid.warnlevel = atoi(tok);
1364
1365 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1366 currule->rule.asid.paniclevel = atoi(tok);
1367 }
1368 else if (strcasecmp(tok, "SVC") == 0) {
1369 tok = wstok(NULL); /* See if there is any service definition at all */
1370 if (tok) {
1371 currule = NEWRULE(C_SVC);
1372
1373 currule->rule.svc.svcexp = setup_expr(tok, 0);
1374 currule->rule.svc.startupexp = NULL;
1375 currule->rule.svc.stateexp = NULL;
1376 currule->rule.svc.state = NULL;
1377 currule->rule.svc.startup = NULL;
1378 currule->rule.svc.color = COL_RED;
1379
1380 do {
1381 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1382
1383 if (strncasecmp(tok, "startup=", 8) == 0) {
1384 currule->rule.svc.startupexp = setup_expr(tok+8, 0);
1385 }
1386 else if (strncasecmp(tok, "status=", 7) == 0) {
1387 currule->rule.svc.stateexp = setup_expr(tok+7, 0);
1388 }
1389 else if (strncasecmp(tok, "col=", 4) == 0) {
1390 currule->rule.svc.color = parse_color(tok+4);
1391 }
1392 else if (strncasecmp(tok, "color=", 6) == 0) {
1393 currule->rule.svc.color = parse_color(tok+6);
1394 }
1395 } while (tok && (!isqual(tok)));
1396
1397 if (!currule->rule.svc.stateexp && !currule->rule.svc.startupexp) {
1398 /* No criteria defined, so we'll assume they just want to check that the service is running */
1399 currule->rule.svc.stateexp = setup_expr("started", 0);
1400 }
1401 }
1402 }
1403 else if (strcasecmp(tok, "MIB") == 0) {
1404 currule = NEWRULE(C_MIBVAL);
1405 currule->rule.mibval.mibvalexp = NULL;
1406 currule->rule.mibval.keyexp = NULL;
1407 currule->rule.mibval.color = COL_RED;
1408 currule->rule.mibval.minval = -1;
1409 currule->rule.mibval.maxval = -1;
1410 currule->rule.mibval.matchexp = NULL;
1411
1412 tok = wstok(NULL);
1413 currule->rule.mibval.mibvalexp = setup_expr(tok, 0);
1414 do {
1415 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1416
1417 if (strncasecmp(tok, "key=", 4) == 0) {
1418 currule->rule.mibval.keyexp = setup_expr(tok+4, 0);
1419 }
1420 else if (strncasecmp(tok, "max=", 4) == 0) {
1421 currule->flags |= MIBCHK_MAXVALUE;
1422 currule->rule.mibval.maxval = atol(tok+4);
1423 }
1424 else if (strncasecmp(tok, "min=", 4) == 0) {
1425 currule->flags |= MIBCHK_MINVALUE;
1426 currule->rule.mibval.minval = atol(tok+4);
1427 }
1428 else if (strncasecmp(tok, "match=", 6) == 0) {
1429 currule->flags |= MIBCHK_MATCH;
1430 currule->rule.mibval.matchexp = setup_expr(tok+6, 0);
1431 }
1432 else if (strncasecmp(tok, "color=", 6) == 0) {
1433 int col = parse_color(tok+6);
1434 if (col != -1) currule->rule.mibval.color = col;
1435 }
1436 } while (tok && (!isqual(tok)));
1437 }
1438 else if (strcasecmp(tok, "DS") == 0) {
1439 char *key, *ds, *column;
1440
1441 currule = NEWRULE(C_RRDDS);
1442 currule->rule.rrdds.color = COL_RED;
1443
1444 tok = wstok(NULL);
1445 column = tok;
1446
1447 tok = wstok(NULL);
1448 key = tok;
1449 ds = (tok ? strrchr(tok, ':') : NULL);
1450 if (ds) { *ds = '\0'; ds++; }
1451
1452 if (!column || !key || !ds) {
1453 errprintf("Invalid DS definition at line %d (missing column, key and/or dataset)\n", cfid);
1454 continue;
1455 }
1456
1457 currule->rule.rrdds.rrdkey = setup_expr(key, 0);
1458 currule->rule.rrdds.rrdds = strdup(ds);
1459 currule->rule.rrdds.column = strdup(column);
1460
1461 do {
1462 int getnumber = 0;
1463
1464 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1465
1466 if (strncasecmp(tok, ">=", 2) == 0) {
1467 if (currule->flags) currule->flags |= RRDDSCHK_INTVL;
1468 currule->flags |= RRDDSCHK_GE;
1469 getnumber = 2;
1470 }
1471 else if (strncasecmp(tok, "<=", 2) == 0) {
1472 if (currule->flags) currule->flags |= RRDDSCHK_INTVL;
1473 currule->flags |= RRDDSCHK_LE;
1474 getnumber = 2;
1475 }
1476 else if (strncasecmp(tok, ">", 1) == 0) {
1477 if (currule->flags) currule->flags |= RRDDSCHK_INTVL;
1478 currule->flags |= RRDDSCHK_GT;
1479 getnumber = 1;
1480 }
1481 else if (strncasecmp(tok, "<", 1) == 0) {
1482 if (currule->flags) currule->flags |= RRDDSCHK_INTVL;
1483 currule->flags |= RRDDSCHK_LT;
1484 getnumber = 1;
1485 }
1486 else if (strncasecmp(tok, "color=", 6) == 0) {
1487 int col = parse_color(tok+6);
1488 if (col != -1) currule->rule.rrdds.color = col;
1489 }
1490
1491 if (getnumber) {
1492 if (currule->flags & RRDDSCHK_INTVL)
1493 currule->rule.rrdds.limitval2 = atof(tok+getnumber);
1494 else
1495 currule->rule.rrdds.limitval = atof(tok+getnumber);
1496
1497 if ((currule->flags & RRDDSCHK_INTVL) && (currule->rule.rrdds.limitval > currule->rule.rrdds.limitval2)) {
1498 /* Swap the two values, so we always have limitval as the lower bound, and limitval2 as the upper */
1499 double tmp;
1500
1501 tmp=currule->rule.rrdds.limitval;
1502 currule->rule.rrdds.limitval = currule->rule.rrdds.limitval2;
1503 currule->rule.rrdds.limitval2 = tmp;
1504 }
1505 }
1506 } while (tok && (!isqual(tok)));
1507 }
1508 else if (strcasecmp(tok, "MQ_QUEUE") == 0) {
1509 char *p;
1510 currule = NEWRULE(C_MQ_QUEUE);
1511 currule->rule.mqqueue.qmgrname = NULL;
1512 currule->rule.mqqueue.qname = NULL;
1513 currule->rule.mqqueue.warnlen = -1;
1514 currule->rule.mqqueue.critlen = -1;
1515 currule->rule.mqqueue.warnage = -1;
1516 currule->rule.mqqueue.critage = -1;
1517
1518 tok = wstok(NULL);
1519 p = strchr(tok, ':');
1520 if (p) {
1521 *p = '\0'; p++;
1522 currule->rule.mqqueue.qmgrname = setup_expr(tok, 0);
1523 currule->rule.mqqueue.qname = setup_expr(p, 0);
1524 }
1525 else {
1526 currule->rule.mqqueue.qmgrname = setup_expr("*", 0);
1527 currule->rule.mqqueue.qname = setup_expr(tok, 0);
1528 };
1529
1530 do {
1531 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1532
1533 if (strncasecmp(tok, "depth-warning=", 14) == 0) {
1534 currule->rule.mqqueue.warnlen = atol(tok+14);
1535 }
1536 else if (strncasecmp(tok, "depth-critical=", 15) == 0) {
1537 currule->rule.mqqueue.critlen = atol(tok+15);
1538 }
1539 else if (strncasecmp(tok, "age-warning=", 12) == 0) {
1540 currule->rule.mqqueue.warnage = atol(tok+12);
1541 }
1542 else if (strncasecmp(tok, "age-critical=", 13) == 0) {
1543 currule->rule.mqqueue.critage = atol(tok+13);
1544 }
1545 else if (strncasecmp(tok, "track", 5) == 0) {
1546 currule->chkflags |= CHK_TRACKIT;
1547 if (*(tok+5) == '=') currule->rrdidstr = strdup(tok+6);
1548 }
1549 } while (tok && (!isqual(tok)));
1550 }
1551 else if (strcasecmp(tok, "MQ_CHANNEL") == 0) {
1552 char *p;
1553
1554 currule = NEWRULE(C_MQ_CHANNEL);
1555 currule->rule.mqchannel.qmgrname = NULL;
1556 currule->rule.mqchannel.chnname = NULL;
1557 currule->rule.mqchannel.warnstates = NULL;
1558 currule->rule.mqchannel.alertstates = NULL;
1559
1560 tok = wstok(NULL);
1561 p = strchr(tok, ':');
1562 if (p) {
1563 *p = '\0'; p++;
1564 currule->rule.mqchannel.qmgrname = setup_expr(tok, 0);
1565 currule->rule.mqchannel.chnname = setup_expr(p, 0);
1566 }
1567 else {
1568 currule->rule.mqchannel.qmgrname = setup_expr("*", 0);
1569 currule->rule.mqchannel.chnname = setup_expr(tok, 0);
1570 };
1571
1572 do {
1573 tok = wstok(NULL); if (!tok || isqual(tok)) continue;
1574
1575 if (strncasecmp(tok, "warning=", 8) == 0) {
1576 currule->rule.mqchannel.warnstates = setup_expr(tok+8, 0);
1577 }
1578 else if (strncasecmp(tok, "alert=", 6) == 0) {
1579 currule->rule.mqchannel.alertstates = setup_expr(tok+6, 0);
1580 }
1581 } while (tok && (!isqual(tok)));
1582
1583 if ((currule->rule.mqchannel.warnstates == NULL) && (currule->rule.mqchannel.alertstates == NULL)) {
1584 /* Default: Alert on channel in BIND or RETRYING state */
1585 currule->rule.mqchannel.alertstates = setup_expr("%BIND|RETRYING", 0);
1586 }
1587 }
1588 else {
1589 errprintf("Unknown token '%s' ignored at line %d\n", tok, cfid);
1590 unknowntok = 1; tok = NULL; continue;
1591 }
1592
1593 if (tok && !isqual(tok)) tok = wstok(NULL);
1594 }
1595
1596 if (!currule && !unknowntok) {
1597 /* No rules on this line - its the new set of criteria */
1598 curhost = newhost;
1599 curpage = newpage;
1600 curclass = newclass;
1601 curexhost = newexhost;
1602 curexpage = newexpage;
1603 curexclass = newexclass;
1604 if (curtime) xfree(curtime); curtime = newtime;
1605 if (curextime) xfree(curextime); curextime = newextime;
1606 if (curtext) xfree(curtext); curtext = newtext;
1607 if (curgroup) xfree(curgroup); curgroup = newgroup;
1608 }
1609 }
1610
1611 stackfclose(fd);
1612 freestrbuffer(inbuf);
1613 if (curtime) xfree(curtime);
1614 if (curextime) xfree(curextime);
1615 if (curtext) xfree(curtext);
1616
1617 /* Create the ruletree, but leave it empty - it will be filled as clients report */
1618 ruletree = xtreeNew(strcasecmp);
1619 havetree = 1;
1620
1621 MEMUNDEFINE(fn);
1622 return 1;
1623 }
1624
dump_client_config(void)1625 void dump_client_config(void)
1626 {
1627 c_rule_t *rwalk;
1628
1629 for (rwalk = rulehead; (rwalk); rwalk = rwalk->next) {
1630 switch (rwalk->ruletype) {
1631 case C_UPTIME:
1632 printf("UP %d %d", rwalk->rule.uptime.recentlimit, rwalk->rule.uptime.ancientlimit);
1633 break;
1634
1635 case C_CLOCK:
1636 printf("CLOCK %d", rwalk->rule.clock.maxdiff);
1637 break;
1638
1639 case C_LOAD:
1640 printf("LOAD %.2f %.2f", rwalk->rule.load.warnlevel, rwalk->rule.load.paniclevel);
1641 break;
1642
1643 case C_DISK:
1644 if (!rwalk->rule.disk.fsexp) break;
1645
1646 printf("DISK %s", rwalk->rule.disk.fsexp->pattern);
1647 if (rwalk->rule.disk.ignored)
1648 printf(" IGNORE");
1649 else {
1650 printf(" %lu%c", rwalk->rule.disk.warnlevel, (rwalk->rule.disk.abswarn ? 'U' : '%'));
1651 printf(" %lu%c", rwalk->rule.disk.paniclevel, (rwalk->rule.disk.abspanic ? 'U' : '%'));
1652 printf(" %d %d %s", rwalk->rule.disk.dmin, rwalk->rule.disk.dmax, colorname(rwalk->rule.disk.color));
1653 }
1654 break;
1655
1656 case C_INODE:
1657 if (!rwalk->rule.inode.fsexp) break;
1658
1659 printf("INODE %s", rwalk->rule.inode.fsexp->pattern);
1660 if (rwalk->rule.inode.ignored)
1661 printf(" IGNORE");
1662 else {
1663 printf(" %lu%c", rwalk->rule.inode.warnlevel, (rwalk->rule.inode.abswarn ? 'U' : '%'));
1664 printf(" %lu%c", rwalk->rule.inode.paniclevel, (rwalk->rule.inode.abspanic ? 'U' : '%'));
1665 printf(" %d %d %s", rwalk->rule.inode.imin, rwalk->rule.inode.imax, colorname(rwalk->rule.inode.color));
1666 }
1667 break;
1668
1669 case C_MEM:
1670 switch (rwalk->rule.mem.memtype) {
1671 case C_MEM_PHYS: printf("MEMREAL"); break;
1672 case C_MEM_SWAP: printf("MEMSWAP"); break;
1673 case C_MEM_ACT: printf("MEMACT"); break;
1674 }
1675 printf(" %d %d", rwalk->rule.mem.warnlevel, rwalk->rule.mem.paniclevel);
1676 break;
1677
1678 case C_ASID:
1679 switch (rwalk->rule.asid.asidtype) {
1680 case C_ASID_MAXUSER: printf("MAXUSER: "); break;
1681 case C_ASID_NPARTS: printf(" NPARTS: "); break;
1682 }
1683 printf(" %d %d", rwalk->rule.asid.warnlevel, rwalk->rule.asid.paniclevel);
1684 break;
1685
1686 case C_PROC:
1687 if (!rwalk->rule.proc.procexp) break;
1688
1689 if (strchr(rwalk->rule.proc.procexp->pattern, ' ') ||
1690 strchr(rwalk->rule.proc.procexp->pattern, '\t')) {
1691 printf("PROC \"%s\" %d %d %s", rwalk->rule.proc.procexp->pattern,
1692 rwalk->rule.proc.pmin, rwalk->rule.proc.pmax, colorname(rwalk->rule.proc.color));
1693 }
1694 else {
1695 printf("PROC %s %d %d %s", rwalk->rule.proc.procexp->pattern,
1696 rwalk->rule.proc.pmin, rwalk->rule.proc.pmax, colorname(rwalk->rule.proc.color));
1697 }
1698 break;
1699
1700 case C_LOG:
1701 if (!rwalk->rule.log.logfile || !rwalk->rule.log.matchexp) break;
1702
1703 printf("LOG %s MATCH=%s COLOR=%s",
1704 rwalk->rule.log.logfile->pattern,
1705 rwalk->rule.log.matchexp->pattern,
1706 colorname(rwalk->rule.log.color));
1707 if (rwalk->rule.log.ignoreexp) printf(" IGNORE=%s", rwalk->rule.log.ignoreexp->pattern);
1708 break;
1709
1710 case C_FILE:
1711 if (!rwalk->rule.fcheck.filename) break;
1712
1713 printf("FILE %s %s", rwalk->rule.fcheck.filename->pattern,
1714 colorname(rwalk->rule.fcheck.color));
1715
1716 if (rwalk->flags & FCHK_NOEXIST)
1717 printf(" noexist");
1718 if (rwalk->flags & FCHK_TYPE)
1719 printf(" type=%s", ftypestr(rwalk->rule.fcheck.ftype));
1720 if (rwalk->flags & FCHK_MODE)
1721 printf(" mode=%o", rwalk->rule.fcheck.fmode);
1722 #ifdef _LARGEFILE_SOURCE
1723 if (rwalk->flags & FCHK_MINSIZE)
1724 printf(" size>%lld", (long long int)rwalk->rule.fcheck.minsize);
1725 if (rwalk->flags & FCHK_MAXSIZE)
1726 printf(" size<%lld", (long long int)rwalk->rule.fcheck.maxsize);
1727 if (rwalk->flags & FCHK_EQLSIZE)
1728 printf(" size=%lld", (long long int)rwalk->rule.fcheck.eqlsize);
1729 #else
1730 if (rwalk->flags & FCHK_MINSIZE)
1731 printf(" size>%ld", rwalk->rule.fcheck.minsize);
1732 if (rwalk->flags & FCHK_MAXSIZE)
1733 printf(" size<%ld", rwalk->rule.fcheck.maxsize);
1734 if (rwalk->flags & FCHK_EQLSIZE)
1735 printf(" size=%ld", rwalk->rule.fcheck.eqlsize);
1736 #endif
1737 if (rwalk->flags & FCHK_MINLINKS)
1738 printf(" links>%u", rwalk->rule.fcheck.minlinks);
1739 if (rwalk->flags & FCHK_MAXLINKS)
1740 printf(" links<%u", rwalk->rule.fcheck.maxlinks);
1741 if (rwalk->flags & FCHK_EQLLINKS)
1742 printf(" links=%u", rwalk->rule.fcheck.eqllinks);
1743 if (rwalk->flags & FCHK_OWNERID)
1744 printf(" owner=%u", rwalk->rule.fcheck.ownerid);
1745 if (rwalk->flags & FCHK_OWNERSTR)
1746 printf(" owner=%s", rwalk->rule.fcheck.ownerstr);
1747 if (rwalk->flags & FCHK_GROUPID)
1748 printf(" group=%u", rwalk->rule.fcheck.groupid);
1749 if (rwalk->flags & FCHK_GROUPSTR)
1750 printf(" group=%s", rwalk->rule.fcheck.groupstr);
1751 if (rwalk->flags & FCHK_CTIMEMIN)
1752 printf(" ctime>%u", rwalk->rule.fcheck.minctimedif);
1753 if (rwalk->flags & FCHK_CTIMEMAX)
1754 printf(" ctime<%u", rwalk->rule.fcheck.maxctimedif);
1755 if (rwalk->flags & FCHK_CTIMEEQL)
1756 printf(" ctime=%u", rwalk->rule.fcheck.ctimeeql);
1757 if (rwalk->flags & FCHK_MTIMEMIN)
1758 printf(" mtime>%u", rwalk->rule.fcheck.minmtimedif);
1759 if (rwalk->flags & FCHK_MTIMEMAX)
1760 printf(" mtime<%u", rwalk->rule.fcheck.maxmtimedif);
1761 if (rwalk->flags & FCHK_MTIMEEQL)
1762 printf(" mtime=%u", rwalk->rule.fcheck.mtimeeql);
1763 if (rwalk->flags & FCHK_ATIMEMIN)
1764 printf(" atime>%u", rwalk->rule.fcheck.minatimedif);
1765 if (rwalk->flags & FCHK_ATIMEMAX)
1766 printf(" atime<%u", rwalk->rule.fcheck.maxatimedif);
1767 if (rwalk->flags & FCHK_ATIMEEQL)
1768 printf(" atime=%u", rwalk->rule.fcheck.atimeeql);
1769 if (rwalk->flags & FCHK_MD5)
1770 printf(" md5=%s", rwalk->rule.fcheck.md5hash);
1771 if (rwalk->flags & FCHK_SHA1)
1772 printf(" sha1=%s", rwalk->rule.fcheck.sha1hash);
1773 if (rwalk->flags & FCHK_SHA256)
1774 printf(" sha256=%s", rwalk->rule.fcheck.sha256hash);
1775 if (rwalk->flags & FCHK_SHA512)
1776 printf(" sha512=%s", rwalk->rule.fcheck.sha512hash);
1777 if (rwalk->flags & FCHK_SHA224)
1778 printf(" sha224=%s", rwalk->rule.fcheck.sha224hash);
1779 if (rwalk->flags & FCHK_SHA384)
1780 printf(" sha384=%s", rwalk->rule.fcheck.sha384hash);
1781 if (rwalk->flags & FCHK_RMD160)
1782 printf(" rmd160=%s", rwalk->rule.fcheck.rmd160hash);
1783 break;
1784
1785 case C_DIR:
1786 if (!rwalk->rule.dcheck.filename) break;
1787
1788 printf("DIR %s %s", rwalk->rule.dcheck.filename->pattern,
1789 colorname(rwalk->rule.dcheck.color));
1790
1791 if (rwalk->flags & FCHK_MINSIZE)
1792 printf(" size>%lu", rwalk->rule.dcheck.minsize);
1793 if (rwalk->flags & FCHK_MAXSIZE)
1794 printf(" size<%lu", rwalk->rule.dcheck.maxsize);
1795 break;
1796
1797 case C_PORT:
1798 printf("PORT");
1799 if (rwalk->rule.port.localexp)
1800 printf(" local=%s", rwalk->rule.port.localexp->pattern);
1801 if (rwalk->rule.port.exlocalexp)
1802 printf(" exlocal=%s", rwalk->rule.port.exlocalexp->pattern);
1803 if (rwalk->rule.port.remoteexp)
1804 printf(" remote=%s", rwalk->rule.port.remoteexp->pattern);
1805 if (rwalk->rule.port.exremoteexp)
1806 printf(" exremote=%s", rwalk->rule.port.exremoteexp->pattern);
1807 if (rwalk->rule.port.stateexp)
1808 printf(" state=%s", rwalk->rule.port.stateexp->pattern);
1809 if (rwalk->rule.port.exstateexp)
1810 printf(" exstate=%s", rwalk->rule.port.exstateexp->pattern);
1811 if (rwalk->rule.port.pmin != -1)
1812 printf(" min=%d", rwalk->rule.port.pmin);
1813 if (rwalk->rule.port.pmax != -1)
1814 printf(" max=%d", rwalk->rule.port.pmax);
1815 printf(" color=%s", colorname(rwalk->rule.port.color));
1816 break;
1817
1818 case C_PAGING:
1819 printf("PAGING %d %d", rwalk->rule.paging.warnlevel, rwalk->rule.paging.paniclevel);
1820 break;
1821
1822 case C_MEM_VSIZE:
1823 printf("z/VSE VSIZE %d %d", rwalk->rule.zvse_vsize.warnlevel, rwalk->rule.zvse_vsize.paniclevel);
1824 break;
1825
1826 case C_MEM_GETVIS:
1827 break;
1828
1829 case C_CICS:
1830 if (!rwalk->rule.cics.applid) break;
1831
1832 printf("CICS: Appid:%s, DSA warning:%d, DSA panic:%d, EDSA warning%d, EDSA panic:%d", rwalk->rule.cics.applid->pattern, rwalk->rule.cics.dsawarnlevel, rwalk->rule.cics.dsapaniclevel, rwalk->rule.cics.edsawarnlevel, rwalk->rule.cics.edsapaniclevel);
1833 break;
1834
1835 case C_SVC:
1836 if (!rwalk->rule.svc.svcexp) break;
1837
1838 printf("SVC %s", rwalk->rule.svc.svcexp->pattern);
1839 if (rwalk->rule.svc.stateexp)
1840 printf(" status=%s", rwalk->rule.svc.stateexp->pattern);
1841 if (rwalk->rule.svc.startupexp)
1842 printf(" startup=%s", rwalk->rule.svc.startupexp->pattern);
1843 printf(" color=%s", colorname(rwalk->rule.svc.color));
1844 break;
1845
1846 case C_MIBVAL:
1847 printf("MIB");
1848 if (rwalk->rule.mibval.mibvalexp)
1849 printf(" %s", rwalk->rule.mibval.mibvalexp->pattern);
1850 if (rwalk->rule.mibval.keyexp)
1851 printf(" key=%s", rwalk->rule.mibval.keyexp->pattern);
1852 if (rwalk->flags & MIBCHK_MINVALUE)
1853 printf(" min=%ld", rwalk->rule.mibval.minval);
1854 if (rwalk->flags & MIBCHK_MAXVALUE)
1855 printf(" max=%ld", rwalk->rule.mibval.maxval);
1856 if (rwalk->flags & MIBCHK_MATCH)
1857 printf(" match=%s", rwalk->rule.mibval.matchexp->pattern);
1858 printf(" color=%s", colorname(rwalk->rule.mibval.color));
1859 break;
1860
1861 case C_RRDDS:
1862 if (!rwalk->rule.rrdds.rrdkey) break;
1863
1864 printf("DS %s %s:%s", rwalk->rule.rrdds.column,
1865 rwalk->rule.rrdds.rrdkey->pattern, rwalk->rule.rrdds.rrdds);
1866 if (rwalk->flags & RRDDSCHK_GT)
1867 printf(" >%.2f", rwalk->rule.rrdds.limitval);
1868 if (rwalk->flags & RRDDSCHK_GE)
1869 printf(" >=%.2f", rwalk->rule.rrdds.limitval);
1870
1871 if (rwalk->flags & RRDDSCHK_INTVL) {
1872 if (rwalk->flags & RRDDSCHK_LT)
1873 printf(" <%.2f", rwalk->rule.rrdds.limitval2);
1874 if (rwalk->flags & RRDDSCHK_LE)
1875 printf(" <=%.2f", rwalk->rule.rrdds.limitval2);
1876 }
1877 else {
1878 if (rwalk->flags & RRDDSCHK_LT)
1879 printf(" <%.2f", rwalk->rule.rrdds.limitval);
1880 if (rwalk->flags & RRDDSCHK_LE)
1881 printf(" <=%.2f", rwalk->rule.rrdds.limitval);
1882 }
1883 printf(" color=%s", colorname(rwalk->rule.rrdds.color));
1884 break;
1885
1886 case C_MQ_QUEUE:
1887 if (!rwalk->rule.mqqueue.qmgrname || !rwalk->rule.mqqueue.qname) break;
1888
1889 printf("MQ_QUEUE %s:%s", rwalk->rule.mqqueue.qmgrname->pattern, rwalk->rule.mqqueue.qname->pattern);
1890 if (rwalk->rule.mqqueue.warnlen != -1)
1891 printf(" depth-warn=%d", rwalk->rule.mqqueue.warnlen);
1892 if (rwalk->rule.mqqueue.critlen != -1)
1893 printf(" depth-critical=%d", rwalk->rule.mqqueue.critlen);
1894 if (rwalk->rule.mqqueue.warnage != -1)
1895 printf(" age-warn=%d", rwalk->rule.mqqueue.warnage);
1896 if (rwalk->rule.mqqueue.critage != -1)
1897 printf(" age-critical=%d", rwalk->rule.mqqueue.critage);
1898 break;
1899
1900 case C_MQ_CHANNEL:
1901 if (!rwalk->rule.mqchannel.qmgrname || !rwalk->rule.mqchannel.chnname) break;
1902
1903 printf("MQ_CHANNEL %s:%s",rwalk->rule.mqchannel.qmgrname->pattern , rwalk->rule.mqchannel.chnname->pattern);
1904 if (rwalk->rule.mqchannel.warnstates) printf(" warning=%s", rwalk->rule.mqchannel.warnstates->pattern);
1905 if (rwalk->rule.mqchannel.alertstates) printf(" alert=%s", rwalk->rule.mqchannel.alertstates->pattern);
1906 break;
1907 }
1908
1909 if (rwalk->chkflags & CHK_TRACKIT) {
1910 printf(" TRACK");
1911 if (rwalk->rrdidstr) printf("=%s", rwalk->rrdidstr);
1912 }
1913
1914 if (rwalk->chkflags & CHK_OPTIONAL) printf(" OPTIONAL");
1915
1916 if (rwalk->timespec) printf(" TIME=%s", rwalk->timespec);
1917 if (rwalk->extimespec) printf(" EXTIME=%s", rwalk->extimespec);
1918 if (rwalk->hostexp) printf(" HOST=%s", rwalk->hostexp->pattern);
1919 if (rwalk->exhostexp) printf(" EXHOST=%s", rwalk->exhostexp->pattern);
1920 if (rwalk->dgexp) printf(" DISPLAYGROUP=%s", rwalk->dgexp->pattern);
1921 if (rwalk->exdgexp) printf(" EXDISPLAYGROUP=%s", rwalk->exdgexp->pattern);
1922 if (rwalk->pageexp) printf(" PAGE=%s", rwalk->pageexp->pattern);
1923 if (rwalk->expageexp) printf(" EXPAGE=%s", rwalk->expageexp->pattern);
1924 if (rwalk->classexp) printf(" CLASS=%s", rwalk->classexp->pattern);
1925 if (rwalk->exclassexp) printf(" EXCLASS=%s", rwalk->exclassexp->pattern);
1926 if (rwalk->statustext) printf(" TEXT=%s", rwalk->statustext);
1927 printf(" (line: %d)\n", rwalk->cfid);
1928 }
1929 }
1930
getrule(char * hostname,char * pagename,char * classname,void * hinfo,ruletype_t ruletype)1931 static c_rule_t *getrule(char *hostname, char *pagename, char *classname, void *hinfo, ruletype_t ruletype)
1932 {
1933 static ruleset_t *rwalk = NULL;
1934 char *holidayset;
1935
1936 if (hostname || pagename) {
1937 rwalk = ruleset(hostname, pagename, classname);
1938 }
1939 else {
1940 if (rwalk) rwalk = rwalk->next;
1941 }
1942
1943 holidayset = (hinfo ? xmh_item(hinfo, XMH_HOLIDAYS) : NULL);
1944
1945 for (; (rwalk); rwalk = rwalk->next) {
1946 if (rwalk->rule->ruletype != ruletype) continue;
1947 if (rwalk->rule->timespec && !timematch(holidayset, rwalk->rule->timespec)) continue;
1948 if (rwalk->rule->extimespec && timematch(holidayset, rwalk->rule->extimespec)) continue;
1949
1950 /* If we get here, then we have something that matches */
1951 return rwalk->rule;
1952 }
1953
1954 return NULL;
1955 }
1956
get_cpu_thresholds(void * hinfo,char * classname,float * loadyellow,float * loadred,int * recentlimit,int * ancientlimit,int * uptimecolor,int * maxclockdiff,int * clockdiffcolor)1957 int get_cpu_thresholds(void *hinfo, char *classname,
1958 float *loadyellow, float *loadred,
1959 int *recentlimit, int *ancientlimit, int *uptimecolor,
1960 int *maxclockdiff, int *clockdiffcolor)
1961 {
1962 int result = 0;
1963 char *hostname, *pagename;
1964 c_rule_t *rule;
1965
1966 hostname = xmh_item(hinfo, XMH_HOSTNAME);
1967 pagename = xmh_item(hinfo, XMH_ALLPAGEPATHS);
1968
1969 *loadyellow = 5.0;
1970 *loadred = 10.0;
1971 *uptimecolor = *clockdiffcolor = COL_YELLOW;
1972
1973 rule = getrule(hostname, pagename, classname, hinfo, C_LOAD);
1974 if (rule) {
1975 *loadyellow = rule->rule.load.warnlevel;
1976 *loadred = rule->rule.load.paniclevel;
1977 result = rule->cfid;
1978 }
1979
1980 *recentlimit = 3600;
1981 *ancientlimit = -1;
1982
1983 rule = getrule(hostname, pagename, classname, hinfo, C_UPTIME);
1984 if (rule) {
1985 *recentlimit = rule->rule.uptime.recentlimit;
1986 *ancientlimit = rule->rule.uptime.ancientlimit;
1987 *uptimecolor = rule->rule.uptime.color;
1988 result = rule->cfid;
1989 }
1990
1991 *maxclockdiff = -1;
1992 rule = getrule(hostname, pagename, classname, hinfo, C_CLOCK);
1993 if (rule) {
1994 *maxclockdiff = rule->rule.clock.maxdiff;
1995 *clockdiffcolor = rule->rule.clock.color;
1996 }
1997
1998 return result;
1999 }
2000
get_disk_thresholds(void * hinfo,char * classname,char * fsname,long * warnlevel,long * paniclevel,int * abswarn,int * abspanic,int * ignored,char ** group)2001 int get_disk_thresholds(void *hinfo, char *classname,
2002 char *fsname,
2003 long *warnlevel, long *paniclevel,
2004 int *abswarn, int *abspanic,
2005 int *ignored, char **group)
2006 {
2007 char *hostname, *pagename;
2008 c_rule_t *rule;
2009
2010 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2011 pagename = xmh_item(hinfo, XMH_ALLPAGEPATHS);
2012
2013 *warnlevel = 90;
2014 *paniclevel = 95;
2015 *abswarn = 0;
2016 *abspanic = 0;
2017 *ignored = 0;
2018 *group = NULL;
2019
2020 rule = getrule(hostname, pagename, classname, hinfo, C_DISK);
2021 while (rule && (!rule->rule.disk.fsexp || !namematch(fsname, rule->rule.disk.fsexp->pattern, rule->rule.disk.fsexp->exp))) {
2022 rule = getrule(NULL, NULL, NULL, hinfo, C_DISK);
2023 }
2024
2025 if (rule) {
2026 *warnlevel = rule->rule.disk.warnlevel;
2027 *abswarn = rule->rule.disk.abswarn;
2028 *paniclevel = rule->rule.disk.paniclevel;
2029 *abspanic = rule->rule.disk.abspanic;
2030 *ignored = rule->rule.disk.ignored;
2031 *group = rule->groups;
2032 return rule->cfid;
2033 }
2034
2035 return 0;
2036 }
2037
get_inode_thresholds(void * hinfo,char * classname,char * fsname,long * warnlevel,long * paniclevel,int * abswarn,int * abspanic,int * ignored,char ** group)2038 int get_inode_thresholds(void *hinfo, char *classname,
2039 char *fsname,
2040 long *warnlevel, long *paniclevel,
2041 int *abswarn, int *abspanic,
2042 int *ignored, char **group)
2043 {
2044 char *hostname, *pagename;
2045 c_rule_t *rule;
2046
2047 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2048 pagename = xmh_item(hinfo, XMH_PAGEPATH);
2049
2050 *warnlevel = 70;
2051 *paniclevel = 90;
2052 *abswarn = 0;
2053 *abspanic = 0;
2054 *ignored = 0;
2055 *group = NULL;
2056
2057 rule = getrule(hostname, pagename, classname, hinfo, C_INODE);
2058 while (rule && (!rule->rule.inode.fsexp || !namematch(fsname, rule->rule.inode.fsexp->pattern, rule->rule.inode.fsexp->exp))) {
2059 rule = getrule(NULL, NULL, NULL, hinfo, C_INODE);
2060 }
2061
2062 if (rule) {
2063 *warnlevel = rule->rule.inode.warnlevel;
2064 *abswarn = rule->rule.inode.abswarn;
2065 *paniclevel = rule->rule.inode.paniclevel;
2066 *abspanic = rule->rule.inode.abspanic;
2067 *ignored = rule->rule.inode.ignored;
2068 *group = rule->groups;
2069 return rule->cfid;
2070 }
2071
2072 return 0;
2073 }
2074
get_cics_thresholds(void * hinfo,char * classname,char * appid,int * dsayel,int * dsared,int * edsayel,int * edsared)2075 void get_cics_thresholds(void *hinfo, char *classname, char *appid,
2076 int *dsayel, int *dsared, int *edsayel, int *edsared)
2077 {
2078 char *hostname, *pagename;
2079 c_rule_t *rule;
2080
2081 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2082 pagename = xmh_item(hinfo, XMH_PAGEPATH);
2083
2084 *dsayel = 90;
2085 *dsared = 95;
2086 *edsayel = 90;
2087 *edsared = 95;
2088
2089 /* Get thresholds for CICS DSA */
2090 rule = getrule(hostname, pagename, classname, hinfo, C_CICS);
2091
2092 /* This is sort of cheating, because the while statement that follows should catch it
2093 but it doesn't. So if there is a way to solve the problem I welcome some tips... */
2094 if (!rule) {
2095 return;
2096 }
2097
2098 while (rule && (!rule->rule.cics.applid || !namematch(appid, rule->rule.cics.applid->pattern, rule->rule.cics.applid->exp))) {
2099 rule = getrule(NULL, NULL, NULL, hinfo, C_CICS);
2100 }
2101
2102 if (rule) {
2103 *dsayel = rule->rule.cics.dsawarnlevel;
2104 *dsared = rule->rule.cics.dsapaniclevel;
2105 *edsayel = rule->rule.cics.edsawarnlevel;
2106 *edsared = rule->rule.cics.edsapaniclevel;
2107 }
2108
2109 }
2110
get_zvsevsize_thresholds(void * hinfo,char * classname,int * usedyel,int * usedred)2111 void get_zvsevsize_thresholds(void *hinfo, char *classname,
2112 int *usedyel, int *usedred)
2113 {
2114 char *hostname, *pagename;
2115 c_rule_t *rule;
2116
2117 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2118 pagename = xmh_item(hinfo, XMH_PAGEPATH);
2119
2120 *usedyel = 90;
2121 *usedred = 95;
2122
2123 /* Get thresholds for z/VSE System Memory */
2124 rule = getrule(hostname, pagename, classname, hinfo, C_MEM_VSIZE);
2125
2126 if (rule) {
2127 *usedyel = rule->rule.zvse_vsize.warnlevel;
2128 *usedred = rule->rule.zvse_vsize.paniclevel;
2129 }
2130 }
2131
get_zvsegetvis_thresholds(void * hinfo,char * classname,char * pid,int * gv24yel,int * gv24red,int * gvanyyel,int * gvanyred)2132 void get_zvsegetvis_thresholds(void *hinfo, char *classname, char *pid,
2133 int *gv24yel, int *gv24red, int *gvanyyel, int *gvanyred)
2134 {
2135 char *hostname, *pagename;
2136 c_rule_t *rule;
2137
2138 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2139 pagename = xmh_item(hinfo, XMH_PAGEPATH);
2140
2141 *gv24yel = 90;
2142 *gv24red = 95;
2143 *gvanyyel = 90;
2144 *gvanyred = 95;
2145
2146 /* Get thresholds for z/VSE Partition Getvis */
2147 rule = getrule(hostname, pagename, classname, hinfo, C_MEM_GETVIS);
2148
2149 /* This is sort of cheating, because the while statement that follows should catch it
2150 but it doesn't. So if there is a way to solve the problem I welcome some tips... */
2151 if (!rule) {
2152 return;
2153 }
2154
2155 while (rule && (!rule->rule.zvse_getvis.partid || !namematch(pid, rule->rule.zvse_getvis.partid->pattern, rule->rule.zvse_getvis.partid->exp))) {
2156 rule = getrule(NULL, NULL, NULL, hinfo, C_MEM_GETVIS);
2157 }
2158
2159 if (rule) {
2160 *gv24yel = rule->rule.zvse_getvis.warnlevel;
2161 *gv24red = rule->rule.zvse_getvis.paniclevel;
2162 *gvanyyel = rule->rule.zvse_getvis.anywarnlevel;
2163 *gvanyred = rule->rule.zvse_getvis.anypaniclevel;
2164 }
2165 }
2166
get_memory_thresholds(void * hinfo,char * classname,int * physyellow,int * physred,int * swapyellow,int * swapred,int * actyellow,int * actred)2167 void get_memory_thresholds(void *hinfo, char *classname,
2168 int *physyellow, int *physred, int *swapyellow, int *swapred, int *actyellow, int *actred)
2169 {
2170 char *hostname, *pagename;
2171 c_rule_t *rule;
2172 int gotphys = 0, gotswap = 0, gotact = 0;
2173
2174 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2175 pagename = xmh_item(hinfo, XMH_ALLPAGEPATHS);
2176
2177 *physyellow = 100;
2178 *physred = 101;
2179 *swapyellow = 50;
2180 *swapred = 80;
2181 *actyellow = 90;
2182 *actred = 97;
2183
2184 rule = getrule(hostname, pagename, classname, hinfo, C_MEM);
2185 while (rule) {
2186 switch (rule->rule.mem.memtype) {
2187 case C_MEM_PHYS:
2188 if (!gotphys) {
2189 *physyellow = rule->rule.mem.warnlevel;
2190 *physred = rule->rule.mem.paniclevel;
2191 gotphys = 1;
2192 }
2193 break;
2194 case C_MEM_ACT:
2195 if (!gotact) {
2196 *actyellow = rule->rule.mem.warnlevel;
2197 *actred = rule->rule.mem.paniclevel;
2198 gotact = 1;
2199 }
2200 break;
2201 case C_MEM_SWAP:
2202 if (!gotswap) {
2203 *swapyellow = rule->rule.mem.warnlevel;
2204 *swapred = rule->rule.mem.paniclevel;
2205 gotswap = 1;
2206 }
2207 break;
2208 }
2209 rule = getrule(NULL, NULL, NULL, hinfo, C_MEM);
2210 }
2211 }
2212
get_zos_memory_thresholds(void * hinfo,char * classname,int * csayellow,int * csared,int * ecsayellow,int * ecsared,int * sqayellow,int * sqared,int * esqayellow,int * esqared)2213 void get_zos_memory_thresholds(void *hinfo, char *classname,
2214 int *csayellow, int *csared, int *ecsayellow, int *ecsared,
2215 int *sqayellow, int *sqared, int *esqayellow, int *esqared)
2216 {
2217 char *hostname, *pagename;
2218 c_rule_t *rule;
2219 int gotcsa = 0, gotecsa = 0, gotsqa = 0, gotesqa = 0;
2220
2221 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2222 pagename = xmh_item(hinfo, XMH_ALLPAGEPATHS);
2223
2224 *csayellow = 90;
2225 *csared = 95;
2226 *ecsayellow = 90;
2227 *ecsared = 95;
2228 *sqayellow = 90;
2229 *sqared = 95;
2230 *esqayellow = 90;
2231 *esqared = 95;
2232
2233 rule = getrule(hostname, pagename, classname, hinfo, C_MEM);
2234 while (rule) {
2235 switch (rule->rule.zos_mem.zos_memtype) {
2236 case C_MEM_CSA:
2237 if (!gotcsa) {
2238 *csayellow = rule->rule.zos_mem.warnlevel;
2239 *csared = rule->rule.zos_mem.paniclevel;
2240 gotcsa = 1;
2241 }
2242 break;
2243 case C_MEM_ECSA:
2244 if (!gotecsa) {
2245 *ecsayellow = rule->rule.zos_mem.warnlevel;
2246 *ecsared = rule->rule.zos_mem.paniclevel;
2247 gotecsa = 1;
2248 }
2249 break;
2250 case C_MEM_SQA:
2251 if (!gotsqa) {
2252 *sqayellow = rule->rule.zos_mem.warnlevel;
2253 *sqared = rule->rule.zos_mem.paniclevel;
2254 gotsqa = 1;
2255 }
2256 break;
2257 case C_MEM_ESQA:
2258 if (!gotesqa) {
2259 *esqayellow = rule->rule.zos_mem.warnlevel;
2260 *esqared = rule->rule.zos_mem.paniclevel;
2261 gotesqa = 1;
2262 }
2263 break;
2264 }
2265 rule = getrule(NULL, NULL, NULL, hinfo, C_MEM);
2266 }
2267
2268 }
2269
2270 /* This routine doubles to get threshold values for z/OS Maxuser and z/VSE Nparts. */
get_asid_thresholds(void * hinfo,char * classname,int * maxyellow,int * maxred)2271 void get_asid_thresholds(void *hinfo, char *classname,
2272 int *maxyellow, int *maxred)
2273 {
2274 int gotmaxuser = 0, gotnparts = 0;
2275 char *hostname, *pagename;
2276 c_rule_t *rule;
2277
2278 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2279 pagename = xmh_item(hinfo, XMH_ALLPAGEPATHS);
2280
2281 *maxyellow = 101;
2282 *maxred = 101;
2283
2284 rule = getrule(hostname, pagename, classname, hinfo, C_ASID);
2285 while (rule) {
2286 switch (rule->rule.asid.asidtype) {
2287 case C_ASID_MAXUSER:
2288 if (!gotmaxuser) {
2289 *maxyellow = rule->rule.asid.warnlevel;
2290 *maxred = rule->rule.asid.paniclevel;
2291 gotmaxuser = 1;
2292 }
2293 break;
2294 case C_ASID_NPARTS:
2295 if (!gotnparts) {
2296 *maxyellow = rule->rule.asid.warnlevel;
2297 *maxred = rule->rule.asid.paniclevel;
2298 gotnparts = 1;
2299 }
2300 break;
2301 }
2302 rule = getrule(NULL, NULL, NULL, hinfo, C_ASID);
2303 }
2304
2305 }
2306
get_paging_thresholds(void * hinfo,char * classname,int * pagingyellow,int * pagingred)2307 int get_paging_thresholds(void *hinfo, char *classname, int *pagingyellow, int *pagingred)
2308 {
2309 int result = 0;
2310 char *hostname, *pagename;
2311 c_rule_t *rule;
2312
2313 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2314 pagename = xmh_item(hinfo, XMH_PAGEPATH);
2315
2316 *pagingyellow = 5;
2317 *pagingred = 10;
2318
2319 rule = getrule(hostname, pagename, classname, hinfo, C_PAGING);
2320 if (rule) {
2321 *pagingyellow = rule->rule.paging.warnlevel;
2322 *pagingred = rule->rule.paging.paniclevel;
2323 result = rule->cfid;
2324 }
2325
2326 return result;
2327 }
2328
get_mibval_thresholds(void * hinfo,char * classname,char * mibname,char * keyname,char * valname,long * minval,long * maxval,void ** matchexp,int * color,char ** group)2329 int get_mibval_thresholds(void *hinfo, char *classname,
2330 char *mibname, char *keyname, char *valname,
2331 long *minval, long *maxval, void **matchexp, int *color, char **group)
2332 {
2333 static void * mibnametree;
2334 static int have_mibnametree = 0;
2335 char *hostname, *pagename, *mibkeyval_id;
2336 c_rule_t *rule;
2337 xtreePos_t namhandle, valdefhandle;
2338 void * valdeftree;
2339
2340 if (!have_mibnametree) {
2341 mibnametree = xtreeNew(strcasecmp);
2342 have_mibnametree = 1;
2343 }
2344
2345 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2346 pagename = xmh_item(hinfo, XMH_PAGEPATH);
2347
2348 /* Any potential rules at all ? */
2349 rule = getrule(hostname, pagename, classname, hinfo, C_MIBVAL);
2350 if (!rule) return -1;
2351
2352 *minval = LONG_MIN;
2353 *maxval = LONG_MAX;
2354 *matchexp = NULL;
2355 *color = COL_GREEN;
2356 *group = NULL;
2357
2358 /*
2359 * Configuration rules are indexed by three items:
2360 * - the MIB Name
2361 * - the MIB Key
2362 * - the Value Name
2363 *
2364 * The MIB- and Value-names are static, so we combine these into
2365 * a single key which is referenced directly in the configuration.
2366 * This is the pattern listed as the first MIB criteria in the config,
2367 * stored in the "mibvalexp" field.
2368 * For the MIB Keys we want to use a regex (so the config can refer to
2369 * all "eth.*" interfaces), so when searching for a rule we must walk
2370 * the list of potential rules for this MIB+Value name, and match the
2371 * actual key value against the pattern.
2372 *
2373 * So all in all rules are keyed with the MIB+Key+Name strings as
2374 * a unique key. Hence, to speed things up we gradually build a tree
2375 * with this key, which points directly to the rule for this item.
2376 * This is the "valdeftree" tree.
2377 *
2378 * TODO: A further optimization would be to somehow keep
2379 * track of how many single MIB variables have a configuration rule,
2380 * to avoid scanning for a configuration for variables when all config
2381 * items have been used in a message. I cannot tell right away if this
2382 * is possible - perhaps by counting the number of configuration cache
2383 * hits while processing a message, and for the next message from the
2384 * same source then only process data until this count has been done?
2385 *
2386 * Finally, for optimising memory usage, the MIB+Key+Name strings
2387 * are not duplicated for each key; instead we have a separate token-
2388 * tree (mibnametree) which holds these.
2389 */
2390
2391 /* Setup the key and find/insert it into the mibnametree */
2392 mibkeyval_id = (char *)malloc(strlen(mibname) + (keyname ? strlen(keyname) : 0) + strlen(valname) + 3);
2393 sprintf(mibkeyval_id, "%s!%s!%s", mibname, (keyname ? keyname : ""), valname);
2394 namhandle = xtreeFind(mibnametree, mibkeyval_id);
2395 if (namhandle == xtreeEnd(mibnametree)) {
2396 xtreeAdd(mibnametree, mibkeyval_id, mibkeyval_id);
2397 }
2398 else {
2399 xfree(mibkeyval_id); /* Discard our copy - we now use the tree value */
2400 mibkeyval_id = (char *)xtreeData(mibnametree, namhandle);
2401 }
2402
2403 /* Create the rule tree (if it does not exist); look up the ruleset */
2404 if (!rule->rule.mibval.havetree) {
2405 rule->rule.mibval.havetree = 1;
2406 valdeftree = rule->rule.mibval.valdeftree = xtreeNew(strcasecmp);
2407 valdefhandle = xtreeEnd(rule->rule.mibval.valdeftree);
2408 }
2409 else {
2410 valdeftree = rule->rule.mibval.valdeftree;
2411 valdefhandle = xtreeFind(valdeftree, mibkeyval_id);
2412 }
2413
2414 if (valdefhandle == xtreeEnd(valdeftree)) {
2415 /*
2416 * Ruleset not in the tree.
2417 * Scan the configuration set for a rule matching this
2418 * MIB+Value name, and where the keyname matches.
2419 * Then insert the result into the tree (even if there is no
2420 * rule matching at all - we also cache the negative lookups!
2421 */
2422 int found = 0;
2423 char *mibval_id = (char *)malloc(strlen(mibname) + strlen(valname) + 2);
2424 sprintf(mibval_id, "%s:%s", mibname, valname);
2425
2426 while (rule && !found) {
2427 found = (rule->rule.mibval.mibvalexp && namematch(mibval_id, rule->rule.mibval.mibvalexp->pattern, rule->rule.mibval.mibvalexp->exp));
2428 if (found && keyname && rule->rule.mibval.keyexp)
2429 found = namematch(keyname, rule->rule.mibval.keyexp->pattern, rule->rule.mibval.keyexp->exp);
2430 if (!found) rule = getrule(NULL, NULL, NULL, hinfo, C_MIBVAL);
2431 }
2432
2433 xtreeAdd(valdeftree, mibkeyval_id, rule);
2434
2435 xfree(mibval_id);
2436 }
2437 else {
2438 /* Found the rule */
2439 rule = (c_rule_t *)xtreeData(valdeftree, valdefhandle);
2440 }
2441
2442 if (rule) {
2443 *color = rule->rule.mibval.color;
2444 *group = rule->groups;
2445 if (rule->flags & MIBCHK_MINVALUE) *minval = rule->rule.mibval.minval;
2446 if (rule->flags & MIBCHK_MAXVALUE) *maxval = rule->rule.mibval.maxval;
2447 if (rule->flags & MIBCHK_MATCH) *matchexp = rule->rule.mibval.matchexp;
2448 }
2449
2450 return (rule ? rule->cfid : 0);
2451 }
2452
2453
check_mibvals(void * hinfo,char * classname,char * mibname,char * keyname,char * mibdata,strbuffer_t * summarybuf,int * anyrules)2454 int check_mibvals(void *hinfo, char *classname,
2455 char *mibname, char *keyname, char *mibdata,
2456 strbuffer_t *summarybuf, int *anyrules)
2457 {
2458 char *bol, *eoln, *dnam, *dval, *delimp, delim;
2459 long minval, maxval, actval;
2460 void *matchexp;
2461 int rulecolor, color = COL_GREEN;
2462 char msgline[MAX_LINE_LEN];
2463 char *group;
2464
2465 /*
2466 * Scan a single section of MIB data - without the [key] line -
2467 * and check all values against the configured limits.
2468 */
2469 *anyrules = 1;
2470 bol = mibdata;
2471 while (bol && *anyrules) {
2472 eoln = strchr(bol, '\n'); if (eoln) *eoln = '\0';
2473 dnam = bol + strspn(bol, " \t");
2474 delimp = dnam + strcspn(dnam, " ="); delim = *delimp; *delimp = '\0';
2475 dval = delimp + 1; dval += strspn(dval, " ="); actval = atol(dval);
2476
2477 switch (get_mibval_thresholds(hinfo, classname, mibname, keyname, dnam, &minval, &maxval, &matchexp, &rulecolor, &group)) {
2478 case -1:
2479 /* This means: No rules at all for this host. So just drop all further processing */
2480 *anyrules = 0;
2481 break;
2482
2483 case 0:
2484 /* No rules for this key/value, but there might be for others */
2485 break;
2486
2487 default:
2488 if (actval < minval) {
2489 if (keyname)
2490 sprintf(msgline, "&%s %s:%s %ld (minimum: %ld)\n",
2491 colorname(rulecolor), keyname, dnam, actval, minval);
2492 else
2493 sprintf(msgline, "&%s %s %ld (minimum: %ld)\n",
2494 colorname(rulecolor), dnam, actval, minval);
2495 addtobuffer(summarybuf, msgline);
2496 if (rulecolor > color) color = rulecolor;
2497 if (group) addalertgroup(group);
2498 }
2499
2500 if (actval > maxval) {
2501 if (keyname)
2502 sprintf(msgline, "&%s %s:%s %ld (maximum: %ld)\n",
2503 colorname(rulecolor), keyname, dnam, actval, maxval);
2504 else
2505 sprintf(msgline, "&%s %s %ld (maximum: %ld)\n",
2506 colorname(rulecolor), dnam, actval, maxval);
2507 addtobuffer(summarybuf, msgline);
2508 if (rulecolor > color) color = rulecolor;
2509 if (group) addalertgroup(group);
2510 }
2511
2512 if (matchexp) {
2513 if (!namematch(dval, ((exprlist_t *)matchexp)->pattern, ((exprlist_t *)matchexp)->exp)) {
2514 if (rulecolor > color) color = rulecolor;
2515 if (group) addalertgroup(group);
2516
2517 if (keyname)
2518 sprintf(msgline, "&%s %s:%s %s (expected: %s)\n",
2519 colorname(rulecolor), keyname, dnam, dval, ((exprlist_t *)matchexp)->pattern);
2520 else
2521 sprintf(msgline, "&%s %s %s (expected: %s)\n",
2522 colorname(rulecolor), dnam, dval, ((exprlist_t *)matchexp)->pattern);
2523 }
2524 else {
2525 if (keyname)
2526 sprintf(msgline, "&green %s:%s %s\n", keyname, dnam, dval);
2527 else
2528 sprintf(msgline, "&green %s %s\n", dnam, dval);
2529 }
2530
2531 addtobuffer(summarybuf, msgline);
2532 }
2533 break;
2534 }
2535
2536 *delimp = delim;
2537 if (eoln) {
2538 *eoln = '\n';
2539 bol = eoln + 1;
2540 }
2541 else {
2542 bol = NULL;
2543 }
2544 }
2545
2546 return color;
2547 }
2548
scan_log(void * hinfo,char * classname,char * logname,char * logdata,char * section,strbuffer_t * summarybuf)2549 int scan_log(void *hinfo, char *classname,
2550 char *logname, char *logdata, char *section, strbuffer_t *summarybuf)
2551 {
2552 int result = COL_GREEN;
2553 char *hostname, *pagename;
2554 c_rule_t *rule;
2555 int nofile = 0;
2556 char *boln, *eoln;
2557 char msgline[PATH_MAX];
2558
2559 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2560 pagename = xmh_item(hinfo, XMH_ALLPAGEPATHS);
2561
2562 nofile = (strncmp(logdata, "Cannot open logfile ", 20) == 0);
2563
2564 for (rule = getrule(hostname, pagename, classname, hinfo, C_LOG); (rule); rule = getrule(NULL, NULL, NULL, hinfo, C_LOG)) {
2565 int anylines = 0;
2566
2567 /* First, check if the filename matches */
2568 if (!rule->rule.log.logfile || !namematch(logname, rule->rule.log.logfile->pattern, rule->rule.log.logfile->exp)) continue;
2569
2570 if (nofile) {
2571 if (!(rule->chkflags & CHK_OPTIONAL)) {
2572 if (COL_YELLOW > result) result = COL_YELLOW;
2573 addalertgroup(rule->groups);
2574 addtobuffer(summarybuf, "&yellow Logfile not accessible \n");
2575 }
2576
2577 continue;
2578 }
2579
2580 /* Next, check for a match anywhere in the data*/
2581 if (!(rule->rule.log.matchexp && patternmatch(logdata, rule->rule.log.matchexp->pattern, rule->rule.log.matchexp->exp))) continue;
2582
2583 /* Some data in there matches what we want. Look at each line. */
2584 boln = logdata;
2585 while (boln) {
2586 eoln = strchr(boln, '\n'); if (eoln) *eoln = '\0';
2587 if (patternmatch(boln, rule->rule.log.matchone->pattern, rule->rule.log.matchone->exp)) {
2588 dbgprintf("Line '%s' matches\n", boln);
2589
2590 /* It matches. But maybe we'll ignore it ? */
2591 if (rule->rule.log.ignoreexp && patternmatch(boln, rule->rule.log.ignoreexp->pattern, rule->rule.log.ignoreexp->exp)) {
2592 /* Ignore it */
2593 }
2594 else {
2595 /* We wants it ... */
2596 dbgprintf("FOUND match in line '%s'\n", boln);
2597 anylines++;
2598 sprintf(msgline, "&%s ", colorname(rule->rule.log.color));
2599 addtobuffer(summarybuf, msgline);
2600 addtobuffer(summarybuf, prehtmlquoted(boln));
2601 addtobuffer(summarybuf, "\n");
2602 }
2603 }
2604
2605 if (eoln) {
2606 *eoln = '\n';
2607 boln = eoln+1;
2608 }
2609 else boln = NULL;
2610 }
2611
2612 /* We have a match */
2613 if (anylines) {
2614 dbgprintf("Log rule at line %d matched\n", rule->cfid);
2615 if (rule->rule.log.color != COL_GREEN) addalertgroup(rule->groups);
2616 if (rule->rule.log.color > result) result = rule->rule.log.color;
2617 }
2618 }
2619
2620 return result;
2621 }
2622
check_file(void * hinfo,char * classname,char * filename,char * filedata,char * section,strbuffer_t * summarybuf,off_t * filesize,char ** id,int * trackit,int * anyrules)2623 int check_file(void *hinfo, char *classname,
2624 char *filename, char *filedata, char *section,
2625 strbuffer_t *summarybuf, off_t *filesize,
2626 char **id, int *trackit, int *anyrules)
2627 {
2628 int result = COL_GREEN;
2629 char *hostname, *pagename;
2630 c_rule_t *rwalk;
2631 char *boln, *eoln;
2632 char msgline[PATH_MAX];
2633
2634 int exists = 1, ftype = 0, islink = 0;
2635 off_t fsize = 0;
2636 unsigned int fmode = 0, linkcount = 0;
2637 int ownerid = -1, groupid = -1;
2638 char *ownerstr = NULL, *groupstr = NULL;
2639 unsigned int ctime = 0, mtime = 0, atime = 0, clock = 0;
2640 unsigned int ctimedif, mtimedif, atimedif;
2641 char *md5hash = NULL, *sha1hash = NULL, *sha256hash = NULL, *sha512hash = NULL, *sha224hash = NULL, *sha384hash = NULL, *rmd160hash = NULL;
2642
2643 hostname = xmh_item(hinfo, XMH_HOSTNAME);
2644 pagename = xmh_item(hinfo, XMH_ALLPAGEPATHS);
2645 *trackit = *anyrules = 0;
2646
2647 boln = filedata;
2648 while (boln && *boln) {
2649 eoln = strchr(boln, '\n'); if (eoln) *eoln = '\0';
2650
2651 if (strncmp(boln, "ERROR:", 6) == 0) {
2652 exists = 0;
2653 }
2654 else if (strncmp(boln, "type:", 5) == 0) {
2655 char *tstr;
2656
2657 tstr = strchr(boln, '(');
2658 if (tstr) {
2659 if (strncmp(tstr, "(file", 5) == 0) ftype = S_IFREG;
2660 else if (strncmp(tstr, "(directory", 10) == 0) ftype = S_IFDIR;
2661 else if (strncmp(tstr, "(char-device", 12) == 0) ftype = S_IFCHR;
2662 else if (strncmp(tstr, "(block-device", 13) == 0) ftype = S_IFBLK;
2663 else if (strncmp(tstr, "(FIFO", 5) == 0) ftype = S_IFIFO;
2664 else if (strncmp(tstr, "(socket", 7) == 0) ftype = S_IFSOCK;
2665 else if (strstr(tstr, ", symlink -> ") == 0) islink = 1;
2666 }
2667 }
2668 else if (strncmp(boln, "mode:", 5) == 0) {
2669 fmode = strtol(boln+5, NULL, 8);
2670 }
2671 else if (strncmp(boln, "linkcount:", 10) == 0) {
2672 linkcount = atoi(boln+6);
2673 }
2674 else if (strncmp(boln, "owner:", 6) == 0) {
2675 ownerid = atoi(boln+6);
2676 ownerstr = strchr(boln, '(');
2677 if (ownerstr) {
2678 char *estr;
2679 ownerstr++;
2680 estr = strchr(ownerstr, ')'); if (estr) *estr = '\0';
2681 }
2682 }
2683 else if (strncmp(boln, "group:", 6) == 0) {
2684 groupid = atoi(boln+6);
2685 groupstr = strchr(boln, '(');
2686 if (groupstr) {
2687 char *estr;
2688 groupstr++;
2689 estr = strchr(groupstr, ')'); if (estr) *estr = '\0';
2690 }
2691 }
2692 else if (strncmp(boln, "size:", 5) == 0) {
2693 fsize = filesize_value(boln+5);
2694 }
2695 else if (strncmp(boln, "clock:", 6) == 0) {
2696 clock = atoi(boln+6);
2697 }
2698 else if (strncmp(boln, "atime:", 6) == 0) {
2699 atime = atoi(boln+6);
2700 }
2701 else if (strncmp(boln, "ctime:", 6) == 0) {
2702 ctime = atoi(boln+6);
2703 }
2704 else if (strncmp(boln, "mtime:", 6) == 0) {
2705 mtime = atoi(boln+6);
2706 }
2707 else if (strncmp(boln, "md5:", 4) == 0) {
2708 md5hash = boln+4;
2709 }
2710 else if (strncmp(boln, "sha1:", 5) == 0) {
2711 sha1hash = boln+5;
2712 }
2713 else if (strncmp(boln, "sha256:", 7) == 0) {
2714 sha256hash = boln+7;
2715 }
2716 else if (strncmp(boln, "sha512:", 7) == 0) {
2717 sha512hash = boln+7;
2718 }
2719 else if (strncmp(boln, "sha224:", 7) == 0) {
2720 sha224hash = boln+7;
2721 }
2722 else if (strncmp(boln, "sha384:", 7) == 0) {
2723 sha384hash = boln+7;
2724 }
2725 else if (strncmp(boln, "rmd160:", 7) == 0) {
2726 rmd160hash = boln+7;
2727 }
2728
2729 if (eoln) { boln = eoln+1; } else boln = NULL;
2730 }
2731
2732 *filesize = fsize;
2733
2734 if (clock == 0) clock = getcurrenttime(NULL);
2735 ctimedif = clock - ctime;
2736 atimedif = clock - atime;
2737 mtimedif = clock - mtime;
2738
2739 for (rwalk = getrule(hostname, pagename, classname, hinfo, C_FILE); (rwalk); rwalk = getrule(NULL, NULL, NULL, hinfo, C_FILE)) {
2740 int rulecolor = COL_GREEN;
2741
2742 /* First, check if the filename matches */
2743 if (!rwalk->rule.fcheck.filename || !namematch(filename, rwalk->rule.fcheck.filename->pattern, rwalk->rule.fcheck.filename->exp)) continue;
2744
2745 *anyrules = 1;
2746 if (!exists) {
2747 if (rwalk->chkflags & CHK_OPTIONAL) goto nextcheck;
2748
2749 if (!(rwalk->flags & FCHK_NOEXIST)) {
2750 /* Required file does not exist */
2751 rulecolor = rwalk->rule.fcheck.color;
2752 addtobuffer(summarybuf, "File is missing\n");
2753 }
2754 goto nextcheck;
2755 }
2756
2757 if (rwalk->flags & FCHK_NOEXIST) {
2758 /* File exists, but it shouldn't */
2759 rulecolor = rwalk->rule.fcheck.color;
2760 addtobuffer(summarybuf, "File exists\n");
2761 goto nextcheck;
2762 }
2763
2764 if (rwalk->flags & FCHK_TYPE) {
2765 if ( ((rwalk->rule.fcheck.ftype == S_IFLNK) && !islink) || (rwalk->rule.fcheck.ftype != ftype) ) {
2766 rulecolor = rwalk->rule.fcheck.color;
2767 sprintf(msgline, "File is a %s - should be %s\n",
2768 ftypestr(ftype), ftypestr(rwalk->rule.fcheck.ftype));
2769 addtobuffer(summarybuf, msgline);
2770 }
2771 }
2772 if (rwalk->flags & FCHK_MODE) {
2773 if (rwalk->rule.fcheck.fmode != fmode) {
2774 rulecolor = rwalk->rule.fcheck.color;
2775 sprintf(msgline, "File is mode %03o - should be %03o\n",
2776 fmode, rwalk->rule.fcheck.fmode);
2777 addtobuffer(summarybuf, msgline);
2778 }
2779 }
2780 if (rwalk->flags & FCHK_MINSIZE) {
2781 if (fsize < rwalk->rule.fcheck.minsize) {
2782 rulecolor = rwalk->rule.fcheck.color;
2783 #ifdef _LARGEFILE_SOURCE
2784 sprintf(msgline, "File has size %lld - should be >%lld\n",
2785 (long long int)fsize, (long long int)rwalk->rule.fcheck.minsize);
2786 #else
2787 sprintf(msgline, "File has size %ld - should be >%ld\n",
2788 (long int)fsize, (long int)rwalk->rule.fcheck.minsize);
2789 #endif
2790 addtobuffer(summarybuf, msgline);
2791 }
2792 }
2793 if (rwalk->flags & FCHK_MAXSIZE) {
2794 if (fsize > rwalk->rule.fcheck.maxsize) {
2795 rulecolor = rwalk->rule.fcheck.color;
2796 #ifdef _LARGEFILE_SOURCE
2797 sprintf(msgline, "File has size %lld - should be <%lld\n",
2798 (long long int)fsize, (long long int)rwalk->rule.fcheck.maxsize);
2799 #else
2800 sprintf(msgline, "File has size %ld - should be <%ld\n",
2801 (long int)fsize, (long int)rwalk->rule.fcheck.maxsize);
2802 #endif
2803 addtobuffer(summarybuf, msgline);
2804 }
2805 }
2806 if (rwalk->flags & FCHK_EQLSIZE) {
2807 if (fsize != rwalk->rule.fcheck.eqlsize) {
2808 rulecolor = rwalk->rule.fcheck.color;
2809 #ifdef _LARGEFILE_SOURCE
2810 sprintf(msgline, "File has size %lld - should be %lld\n",
2811 (long long int)fsize, (long long int)rwalk->rule.fcheck.eqlsize);
2812 #else
2813 sprintf(msgline, "File has size %ld - should be %ld\n",
2814 (long int)fsize, (long int)rwalk->rule.fcheck.eqlsize);
2815 #endif
2816 addtobuffer(summarybuf, msgline);
2817 }
2818 }
2819 if (rwalk->flags & FCHK_MINLINKS) {
2820 if (linkcount < rwalk->rule.fcheck.minlinks) {
2821 rulecolor = rwalk->rule.fcheck.color;
2822 sprintf(msgline, "File has linkcount %u - should be >%u\n",
2823 linkcount, rwalk->rule.fcheck.minlinks);
2824 addtobuffer(summarybuf, msgline);
2825 }
2826 }
2827 if (rwalk->flags & FCHK_MAXLINKS) {
2828 if (linkcount > rwalk->rule.fcheck.maxlinks) {
2829 rulecolor = rwalk->rule.fcheck.color;
2830 sprintf(msgline, "File has linkcount %u - should be <%u\n",
2831 linkcount, rwalk->rule.fcheck.maxlinks);
2832 addtobuffer(summarybuf, msgline);
2833 }
2834 }
2835 if (rwalk->flags & FCHK_OWNERID) {
2836 if (ownerid != rwalk->rule.fcheck.ownerid) {
2837 rulecolor = rwalk->rule.fcheck.color;
2838 sprintf(msgline, "File is owned by user %u - should be %u\n",
2839 ownerid, rwalk->rule.fcheck.ownerid);
2840 addtobuffer(summarybuf, msgline);
2841 }
2842 }
2843 if (rwalk->flags & FCHK_OWNERSTR) {
2844 if (!ownerstr) ownerstr = "(No owner data)";
2845 if (strcmp(ownerstr, rwalk->rule.fcheck.ownerstr) != 0) {
2846 rulecolor = rwalk->rule.fcheck.color;
2847 sprintf(msgline, "File is owned by user %s - should be %s\n",
2848 ownerstr, rwalk->rule.fcheck.ownerstr);
2849 addtobuffer(summarybuf, msgline);
2850 }
2851 }
2852 if (rwalk->flags & FCHK_GROUPID) {
2853 if (groupid != rwalk->rule.fcheck.groupid) {
2854 rulecolor = rwalk->rule.fcheck.color;
2855 sprintf(msgline, "File is owned by group %u - should be %u\n",
2856 groupid, rwalk->rule.fcheck.groupid);
2857 addtobuffer(summarybuf, msgline);
2858 }
2859 }
2860 if (rwalk->flags & FCHK_GROUPSTR) {
2861 if (!groupstr) groupstr = "(No group data)";
2862 if (strcmp(groupstr, rwalk->rule.fcheck.groupstr) != 0) {
2863 rulecolor = rwalk->rule.fcheck.color;
2864 sprintf(msgline, "File is owned by group %s - should be %s\n",
2865 groupstr, rwalk->rule.fcheck.groupstr);
2866 addtobuffer(summarybuf, msgline);
2867 }
2868 }
2869 if (rwalk->flags & FCHK_CTIMEMIN) {
2870 if (ctimedif < rwalk->rule.fcheck.minctimedif) {
2871 rulecolor = rwalk->rule.fcheck.color;
2872 sprintf(msgline, "File status changed %u seconds ago - should be >%u\n",
2873 ctimedif, rwalk->rule.fcheck.minctimedif);
2874 addtobuffer(summarybuf, msgline);
2875 }
2876 }
2877 if (rwalk->flags & FCHK_CTIMEMAX) {
2878 if (ctimedif > rwalk->rule.fcheck.maxctimedif) {
2879 rulecolor = rwalk->rule.fcheck.color;
2880 sprintf(msgline, "File status changed %u seconds ago - should be <%u\n",
2881 ctimedif, rwalk->rule.fcheck.maxctimedif);
2882 addtobuffer(summarybuf, msgline);
2883 }
2884 }
2885 if (rwalk->flags & FCHK_MTIMEMIN) {
2886 if (mtimedif < rwalk->rule.fcheck.minmtimedif) {
2887 rulecolor = rwalk->rule.fcheck.color;
2888 sprintf(msgline, "File was modified %u seconds ago - should be >%u\n",
2889 mtimedif, rwalk->rule.fcheck.minmtimedif);
2890 addtobuffer(summarybuf, msgline);
2891 }
2892 }
2893 if (rwalk->flags & FCHK_MTIMEMAX) {
2894 if (mtimedif > rwalk->rule.fcheck.maxmtimedif) {
2895 rulecolor = rwalk->rule.fcheck.color;
2896 sprintf(msgline, "File was modified %u seconds ago - should be <%u\n",
2897 mtimedif, rwalk->rule.fcheck.maxmtimedif);
2898 addtobuffer(summarybuf, msgline);
2899 }
2900 }
2901 if (rwalk->flags & FCHK_ATIMEMIN) {
2902 if (atimedif < rwalk->rule.fcheck.minatimedif) {
2903 rulecolor = rwalk->rule.fcheck.color;
2904 sprintf(msgline, "File was accessed %u seconds ago - should be >%u\n",
2905 atimedif, rwalk->rule.fcheck.minatimedif);
2906 addtobuffer(summarybuf, msgline);
2907 }
2908 }
2909 if (rwalk->flags & FCHK_ATIMEMAX) {
2910 if (atimedif > rwalk->rule.fcheck.maxatimedif) {
2911 rulecolor = rwalk->rule.fcheck.color;
2912 sprintf(msgline, "File was accessed %u seconds ago - should be <%u\n",
2913 atimedif, rwalk->rule.fcheck.maxatimedif);
2914 addtobuffer(summarybuf, msgline);
2915 }
2916 }
2917 if (rwalk->flags & FCHK_MD5) {
2918 if (!md5hash) md5hash = "(No MD5 data)";
2919 if (strcmp(md5hash, rwalk->rule.fcheck.md5hash) != 0) {
2920 rulecolor = rwalk->rule.fcheck.color;
2921 sprintf(msgline, "File has MD5 hash %s - should be %s\n",
2922 md5hash, rwalk->rule.fcheck.md5hash);
2923 addtobuffer(summarybuf, msgline);
2924 }
2925 }
2926 if (rwalk->flags & FCHK_SHA1) {
2927 if (!sha1hash) sha1hash = "(No SHA1 data)";
2928 if (strcmp(sha1hash, rwalk->rule.fcheck.sha1hash) != 0) {
2929 rulecolor = rwalk->rule.fcheck.color;
2930 sprintf(msgline, "File has SHA1 hash %s - should be %s\n",
2931 sha1hash, rwalk->rule.fcheck.sha1hash);
2932 addtobuffer(summarybuf, msgline);
2933 }
2934 }
2935 if (rwalk->flags & FCHK_SHA256) {
2936 if (!sha256hash) sha256hash = "(No SHA256 data)";
2937 if (strcmp(sha256hash, rwalk->rule.fcheck.sha256hash) != 0) {
2938 rulecolor = rwalk->rule.fcheck.color;
2939 sprintf(msgline, "File has SHA256 hash %s - should be %s\n",
2940 sha256hash, rwalk->rule.fcheck.sha256hash);
2941 addtobuffer(summarybuf, msgline);
2942 }
2943 }
2944 if (rwalk->flags & FCHK_SHA512) {
2945 if (!sha512hash) sha512hash = "(No SHA256 data)";
2946 if (strcmp(sha512hash, rwalk->rule.fcheck.sha512hash) != 0) {
2947 rulecolor = rwalk->rule.fcheck.color;
2948 sprintf(msgline, "File has SHA512 hash %s - should be %s\n",
2949 sha512hash, rwalk->rule.fcheck.sha512hash);
2950 addtobuffer(summarybuf, msgline);
2951 }
2952 }
2953 if (rwalk->flags & FCHK_SHA224) {
2954 if (!sha224hash) sha224hash = "(No SHA224 data)";
2955 if (strcmp(sha224hash, rwalk->rule.fcheck.sha224hash) != 0) {
2956 rulecolor = rwalk->rule.fcheck.color;
2957 sprintf(msgline, "File has SHA224 hash %s - should be %s\n",
2958 sha224hash, rwalk->rule.fcheck.sha224hash);
2959 addtobuffer(summarybuf, msgline);
2960 }
2961 }
2962 if (rwalk->flags & FCHK_SHA384) {
2963 if (!sha384hash) sha384hash = "(No SHA384 data)";
2964 if (strcmp(sha384hash, rwalk->rule.fcheck.sha384hash) != 0) {
2965 rulecolor = rwalk->rule.fcheck.color;
2966 sprintf(msgline, "File has SHA384 hash %s - should be %s\n",
2967 sha384hash, rwalk->rule.fcheck.sha384hash);
2968 addtobuffer(summarybuf, msgline);
2969 }
2970 }
2971 if (rwalk->flags & FCHK_RMD160) {
2972 if (!rmd160hash) rmd160hash = "(No RMD160 data)";
2973 if (strcmp(rmd160hash, rwalk->rule.fcheck.rmd160hash) != 0) {
2974 rulecolor = rwalk->rule.fcheck.color;
2975 sprintf(msgline, "File has RMD160 hash %s - should be %s\n",
2976 rmd160hash, rwalk->rule.fcheck.rmd160hash);
2977 addtobuffer(summarybuf, msgline);
2978 }
2979 }
2980 if (rwalk->chkflags & CHK_TRACKIT) {
2981 *trackit = (trackit || (ftype == S_IFREG));
2982 *id = rwalk->rrdidstr;
2983 }
2984
2985 nextcheck:
2986 if (rulecolor != COL_GREEN) addalertgroup(rwalk->groups);
2987 if (rulecolor > result) result = rulecolor;
2988 }
2989
2990 return result;
2991 }
2992
check_dir(void * hinfo,char * classname,char * filename,char * filedata,char * section,strbuffer_t * summarybuf,unsigned long * dirsize,char ** id,int * trackit)2993 int check_dir(void *hinfo, char *classname,
2994 char *filename, char *filedata, char *section,
2995 strbuffer_t *summarybuf, unsigned long *dirsize,
2996 char **id, int *trackit)
2997 {
2998 int result = COL_GREEN;
2999 int gotsize = 0;
3000 char *hostname, *pagename;
3001 c_rule_t *rwalk;
3002 char *boln, *eoln;
3003 char msgline[PATH_MAX];
3004
3005 unsigned long dsize = 0;
3006
3007 hostname = xmh_item(hinfo, XMH_HOSTNAME);
3008 pagename = xmh_item(hinfo, XMH_ALLPAGEPATHS);
3009 *trackit = 0;
3010
3011 boln = filedata;
3012 while (boln && *boln) {
3013 unsigned long sz;
3014 char *p;
3015
3016 eoln = strchr(boln, '\n'); if (eoln) *eoln = '\0';
3017
3018 /*
3019 * We need to check the directory name on each line, to
3020 * find the line that gives us the exact directory we want.
3021 * NB: Assumes the output is in the form
3022 * 12345 /foo/bar/baz
3023 */
3024 sz = atol(boln);
3025 p = boln + strcspn(boln, " \t");
3026 if (isspace((int)*p)) p += strspn(p, " \t");
3027 if (strcmp(p, filename) == 0) { gotsize = 1; dsize = sz; }
3028
3029 if (eoln) { *eoln = '\0'; boln = eoln+1; } else boln = NULL;
3030 }
3031
3032 *dirsize = dsize;
3033
3034 /* Got the data? */
3035 if (!gotsize) {
3036 sprintf(msgline, "Could not determine size of directory %s\n", filename);
3037 addtobuffer(summarybuf, msgline);
3038 return COL_YELLOW;
3039 }
3040
3041 for (rwalk = getrule(hostname, pagename, classname, hinfo, C_DIR); (rwalk); rwalk = getrule(NULL, NULL, NULL, hinfo, C_DIR)) {
3042 int rulecolor = COL_GREEN;
3043
3044 /* First, check if the filename matches */
3045 if (!rwalk->rule.fcheck.filename || !namematch(filename, rwalk->rule.fcheck.filename->pattern, rwalk->rule.fcheck.filename->exp)) continue;
3046
3047 if (rwalk->flags & FCHK_MAXSIZE) {
3048 if (dsize > rwalk->rule.dcheck.maxsize) {
3049 rulecolor = rwalk->rule.dcheck.color;
3050 sprintf(msgline, "Directory has size %lu - should be <%lu\n",
3051 dsize, rwalk->rule.dcheck.maxsize);
3052 addtobuffer(summarybuf, msgline);
3053 }
3054 }
3055 else if (rwalk->flags & FCHK_MINSIZE) {
3056 if (dsize < rwalk->rule.dcheck.minsize) {
3057 rulecolor = rwalk->rule.dcheck.color;
3058 sprintf(msgline, "Directory has size %lu - should be >%lu\n",
3059 dsize, rwalk->rule.dcheck.minsize);
3060 addtobuffer(summarybuf, msgline);
3061 }
3062 }
3063 if (rwalk->chkflags & CHK_TRACKIT) {
3064 *trackit = 1;
3065 *id = rwalk->rrdidstr;
3066 }
3067
3068 if (rulecolor != COL_GREEN) addalertgroup(rwalk->groups);
3069 if (rulecolor > result) result = rulecolor;
3070 }
3071
3072 return result;
3073 }
3074
check_rrdds_thresholds(char * hostname,char * classname,char * pagepaths,char * rrdkey,void * valnames,char * vals)3075 strbuffer_t *check_rrdds_thresholds(char *hostname, char *classname, char *pagepaths, char *rrdkey, void * valnames, char *vals)
3076 {
3077 static strbuffer_t *resbuf = NULL;
3078 char msgline[1024];
3079 c_rule_t *rule;
3080 char *valscopy = NULL;
3081 char **vallist = NULL;
3082 xtreePos_t handle;
3083 rrdtplnames_t *tpl;
3084 double val;
3085 void *hinfo;
3086
3087 if (!resbuf) resbuf = newstrbuffer(0);
3088 clearstrbuffer(resbuf);
3089
3090 hinfo = hostinfo(hostname);
3091 rule = getrule(hostname, pagepaths, classname, hinfo, C_RRDDS);
3092 while (rule) {
3093 int rulematch = 0;
3094
3095 if (strcmp(rule->rule.rrdds.column, "http") == 0) {
3096 if (!rule->rule.rrdds.rrdkey || !patternmatch(rrdkey, rule->rule.rrdds.rrdkey->pattern, rule->rule.rrdds.rrdkey->exp)) goto nextrule;
3097 }
3098 else {
3099 if (!rule->rule.rrdds.rrdkey || !namematch(rrdkey, rule->rule.rrdds.rrdkey->pattern, rule->rule.rrdds.rrdkey->exp)) goto nextrule;
3100 }
3101
3102 handle = xtreeFind(valnames, rule->rule.rrdds.rrdds);
3103 if (handle == xtreeEnd(valnames)) goto nextrule;
3104 tpl = (rrdtplnames_t *)xtreeData(valnames, handle);
3105
3106 /* Split the value-string into individual numbers that we can index */
3107 if (!vallist) {
3108 char *p;
3109 int idx = 0;
3110
3111 valscopy = strdup(vals);
3112 vallist = calloc(128, sizeof(char *));
3113 vallist[0] = valscopy;
3114
3115 for (p = strchr(valscopy, ':'); (p); p = strchr(p+1, ':')) {
3116 vallist[++idx] = p+1;
3117 *p = '\0';
3118 }
3119 }
3120
3121 if (vallist[tpl->idx] == NULL) goto nextrule;
3122 val = atof(vallist[tpl->idx]);
3123
3124 /* Do the checks */
3125 if (rule->flags & RRDDSCHK_INTVL) {
3126 rulematch = ( ( ((rule->flags & RRDDSCHK_GT) && (val > rule->rule.rrdds.limitval)) ||
3127 ((rule->flags & RRDDSCHK_GE) && (val >= rule->rule.rrdds.limitval)) ) &&
3128 ( ((rule->flags & RRDDSCHK_LT) && (val < rule->rule.rrdds.limitval2)) ||
3129 ((rule->flags & RRDDSCHK_LE) && (val <= rule->rule.rrdds.limitval2)) ) );
3130
3131 if (!rule->statustext) {
3132 char fmt[100];
3133
3134 strcpy(fmt, "&N=&V (");
3135 if (rule->flags & RRDDSCHK_GT) strcat(fmt, " > &L");
3136 else if (rule->flags & RRDDSCHK_GE) strcat(fmt, " >= &L");
3137 strcat(fmt, " and");
3138 if (rule->flags & RRDDSCHK_LT) strcat(fmt, " < &U)");
3139 else if (rule->flags & RRDDSCHK_LE) strcat(fmt, " <= &U)");
3140
3141 rule->statustext = strdup(fmt);
3142 }
3143 }
3144 else {
3145 rulematch = ( ((rule->flags & RRDDSCHK_GT) && (val > rule->rule.rrdds.limitval)) ||
3146 ((rule->flags & RRDDSCHK_GE) && (val >= rule->rule.rrdds.limitval)) ||
3147 ((rule->flags & RRDDSCHK_LT) && (val < rule->rule.rrdds.limitval)) ||
3148 ((rule->flags & RRDDSCHK_LE) && (val <= rule->rule.rrdds.limitval)) );
3149
3150 if (!rule->statustext) {
3151 char *fmt = "";
3152
3153 if (rule->flags & RRDDSCHK_GT) fmt = "&N=&V (> &L)";
3154 else if (rule->flags & RRDDSCHK_GE) fmt = "&N=&V (>= &L)";
3155 else if (rule->flags & RRDDSCHK_LT) fmt = "&N=&V (< &L)";
3156 else if (rule->flags & RRDDSCHK_LE) fmt = "&N=&V (<= &L)";
3157
3158 rule->statustext = strdup(fmt);
3159 }
3160 }
3161
3162 if (rulematch) {
3163 char *bot, *marker;
3164
3165 sprintf(msgline, "modify %s.%s %s rrdds ",
3166 hostname, rule->rule.rrdds.column,
3167 colorname(rule->rule.rrdds.color));
3168 addtobuffer(resbuf, msgline);
3169
3170 /* Format and add the status text */
3171 bot = rule->statustext;
3172 do {
3173 marker = strchr(bot, '&');
3174 if (marker) {
3175 *marker = '\0';
3176 addtobuffer(resbuf, bot);
3177 *marker = '&';
3178 switch (*(marker+1)) {
3179 case 'N': addtobuffer(resbuf, rule->rule.rrdds.rrdds);
3180 bot = marker+2;
3181 break;
3182
3183 case 'V': addtobuffer(resbuf, vallist[tpl->idx]);
3184 bot = marker+2;
3185 break;
3186
3187 case 'L': sprintf(msgline, "%.2f", rule->rule.rrdds.limitval);
3188 addtobuffer(resbuf, msgline);
3189 bot = marker+2;
3190 break;
3191
3192 case 'U': sprintf(msgline, "%.2f", (rule->flags & RRDDSCHK_INTVL) ? rule->rule.rrdds.limitval2 : rule->rule.rrdds.limitval);
3193 addtobuffer(resbuf, msgline);
3194 bot = marker+2;
3195 break;
3196
3197 default: addtobuffer(resbuf, "&"); bot = marker+1; break;
3198 }
3199 }
3200 else {
3201 addtobuffer(resbuf, bot);
3202 bot = NULL;
3203 }
3204 } while (bot);
3205
3206 addtobuffer(resbuf, "\n\n");
3207 }
3208
3209 nextrule:
3210 rule = getrule(NULL, NULL, NULL, hinfo, C_RRDDS);
3211 }
3212
3213 if (valscopy) xfree(valscopy);
3214 if (vallist) xfree(vallist);
3215
3216 return (STRBUFLEN(resbuf) > 0) ? resbuf : NULL;
3217 }
3218
3219
get_mqqueue_thresholds(void * hinfo,char * classname,char * qmgrname,char * qname,int * warnlen,int * critlen,int * warnage,int * critage,char ** trackit)3220 void get_mqqueue_thresholds(void *hinfo, char *classname, char *qmgrname, char *qname, int *warnlen, int *critlen, int *warnage, int *critage, char **trackit)
3221 {
3222 char *hostname, *pagepaths;
3223 c_rule_t *rule;
3224
3225 hostname = xmh_item(hinfo, XMH_HOSTNAME);
3226 pagepaths = xmh_item(hinfo, XMH_ALLPAGEPATHS);
3227
3228 *warnlen = *critlen = *warnage = *critage = -1;
3229 *trackit = NULL;
3230
3231 rule = getrule(hostname, pagepaths, classname, hinfo, C_MQ_QUEUE);
3232 while (rule) {
3233 if (rule->rule.mqqueue.qname && rule->rule.mqqueue.qmgrname &&
3234 namematch(qname, rule->rule.mqqueue.qname->pattern, rule->rule.mqqueue.qname->exp) &&
3235 namematch(qmgrname, rule->rule.mqqueue.qmgrname->pattern, rule->rule.mqqueue.qmgrname->exp)) {
3236 *warnlen = rule->rule.mqqueue.warnlen;
3237 *critlen = rule->rule.mqqueue.critlen;
3238 *warnage = rule->rule.mqqueue.warnage;
3239 *critage = rule->rule.mqqueue.critage;
3240 if (rule->chkflags & CHK_TRACKIT) *trackit = (rule->rrdidstr ? rule->rrdidstr : "");
3241 return;
3242 }
3243
3244 rule = getrule(NULL, NULL, NULL, hinfo, C_MQ_QUEUE);
3245 }
3246 }
3247
get_mqchannel_params(void * hinfo,char * classname,char * qmgrname,char * chnname,char * chnstatus,int * color)3248 int get_mqchannel_params(void *hinfo, char *classname, char *qmgrname, char *chnname, char *chnstatus, int *color)
3249 {
3250 char *hostname, *pagepaths;
3251 c_rule_t *rule;
3252
3253 hostname = xmh_item(hinfo, XMH_HOSTNAME);
3254 pagepaths = xmh_item(hinfo, XMH_ALLPAGEPATHS);
3255
3256 rule = getrule(hostname, pagepaths, classname, hinfo, C_MQ_CHANNEL);
3257 while (rule) {
3258 if (rule->rule.mqchannel.chnname && rule->rule.mqchannel.qmgrname &&
3259 namematch(chnname, rule->rule.mqchannel.chnname->pattern, rule->rule.mqchannel.chnname->exp) &&
3260 namematch(qmgrname, rule->rule.mqchannel.qmgrname->pattern, rule->rule.mqchannel.qmgrname->exp)) {
3261 if (rule->rule.mqchannel.alertstates && namematch(chnstatus, rule->rule.mqchannel.alertstates->pattern, rule->rule.mqchannel.alertstates->exp)) {
3262 *color = COL_RED;
3263 }
3264 else if (rule->rule.mqchannel.warnstates && namematch(chnstatus, rule->rule.mqchannel.warnstates->pattern, rule->rule.mqchannel.warnstates->exp)) {
3265 *color = COL_YELLOW;
3266 }
3267 else {
3268 *color = COL_GREEN;
3269 }
3270
3271 return 1;
3272 }
3273
3274 rule = getrule(NULL, NULL, NULL, hinfo, C_MQ_CHANNEL);
3275 }
3276
3277 return 0;
3278 }
3279
3280
3281 typedef struct mon_proc_t {
3282 c_rule_t *rule;
3283 struct mon_proc_t *next;
3284 } mon_proc_t;
3285
clear_counts(void * hinfo,char * classname,ruletype_t ruletype,mon_proc_t ** head,mon_proc_t ** tail,mon_proc_t ** walk)3286 static int clear_counts(void *hinfo, char *classname, ruletype_t ruletype,
3287 mon_proc_t **head, mon_proc_t **tail, mon_proc_t **walk)
3288 {
3289 char *hostname, *pagename;
3290 c_rule_t *rule;
3291 int count = 0;
3292
3293 while (*head) {
3294 mon_proc_t *tmp = *head;
3295 *head = (*head)->next;
3296 xfree(tmp);
3297 }
3298 *head = *tail = *walk = NULL;
3299
3300 hostname = xmh_item(hinfo, XMH_HOSTNAME);
3301 pagename = xmh_item(hinfo, XMH_ALLPAGEPATHS);
3302
3303 rule = getrule(hostname, pagename, classname, hinfo, ruletype);
3304 while (rule) {
3305 mon_proc_t *newitem = (mon_proc_t *)calloc(1, sizeof(mon_proc_t));
3306
3307 newitem->rule = rule;
3308 newitem->next = NULL;
3309 if (*tail) { (*tail)->next = newitem; *tail = newitem; }
3310 else { *head = *tail = newitem; }
3311
3312 count++;
3313 switch (rule->ruletype) {
3314 case C_DISK : rule->rule.disk.dcount = 0; break;
3315 case C_INODE: rule->rule.inode.icount = 0; break;
3316 case C_PROC : rule->rule.proc.pcount = 0; break;
3317 case C_PORT : rule->rule.port.pcount = 0; break;
3318 case C_SVC : rule->rule.svc.scount = 0; break;
3319 default: break;
3320 }
3321
3322 rule = getrule(NULL, NULL, NULL, hinfo, ruletype);
3323 }
3324
3325 *walk = *head;
3326 return count;
3327 }
3328
add_count(char * pname,mon_proc_t * head)3329 static void add_count(char *pname, mon_proc_t *head)
3330 {
3331 mon_proc_t *pwalk;
3332
3333 if (!pname) return;
3334
3335 for (pwalk = head; (pwalk); pwalk = pwalk->next) {
3336 switch (pwalk->rule->ruletype) {
3337 case C_PROC:
3338 if (!pwalk->rule->rule.proc.procexp->exp) {
3339 /*
3340 * No pattern, just see if the token in the config file is
3341 * present in the string we got from "ps". So you can setup
3342 * the config to look for "cron" and it will actually find "/usr/sbin/cron".
3343 */
3344 if (strstr(pname, pwalk->rule->rule.proc.procexp->pattern))
3345 pwalk->rule->rule.proc.pcount++;
3346 }
3347 else {
3348 /*
3349 * Strip the initial spaces, pipes and so forth seen if an ASCII forest was generated
3350 * This allows PCRE regexes using a '^' to remain useful.
3351 */
3352 pname += strspn(pname, " |\\_");
3353 if (!pname) break;
3354 if (namematch(pname, pwalk->rule->rule.proc.procexp->pattern, pwalk->rule->rule.proc.procexp->exp))
3355 pwalk->rule->rule.proc.pcount++;
3356 }
3357 break;
3358
3359 case C_DISK:
3360 if (!pwalk->rule->rule.disk.fsexp->exp) {
3361 if (strstr(pname, pwalk->rule->rule.disk.fsexp->pattern))
3362 pwalk->rule->rule.disk.dcount++;
3363 }
3364 else {
3365 if (namematch(pname, pwalk->rule->rule.disk.fsexp->pattern, pwalk->rule->rule.disk.fsexp->exp))
3366 pwalk->rule->rule.disk.dcount++;
3367 }
3368 break;
3369
3370 case C_INODE:
3371 if (!pwalk->rule->rule.inode.fsexp->exp) {
3372 if (strstr(pname, pwalk->rule->rule.inode.fsexp->pattern))
3373 pwalk->rule->rule.inode.icount++;
3374 }
3375 else {
3376 if (namematch(pname, pwalk->rule->rule.inode.fsexp->pattern, pwalk->rule->rule.inode.fsexp->exp))
3377 pwalk->rule->rule.inode.icount++;
3378 }
3379
3380 default: break;
3381 }
3382 }
3383 }
3384
check_expr_match(char * s,exprlist_t * inclexp,exprlist_t * exclexp)3385 static int check_expr_match(char *s, exprlist_t *inclexp, exprlist_t *exclexp)
3386 {
3387 int inclmatch = 0;
3388 int exclmatch = 0;
3389
3390 if (inclexp) {
3391 if (namematch(s, inclexp->pattern, inclexp->exp)) inclmatch = 1;
3392 }
3393 else inclmatch = 1;
3394
3395 /* If rejected by include spec, no need to check excludes */
3396 if (inclmatch == 0) return 0;
3397
3398 if (exclexp) {
3399 if (namematch(s, exclexp->pattern, exclexp->exp)) exclmatch = 1;
3400 }
3401
3402 /* If the exclude matched, then the whole thing does not match */
3403 if (exclmatch) return 0;
3404
3405 /* Include- and exclude-patterns match OK, we have a match */
3406 return 1;
3407 }
3408
add_count3(char * pname0,char * pname1,char * pname2,mon_proc_t * head)3409 static void add_count3(char *pname0, char *pname1, char *pname2 , mon_proc_t *head)
3410 {
3411 mon_proc_t *pwalk;
3412 int mymatch;
3413
3414 if (!pname0) return;
3415 if (!pname1) return;
3416 if (!pname2) return;
3417
3418 for (pwalk = head; (pwalk); pwalk = pwalk->next) {
3419 switch (pwalk->rule->ruletype) {
3420 case C_PORT:
3421 mymatch = 0;
3422
3423 if (check_expr_match(pname0, pwalk->rule->rule.port.localexp, pwalk->rule->rule.port.exlocalexp)) mymatch++;
3424 if (check_expr_match(pname1, pwalk->rule->rule.port.remoteexp, pwalk->rule->rule.port.exremoteexp)) mymatch++;
3425 if (check_expr_match(pname2, pwalk->rule->rule.port.stateexp, pwalk->rule->rule.port.exstateexp)) mymatch++;
3426
3427 if (mymatch == 3) {pwalk->rule->rule.port.pcount++;}
3428 break;
3429
3430 case C_SVC:
3431 mymatch = 0;
3432
3433 if (check_expr_match(pname0, pwalk->rule->rule.svc.svcexp, NULL)) {
3434 mymatch++;
3435
3436 /* Save the actual startup-method and state for later display in the status message */
3437 pwalk->rule->rule.svc.svcname = strdup(pname0);
3438 pwalk->rule->rule.svc.startup = strdup(pname1);
3439 pwalk->rule->rule.svc.state = strdup(pname2);
3440
3441 /* Startupexp and stateexp are optional - if no criteria defined, then they do match */
3442 if (!pwalk->rule->rule.svc.startupexp || check_expr_match(pname1, pwalk->rule->rule.svc.startupexp, NULL)) mymatch++;
3443 if (!pwalk->rule->rule.svc.stateexp || check_expr_match(pname2, pwalk->rule->rule.svc.stateexp, NULL)) mymatch++;
3444 }
3445
3446 if (mymatch == 3) {pwalk->rule->rule.svc.scount++;}
3447 break;
3448
3449 default:
3450 break;
3451 }
3452 }
3453 }
3454
check_count(int * count,ruletype_t ruletype,int * lowlim,int * uplim,int * color,mon_proc_t ** walk,char ** id,int * trackit,char ** group)3455 static char *check_count(int *count, ruletype_t ruletype, int *lowlim, int *uplim, int *color, mon_proc_t **walk, char **id, int *trackit,
3456 char **group)
3457 {
3458 char *result = NULL;
3459
3460 *color = COL_GREEN;
3461 *count = 0;
3462 if (*walk == NULL) return NULL;
3463
3464 switch (ruletype) {
3465 case C_PROC:
3466 result = (*walk)->rule->statustext;
3467 if (!result) result = (*walk)->rule->rule.proc.procexp->pattern;
3468 *count = (*walk)->rule->rule.proc.pcount;
3469 *lowlim = (*walk)->rule->rule.proc.pmin;
3470 *uplim = (*walk)->rule->rule.proc.pmax;
3471 if ((*lowlim != 0) && (*count < *lowlim)) *color = (*walk)->rule->rule.proc.color;
3472 if ((*uplim != -1) && (*count > *uplim)) *color = (*walk)->rule->rule.proc.color;
3473 *trackit = ((*walk)->rule->chkflags & CHK_TRACKIT);
3474 *id = (*walk)->rule->rrdidstr;
3475 if (group) *group = (*walk)->rule->groups;
3476 break;
3477
3478 case C_DISK:
3479 result = (*walk)->rule->rule.disk.fsexp->pattern;
3480 *count = (*walk)->rule->rule.disk.dcount;
3481 *lowlim = (*walk)->rule->rule.disk.dmin;
3482 *uplim = (*walk)->rule->rule.disk.dmax;
3483 if ((*lowlim != 0) && (*count < *lowlim)) *color = (*walk)->rule->rule.disk.color;
3484 if ((*uplim != -1) && (*count > *uplim)) *color = (*walk)->rule->rule.disk.color;
3485 if (group) *group = (*walk)->rule->groups;
3486 break;
3487
3488 case C_INODE:
3489 result = (*walk)->rule->rule.inode.fsexp->pattern;
3490 *count = (*walk)->rule->rule.inode.icount;
3491 *lowlim = (*walk)->rule->rule.inode.imin;
3492 *uplim = (*walk)->rule->rule.inode.imax;
3493 *color = COL_GREEN;
3494 if ((*lowlim != 0) && (*count < *lowlim)) *color = (*walk)->rule->rule.inode.color;
3495 if ((*uplim != -1) && (*count > *uplim)) *color = (*walk)->rule->rule.inode.color;
3496 if (group) *group = (*walk)->rule->groups;
3497 break;
3498
3499 case C_PORT:
3500 result = (*walk)->rule->statustext;
3501 if (!result) {
3502 int sz = 1024;
3503 char *p;
3504
3505 if ((*walk)->rule->rule.port.localexp)
3506 sz += strlen((*walk)->rule->rule.port.localexp->pattern) + 10;
3507 if ((*walk)->rule->rule.port.exlocalexp)
3508 sz += strlen((*walk)->rule->rule.port.exlocalexp->pattern) + 10;
3509 if ((*walk)->rule->rule.port.remoteexp)
3510 sz += strlen((*walk)->rule->rule.port.remoteexp->pattern) + 10;
3511 if ((*walk)->rule->rule.port.exremoteexp)
3512 sz += strlen((*walk)->rule->rule.port.exremoteexp->pattern) + 10;
3513 if ((*walk)->rule->rule.port.stateexp)
3514 sz += strlen((*walk)->rule->rule.port.stateexp->pattern) + 10;
3515 if ((*walk)->rule->rule.port.exstateexp)
3516 sz += strlen((*walk)->rule->rule.port.exstateexp->pattern) + 10;
3517
3518 (*walk)->rule->statustext = (char *)malloc(sz + 1);
3519 p = (*walk)->rule->statustext;
3520 if ((*walk)->rule->rule.port.localexp)
3521 p += sprintf(p, "local=%s ", (*walk)->rule->rule.port.localexp->pattern);
3522 if ((*walk)->rule->rule.port.exlocalexp)
3523 p += sprintf(p, "exlocal=%s ", (*walk)->rule->rule.port.exlocalexp->pattern);
3524 if ((*walk)->rule->rule.port.remoteexp)
3525 p += sprintf(p, "remote=%s ", (*walk)->rule->rule.port.remoteexp->pattern);
3526 if ((*walk)->rule->rule.port.exremoteexp)
3527 p += sprintf(p, "exremote=%s ", (*walk)->rule->rule.port.exremoteexp->pattern);
3528 if ((*walk)->rule->rule.port.stateexp)
3529 p += sprintf(p, "state=%s ", (*walk)->rule->rule.port.stateexp->pattern);
3530 if ((*walk)->rule->rule.port.exstateexp)
3531 p += sprintf(p, "exstate=%s ", (*walk)->rule->rule.port.exstateexp->pattern);
3532 *p = '\0';
3533 strcat((*walk)->rule->statustext, ":");
3534
3535 result = (*walk)->rule->statustext;
3536 }
3537 *count = (*walk)->rule->rule.port.pcount;
3538 *lowlim = (*walk)->rule->rule.port.pmin;
3539 *uplim = (*walk)->rule->rule.port.pmax;
3540 if ((*lowlim != 0) && (*count < *lowlim)) *color = (*walk)->rule->rule.port.color;
3541 if ((*uplim != -1) && (*count > *uplim)) *color = (*walk)->rule->rule.port.color;
3542 *trackit = ((*walk)->rule->chkflags & CHK_TRACKIT);
3543 *id = (*walk)->rule->rrdidstr;
3544 if (group) *group = (*walk)->rule->groups;
3545 break;
3546
3547 case C_SVC:
3548 /* Have to clear this each time since it contains current state */
3549 // result = (*walk)->rule->statustext;
3550 if (!result) {
3551 int sz = 1024;
3552 char *p;
3553
3554 /* Current state */
3555 if ((*walk)->rule->rule.svc.svcname)
3556 sz += strlen((*walk)->rule->rule.svc.svcname) + 10;
3557 if ((*walk)->rule->rule.svc.startup)
3558 sz += strlen((*walk)->rule->rule.svc.startup) + 10;
3559 if ((*walk)->rule->rule.svc.state)
3560 sz += strlen((*walk)->rule->rule.svc.state) + 10;
3561 if ((*walk)->rule->rule.svc.startupexp)
3562 sz += strlen((*walk)->rule->rule.svc.startupexp->pattern) + 10;
3563 if ((*walk)->rule->rule.svc.stateexp)
3564 sz += strlen((*walk)->rule->rule.svc.stateexp->pattern) + 10;
3565
3566 if ((*walk)->rule->statustext != NULL) xfree((*walk)->rule->statustext);
3567 (*walk)->rule->statustext = (char *)malloc(sz + 1);
3568
3569 p = (*walk)->rule->statustext;
3570 if ((*walk)->rule->rule.svc.svcname) {
3571 p += sprintf(p, "%s is %s/%s", (*walk)->rule->rule.svc.svcname,
3572 ((*walk)->rule->rule.svc.state ? (*walk)->rule->rule.svc.state : "Unknown"),
3573 ((*walk)->rule->rule.svc.startup ? (*walk)->rule->rule.svc.startup : "Unknown"));
3574 }
3575 else {
3576 /* Did not find the service matching our wanted criteria */
3577 p += sprintf(p, "%s: No matching service", (*walk)->rule->rule.svc.svcexp->pattern);
3578 }
3579 p += sprintf(p, " - want %s/%s",
3580 ((*walk)->rule->rule.svc.stateexp ? (*walk)->rule->rule.svc.stateexp->pattern : "Any"),
3581 ((*walk)->rule->rule.svc.startupexp ? (*walk)->rule->rule.svc.startupexp->pattern : "Any"));
3582 *p = '\0';
3583
3584 result = (*walk)->rule->statustext;
3585
3586 /* We free the extra buffers */
3587 if ((*walk)->rule->rule.svc.svcname)
3588 xfree((*walk)->rule->rule.svc.svcname);
3589 if ((*walk)->rule->rule.svc.state)
3590 xfree((*walk)->rule->rule.svc.state);
3591 if ((*walk)->rule->rule.svc.startup)
3592 xfree((*walk)->rule->rule.svc.startup);
3593 }
3594 *count = (*walk)->rule->rule.svc.scount;
3595 if (*count == 0) *color = (*walk)->rule->rule.svc.color;
3596 if (group) *group = (*walk)->rule->groups;
3597 break;
3598
3599 default: break;
3600 }
3601
3602 *walk = (*walk)->next;
3603
3604 return result;
3605 }
3606
3607 static mon_proc_t *phead = NULL, *ptail = NULL, *pmonwalk = NULL;
3608 static mon_proc_t *dhead = NULL, *dtail = NULL, *dmonwalk = NULL;
3609 static mon_proc_t *ihead = NULL, *itail = NULL, *imonwalk = NULL;
3610 static mon_proc_t *porthead = NULL, *porttail = NULL, *portmonwalk = NULL;
3611 static mon_proc_t *svchead = NULL, *svctail = NULL, *svcmonwalk = NULL;
3612
clear_process_counts(void * hinfo,char * classname)3613 int clear_process_counts(void *hinfo, char *classname)
3614 {
3615 return clear_counts(hinfo, classname, C_PROC, &phead, &ptail, &pmonwalk);
3616 }
3617
clear_disk_counts(void * hinfo,char * classname)3618 int clear_disk_counts(void *hinfo, char *classname)
3619 {
3620 return clear_counts(hinfo, classname, C_DISK, &dhead, &dtail, &dmonwalk);
3621 }
3622
clear_inode_counts(void * hinfo,char * classname)3623 int clear_inode_counts(void *hinfo, char *classname)
3624 {
3625 return clear_counts(hinfo, classname, C_INODE, &ihead, &itail, &imonwalk);
3626 }
3627
clear_port_counts(void * hinfo,char * classname)3628 int clear_port_counts(void *hinfo, char *classname)
3629 {
3630 return clear_counts(hinfo, classname, C_PORT, &porthead, &porttail, &portmonwalk);
3631 }
3632
clear_svc_counts(void * hinfo,char * classname)3633 int clear_svc_counts(void *hinfo, char *classname)
3634 {
3635 return clear_counts(hinfo, classname, C_SVC, &svchead, &svctail, &svcmonwalk);
3636 }
3637
add_process_count(char * pname)3638 void add_process_count(char *pname)
3639 {
3640 add_count(pname, phead);
3641 }
3642
add_disk_count(char * dname)3643 void add_disk_count(char *dname)
3644 {
3645 add_count(dname, dhead);
3646 }
3647
add_inode_count(char * iname)3648 void add_inode_count(char *iname)
3649 {
3650 add_count(iname, ihead);
3651 }
3652
add_port_count(char * localstr,char * foreignstr,char * stname)3653 void add_port_count(char *localstr, char *foreignstr, char *stname)
3654 {
3655 add_count3(localstr, foreignstr, stname, porthead);
3656 }
3657
add_svc_count(char * localstr,char * foreignstr,char * stname)3658 void add_svc_count(char *localstr, char *foreignstr, char *stname)
3659 {
3660 add_count3(localstr, foreignstr, stname, svchead);
3661 }
3662
check_process_count(int * count,int * lowlim,int * uplim,int * color,char ** id,int * trackit,char ** group)3663 char *check_process_count(int *count, int *lowlim, int *uplim, int *color, char **id, int *trackit, char **group)
3664 {
3665 return check_count(count, C_PROC, lowlim, uplim, color, &pmonwalk, id, trackit, group);
3666 }
3667
check_disk_count(int * count,int * lowlim,int * uplim,int * color,char ** group)3668 char *check_disk_count(int *count, int *lowlim, int *uplim, int *color, char **group)
3669 {
3670 return check_count(count, C_DISK, lowlim, uplim, color, &dmonwalk, NULL, NULL, group);
3671 }
3672
check_inode_count(int * count,int * lowlim,int * uplim,int * color,char ** group)3673 char *check_inode_count(int *count, int *lowlim, int *uplim, int *color, char **group)
3674 {
3675 return check_count(count, C_INODE, lowlim, uplim, color, &imonwalk, NULL, NULL, group);
3676 }
3677
check_port_count(int * count,int * lowlim,int * uplim,int * color,char ** id,int * trackit,char ** group)3678 char *check_port_count(int *count, int *lowlim, int *uplim, int *color, char **id, int *trackit, char **group)
3679 {
3680 return check_count(count, C_PORT, lowlim, uplim, color, &portmonwalk, id, trackit, group);
3681 }
3682
check_svc_count(int * count,int * color,char ** group)3683 char *check_svc_count(int *count, int *color, char **group)
3684 {
3685 return check_count(count, C_SVC, NULL, NULL, color, &svcmonwalk, NULL, NULL, group);
3686 }
3687