Beispiel #1
0
hostinfo *
rpc_manager::lookup_host (const net_address &r)
{
  str key = strbuf () << r.hostname << ":" << r.port << "\n";
  hostinfo *h = hosts[key];
  if (!h) {
    if (hosts.size () > max_host_cache) {
      hostinfo *o = hostlru.first;
      hostlru.remove (o);
      hosts.remove (o);
      remove_host (o);
      delete (o);
    }
    h = New hostinfo (r);
    h->key = key;
    hostlru.insert_tail (h);
    hosts.insert (h);
  } else {
    // record recent access
    hostlru.remove (h);
    hostlru.insert_tail (h);
  }
  assert (h);
  return h;
}
Beispiel #2
0
char *check_downtime(char *hostname, char *testname)
{
	namelist_t *hinfo = hostinfo(hostname);
	char *dtag;

	if (hinfo == NULL) return NULL;

	dtag = bbh_item(hinfo, BBH_DOWNTIME);
	if (dtag && *dtag) {
		static char *downtag = NULL;
		static unsigned char *cause = NULL;
		static int causelen = 0;
		char *s1, *s2, *s3, *s4, *s5, *p;
		char timetxt[30];

		if (downtag) xfree(downtag);
		if (cause) xfree(cause);

		p = downtag = strdup(dtag);
		do {
			/* Its either DAYS:START:END or SERVICE:DAYS:START:END:CAUSE */

			s1 = p; p += strcspn(p, ":"); if (*p != '\0') { *p = '\0'; p++; }
			s2 = p; p += strcspn(p, ":"); if (*p != '\0') { *p = '\0'; p++; }
			s3 = p; p += strcspn(p, ":;,"); 
			if ((*p == ',') || (*p == ';') || (*p == '\0')) { 
				if (*p != '\0') { *p = '\0'; p++; }
				snprintf(timetxt, sizeof(timetxt), "%s:%s:%s", s1, s2, s3);
				cause = strdup("Planned downtime");
				s1 = "*";
			}
			else if (*p == ':') {
				*p = '\0'; p++; 
				s4 = p; p += strcspn(p, ":"); if (*p != '\0') { *p = '\0'; p++; }
				s5 = p; p += strcspn(p, ",;"); if (*p != '\0') { *p = '\0'; p++; }
				snprintf(timetxt, sizeof(timetxt), "%s:%s:%s", s2, s3, s4);
				getescapestring(s5, &cause, &causelen);
			}

			if (within_sla(timetxt, 0)) {
				char *onesvc, *buf;

				if (strcmp(s1, "*") == 0) return cause;

				onesvc = strtok_r(s1, ",", &buf);
				while (onesvc) {
					if (strcmp(onesvc, testname) == 0) return cause;
					onesvc = strtok_r(NULL, ",", &buf);
				}
			}
		} while (*p);
	}

	return NULL;
}
Beispiel #3
0
void loadhostdata(char *hostname, char **ip, char **displayname)
{
	namelist_t *hinfo = NULL;

	load_hostnames(xgetenv("BBHOSTS"), NULL, get_fqdn());

	if ((hinfo = hostinfo(hostname)) == NULL) {
		errormsg("No such host");
		exit(1);
	}

	*ip = bbh_item(hinfo, BBH_IP);
	*displayname = bbh_item(hinfo, BBH_DISPLAYNAME);
	if (!(*displayname)) *displayname = hostname;
}
Beispiel #4
0
int unwantedcolumn(char *hostname, char *testname)
{
	void *hinfo;
	char *nc, *tok;
	int result = 0;

	hinfo = hostinfo(hostname);
	if (!hinfo) return 1;

	nc = bbh_item(hinfo, BBH_NOCOLUMNS);
	if (!nc) return 0;

	nc = strdup(nc);
	tok = strtok(nc, ",");
	while (tok && (result == 0)) {
		if (strcmp(tok, testname) == 0) result = 1;
		tok = strtok(NULL, ",");
	}

	return result;
}
Beispiel #5
0
int main(int argc, char *argv[])
{
	char *msg;
	int seq;
	int argi;
	int alertcolors, alertinterval;
	char *configfn = NULL;
	char *checkfn = NULL;
	int checkpointinterval = 900;
	char acklogfn[PATH_MAX];
	FILE *acklogfd = NULL;
	char notiflogfn[PATH_MAX];
	FILE *notiflogfd = NULL;
	char *tracefn = NULL;
	struct sigaction sa;
	int configchanged;
	time_t lastxmit = 0;

	MEMDEFINE(acklogfn);
	MEMDEFINE(notiflogfn);

	libxymon_init(argv[0]);

	/* Dont save the error buffer */
	save_errbuf = 0;

	/* Load alert config */
	alertcolors = colorset(xgetenv("ALERTCOLORS"), ((1 << COL_GREEN) | (1 << COL_BLUE)));
	alertinterval = 60*atoi(xgetenv("ALERTREPEAT"));

	/* Create our loookup-trees */
	hostnames = xtreeNew(strcasecmp);
	testnames = xtreeNew(strcasecmp);
	locations = xtreeNew(strcasecmp);

	for (argi=1; (argi < argc); argi++) {
		if (argnmatch(argv[argi], "--config=")) {
			configfn = strdup(strchr(argv[argi], '=')+1);
		}
		else if (argnmatch(argv[argi], "--checkpoint-file=")) {
			checkfn = strdup(strchr(argv[argi], '=')+1);
		}
		else if (argnmatch(argv[argi], "--checkpoint-interval=")) {
			char *p = strchr(argv[argi], '=') + 1;
			checkpointinterval = atoi(p);
		}
		else if (argnmatch(argv[argi], "--dump-config")) {
			load_alertconfig(configfn, alertcolors, alertinterval);
			dump_alertconfig(1);
			return 0;
		}
		else if (argnmatch(argv[argi], "--cfid")) {
			include_configid = 1;
		}
		else if (argnmatch(argv[argi], "--test")) {
			char *testhost = NULL, *testservice = NULL, *testpage = NULL, 
			     *testcolor = "red", *testgroups = NULL;
			void *hinfo;
			int testdur = 0;
			FILE *logfd = NULL;
			activealerts_t *awalk = NULL;
			int paramno = 0;

			argi++; if (argi < argc) testhost = argv[argi];
			argi++; if (argi < argc) testservice = argv[argi];
			argi++; 
			while (argi < argc) {
				if (strncasecmp(argv[argi], "--duration=", 11) == 0) {
					testdur = durationvalue(strchr(argv[argi], '=')+1);
				}
				else if (strncasecmp(argv[argi], "--color=", 8) == 0) {
					testcolor = strchr(argv[argi], '=')+1;
				}
				else if (strncasecmp(argv[argi], "--group=", 8) == 0) {
					testgroups = strchr(argv[argi], '=')+1;
				}
				else if (strncasecmp(argv[argi], "--time=", 7) == 0) {
					fakestarttime = (time_t)atoi(strchr(argv[argi], '=')+1);
				}
				else {
					paramno++;
					if (paramno == 1) testdur = atoi(argv[argi]);
					else if (paramno == 2) testcolor = argv[argi];
					else if (paramno == 3) fakestarttime = (time_t) atoi(argv[argi]);
				}

				argi++;
			}

			if ((testhost == NULL) || (testservice == NULL)) {
				printf("Usage: xymond_alert --test HOST SERVICE [options]\n");
				printf("Possible options:\n\t[--duration=MINUTES]\n\t[--color=COLOR]\n\t[--group=GROUPNAME]\n\t[--time=TIMESPEC]\n");

				return 1;
			}

			load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn());
			hinfo = hostinfo(testhost);
			if (hinfo) {
				testpage = strdup(xmh_item(hinfo, XMH_ALLPAGEPATHS));
			}
			else {
				errprintf("Host not found in hosts.cfg - assuming it is on the top page\n");
				testpage = "";
			}

			awalk = (activealerts_t *)calloc(1, sizeof(activealerts_t));
			awalk->hostname = find_name(hostnames, testhost);
			awalk->testname = find_name(testnames, testservice);
			awalk->location = find_name(locations, testpage);
			awalk->ip = strdup("127.0.0.1");
			awalk->color = awalk->maxcolor = parse_color(testcolor);
			awalk->pagemessage = "Test of the alert configuration";
			awalk->eventstart = getcurrenttime(NULL) - testdur*60;
			awalk->groups = (testgroups ? strdup(testgroups) : NULL);
			awalk->state = A_PAGING;
			awalk->cookie = 12345;
			awalk->next = NULL;

			logfd = fopen("/dev/null", "w");
			starttrace(NULL);
			testonly = 1;

			load_alertconfig(configfn, alertcolors, alertinterval);
			load_holidays(0);
			send_alert(awalk, logfd);
			return 0;
		}
		else if (argnmatch(argv[argi], "--trace=")) {
			tracefn = strdup(strchr(argv[argi], '=')+1);
			starttrace(tracefn);
		}
		else if (net_worker_option(argv[argi])) {
			/* Handled in the subroutine */
		}
		else if (standardoption(argv[argi])) {
			if (showhelp) return 0;
		}
		else {
			errprintf("Unknown option '%s'\n", argv[argi]);
		}
	}

	/* Do the network stuff if needed */
	net_worker_run(ST_ALERT, LOC_SINGLESERVER, NULL);

	if (checkfn) {
		load_checkpoint(checkfn);
		nextcheckpoint = gettimer() + checkpointinterval;
		dbgprintf("Next checkpoint at %d, interval %d\n", (int) nextcheckpoint, checkpointinterval);
	}

	setup_signalhandler("xymond_alert");
	/* Need to handle these ourselves, so we can shutdown and save state-info */
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sig_handler;
	sigaction(SIGPIPE, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGUSR1, &sa, NULL);
	sigaction(SIGHUP,  &sa, NULL);

	if (xgetenv("XYMONSERVERLOGS")) {
		sprintf(acklogfn, "%s/acknowledge.log", xgetenv("XYMONSERVERLOGS"));
		acklogfd = fopen(acklogfn, "a");
		sprintf(notiflogfn, "%s/notifications.log", xgetenv("XYMONSERVERLOGS"));
		notiflogfd = fopen(notiflogfn, "a");
	}

	/*
	 * The general idea here is that this loop handles receiving of alert-
	 * and ack-messages from the master daemon, and maintains a list of 
	 * host+test combinations that may have alerts going out.
	 *
	 * This module does not deal with any specific alert-configuration, 
	 * it just picks up the alert messages, maintains the list of 
	 * known tests that are in some sort of critical condition, and
	 * periodically pushes alerts to the do_alert.c module for handling.
	 *
	 * The only modification of alerts that happen here is the handling
	 * of when the next alert is due. It calls into the next_alert() 
	 * routine to learn when an alert should be repeated, and also 
	 * deals with Acknowledgments that stop alerts from going out for
	 * a period of time.
	 */
	while (running) {
		char *eoln, *restofmsg;
		char *metadata[20];
		char *p;
		int metacount;
		char *hostname = NULL, *testname = NULL;
		struct timespec timeout;
		time_t now, nowtimer;
		int anytogo;
		activealerts_t *awalk;
		int childstat;

		nowtimer = gettimer();
		if (checkfn && (nowtimer > nextcheckpoint)) {
			dbgprintf("Saving checkpoint\n");
			nextcheckpoint = nowtimer + checkpointinterval;
			save_checkpoint(checkfn);

			if (acklogfd) acklogfd = freopen(acklogfn, "a", acklogfd);
			if (notiflogfd) notiflogfd = freopen(notiflogfn, "a", notiflogfd);
		}

		timeout.tv_sec = 60; timeout.tv_nsec = 0;
		msg = get_xymond_message(C_PAGE, "xymond_alert", &seq, &timeout);
		if (msg == NULL) {
			running = 0;
			continue;
		}

		/* See what time it is - must happen AFTER the timeout */
		now = getcurrenttime(NULL);

		/* Split the message in the first line (with meta-data), and the rest */
 		eoln = strchr(msg, '\n');
		if (eoln) {
			*eoln = '\0';
			restofmsg = eoln+1;
		}
		else {
			restofmsg = "";
		}

		/* 
		 * Now parse the meta-data into elements.
		 * We use our own "gettok()" routine which works
		 * like strtok(), but can handle empty elements.
		 */
		metacount = 0; 
		memset(&metadata, 0, sizeof(metadata));
		p = gettok(msg, "|");
		while (p && (metacount < 19)) {
			metadata[metacount] = p;
			metacount++;
			p = gettok(NULL, "|");
		}
		metadata[metacount] = NULL;

		if (metacount > 3) hostname = metadata[3];
		if (metacount > 4) testname = metadata[4];

		if ((metacount > 10) && (strncmp(metadata[0], "@@page", 6) == 0)) {
			/* @@page|timestamp|sender|hostname|testname|hostip|expiretime|color|prevcolor|changetime|location|cookie|osname|classname|grouplist|modifiers */

			int newcolor, newalertstatus, oldalertstatus;

			dbgprintf("Got page message from %s:%s\n", hostname, testname);
			traceprintf("@@page %s:%s:%s=%s\n", hostname, testname, metadata[10], metadata[7]);

			awalk = find_active(hostname, testname);
			if (awalk == NULL) {
				char *hwalk = find_name(hostnames, hostname);
				char *twalk = find_name(testnames, testname);
				char *pwalk = find_name(locations, metadata[10]);

				awalk = (activealerts_t *)calloc(1, sizeof(activealerts_t));
				awalk->hostname = hwalk;
				awalk->testname = twalk;
				awalk->location = pwalk;
				awalk->cookie = -1;
				awalk->state = A_DEAD;
				/*
				 * Use changetime here, if we restart the alert module then
				 * this gets the duration values more right than using "now".
				 * Also, define this only when a new alert arrives - we should
				 * NOT clear this when a status goes yellow->red, or if it
				 * flaps between yellow and red.
				 */
				awalk->eventstart = atoi(metadata[9]);
				add_active(awalk->hostname, awalk);
				traceprintf("New record\n");
			}

			newcolor = parse_color(metadata[7]);
			oldalertstatus = ((alertcolors & (1 << awalk->color)) != 0);
			newalertstatus = ((alertcolors & (1 << newcolor)) != 0);

			traceprintf("state %d->%d\n", oldalertstatus, newalertstatus);

			if (newalertstatus) {
				/* It's in an alert state. */
				awalk->color = newcolor;
				awalk->state = A_PAGING;

				if (newcolor > awalk->maxcolor) {
					if (awalk->maxcolor != 0) {
						/*
						 * Severity has increased (yellow -> red).
						 * Clear the repeat-interval, and set maxcolor to
						 * the new color. If it drops to yellow again,
						 * maxcolor stays at red, so a test that flaps
						 * between yellow and red will only alert on red
						 * the first time, and then follow the repeat
						 * interval.
						 */
						dbgprintf("Severity increased, cleared repeat interval: %s/%s %s->%s\n",
							awalk->hostname, awalk->testname,
							colorname(awalk->maxcolor), colorname(newcolor));
						clear_interval(awalk);
					}

					awalk->maxcolor = newcolor;
				}
			}
			else {
				/* 
				 * Send one "recovered" message out now, then go to A_DEAD.
				 * Dont update the color here - we want recoveries to go out 
				 * only if the alert color triggered an alert
				 */
				awalk->state = (newcolor == COL_BLUE) ? A_DISABLED : A_RECOVERED;
			}

			if (oldalertstatus != newalertstatus) {
				dbgprintf("Alert status changed from %d to %d\n", oldalertstatus, newalertstatus);
				clear_interval(awalk);
			}

			if (awalk->ip) xfree(awalk->ip);
			awalk->ip = strdup(metadata[5]);
			awalk->cookie = atoi(metadata[11]);
			if (awalk->osname) xfree(awalk->osname);
			awalk->osname    = (metadata[12] ? strdup(metadata[12]) : NULL);
			if (awalk->classname) xfree(awalk->classname);
			awalk->classname = (metadata[13] ? strdup(metadata[13]) : NULL);
			if (awalk->groups) xfree(awalk->groups);
			awalk->groups    = (metadata[14] ? strdup(metadata[14]) : NULL);
			if (awalk->pagemessage) xfree(awalk->pagemessage);
			if (metadata[15]) {
				/* Modifiers are more interesting than the message itself */
				awalk->pagemessage = (char *)malloc(strlen(awalk->hostname) + strlen(awalk->testname) + strlen(colorname(awalk->color)) + strlen(metadata[15]) + strlen(restofmsg) + 10);
				sprintf(awalk->pagemessage, "%s:%s %s\n%s\n%s",
					awalk->hostname, awalk->testname, colorname(awalk->color), metadata[15], restofmsg);
			}
			else {
				awalk->pagemessage = strdup(restofmsg);
			}
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@ack", 5) == 0)) {
 			/* @@ack|timestamp|sender|hostname|testname|hostip|expiretime */

			/*
			 * An ack is handled simply by setting the next
			 * alert-time to when the ack expires.
			 */
			time_t nextalert = atoi(metadata[6]);

			dbgprintf("Got ack message from %s:%s\n", hostname, testname);
			traceprintf("@@ack: %s:%s now=%d, ackeduntil %d\n",
				     hostname, testname, (int)now, (int)nextalert);

			awalk = find_active(hostname, testname);

			if (acklogfd) {
				int cookie = (awalk ? awalk->cookie : -1);
				int color  = (awalk ? awalk->color : 0);

				fprintf(acklogfd, "%d\t%d\t%d\t%d\t%s\t%s.%s\t%s\t%s\n",
					(int)now, cookie, 
					(int)((nextalert - now) / 60), cookie,
					"np_filename_not_used", 
					hostname, testname, 
					colorname(color),
					nlencode(restofmsg));
				fflush(acklogfd);
			}

			if (awalk && (awalk->state == A_PAGING)) {
				traceprintf("Record updated\n");
				awalk->state = A_ACKED;
				awalk->nextalerttime = nextalert;
				if (awalk->ackmessage) xfree(awalk->ackmessage);
				awalk->ackmessage = strdup(restofmsg);
			}
			else {
				traceprintf("No record\n");
			}
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@notify", 5) == 0)) {
			/* @@notify|timestamp|sender|hostname|testname|pagepath */

			char *hwalk = find_name(hostnames, hostname);
			char *twalk = find_name(testnames, testname);
			char *pwalk = find_name(locations, (metadata[5] ? metadata[5] : ""));

			awalk = (activealerts_t *)calloc(1, sizeof(activealerts_t));
			awalk->hostname = hwalk;
			awalk->testname = twalk;
			awalk->location = pwalk;
			awalk->cookie = -1;
			awalk->pagemessage = strdup(restofmsg);
			awalk->eventstart = getcurrenttime(NULL);
			awalk->state = A_NOTIFY;
			add_active(awalk->hostname, awalk);
		}
		else if ((metacount > 3) && 
			 ((strncmp(metadata[0], "@@drophost", 10) == 0) || (strncmp(metadata[0], "@@dropstate", 11) == 0))) {
			/* @@drophost|timestamp|sender|hostname */
			/* @@dropstate|timestamp|sender|hostname */
			xtreePos_t handle;

			handle = xtreeFind(hostnames, hostname);
			if (handle != xtreeEnd(hostnames)) {
				alertanchor_t *anchor = (alertanchor_t *)xtreeData(hostnames, handle);
				for (awalk = anchor->head; (awalk); awalk = awalk->next) awalk->state = A_DEAD;
			}
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) {
			/* @@droptest|timestamp|sender|hostname|testname */

			awalk = find_active(hostname, testname);
			if (awalk) awalk->state = A_DEAD;
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) {
			/* @@renamehost|timestamp|sender|hostname|newhostname */

			/* 
			 * We handle rename's simply by dropping the alert. If there is still an
			 * active alert for the host, it will have to be dealt with when the next
			 * status update arrives.
			 */
			xtreePos_t handle;

			handle = xtreeFind(hostnames, hostname);
			if (handle != xtreeEnd(hostnames)) {
				alertanchor_t *anchor = (alertanchor_t *)xtreeData(hostnames, handle);
				for (awalk = anchor->head; (awalk); awalk = awalk->next) awalk->state = A_DEAD;
			}
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) {
			/* @@renametest|timestamp|sender|hostname|oldtestname|newtestname */

			/* 
			 * We handle rename's simply by dropping the alert. If there is still an
			 * active alert for the host, it will have to be dealt with when the next
			 * status update arrives.
			 */
			awalk = find_active(hostname, testname);
			if (awalk) awalk->state = A_DEAD;
		}
		else if (strncmp(metadata[0], "@@shutdown", 10) == 0) {
			running = 0;
			errprintf("Got a shutdown message\n");
			continue;
		}
		else if (strncmp(metadata[0], "@@logrotate", 11) == 0) {
			char *fn = xgetenv("XYMONCHANNEL_LOGFILENAME");
			if (fn && strlen(fn)) {
				reopen_file(fn, "a", stdout);
				reopen_file(fn, "a", stderr);

				if (tracefn) {
					stoptrace();
					starttrace(tracefn);
				}
			}
			continue;
		}
		else if (strncmp(metadata[0], "@@reload", 8) == 0) {
			/* Nothing ... right now */
		}
		else if (strncmp(metadata[0], "@@idle", 6) == 0) {
			/* Timeout */
		}

		/*
		 * When a burst of alerts happen, we get lots of alert messages
		 * coming in quickly. So lets handle them in bunches and only 
		 * do the full alert handling once every 10 secs - that lets us
		 * combine a bunch of alerts into one transmission process.
		 */
		if (nowtimer < (lastxmit+10)) continue;
		lastxmit = nowtimer;

		/* 
		 * Loop through the activealerts list and see if anything is pending.
		 * This is an optimization, we could just as well just fork off the
		 * notification child and let it handle all of it. But there is no
		 * reason to fork a child process unless it is going to do something.
		 */
		configchanged = load_alertconfig(configfn, alertcolors, alertinterval);
		configchanged += load_holidays(0);
		anytogo = 0;
		for (awalk = alistBegin(); (awalk); awalk = alistNext()) {
			int anymatch = 0;

			switch (awalk->state) {
			  case A_NORECIP:
				if (!configchanged) break;

				/* The configuration has changed - switch NORECIP -> PAGING */
				awalk->state = A_PAGING;
				clear_interval(awalk);
				/* Fall through */

			  case A_PAGING:
				if (have_recipient(awalk, &anymatch)) {
					if (awalk->nextalerttime <= now) anytogo++;
				}
				else {
					if (!anymatch) {
						awalk->state = A_NORECIP;
						cleanup_alert(awalk);
					}
				}
				break;

			  case A_ACKED:
				if (awalk->nextalerttime <= now) {
					/* An ack has expired, so drop the ack message and switch to A_PAGING */
					anytogo++;
					if (awalk->ackmessage) xfree(awalk->ackmessage);
					awalk->state = A_PAGING;
				}
				break;

			  case A_RECOVERED:
			  case A_DISABLED:
			  case A_NOTIFY:
				anytogo++;
				break;

			  case A_DEAD:
				break;
			}
		}
		dbgprintf("%d alerts to go\n", anytogo);

		if (anytogo) {
			pid_t childpid;

			childpid = fork();
			if (childpid == 0) {
				/* The child */
				start_alerts();
				for (awalk = alistBegin(); (awalk); awalk = alistNext()) {
					switch (awalk->state) {
					  case A_PAGING:
						if (awalk->nextalerttime <= now) {
							send_alert(awalk, notiflogfd);
						}
						break;

					  case A_ACKED:
						/* Cannot be A_ACKED unless the ack is still valid, so no alert. */
						break;

					  case A_RECOVERED:
					  case A_DISABLED:
					  case A_NOTIFY:
						send_alert(awalk, notiflogfd);
						break;

					  case A_NORECIP:
					  case A_DEAD:
						break;
					}
				}
				finish_alerts();

				/* Child does not continue */
				exit(0);
			}
			else if (childpid < 0) {
				errprintf("Fork failed, cannot send alerts: %s\n", strerror(errno));
			}
		}

		/* Update the state flag and the next-alert timestamp */
		for (awalk = alistBegin(); (awalk); awalk = alistNext()) {
			switch (awalk->state) {
			  case A_PAGING:
				if (awalk->nextalerttime <= now) awalk->nextalerttime = next_alert(awalk);
				break;

			  case A_NORECIP:
				break;

			  case A_ACKED:
				/* Still cannot get here except if ack is still valid */
				break;

			  case A_RECOVERED:
			  case A_DISABLED:
			  case A_NOTIFY:
				awalk->state = A_DEAD;
				/* Fall through */

			  case A_DEAD:
				cleanup_alert(awalk); 
				break;
			}
		}

		clean_all_active();

		/* Pickup any finished child processes to avoid zombies */
		while (wait3(&childstat, WNOHANG, NULL) > 0) ;
	}

	if (checkfn) save_checkpoint(checkfn);
	if (acklogfd) fclose(acklogfd);
	if (notiflogfd) fclose(notiflogfd);
	stoptrace();

	MEMUNDEFINE(notiflogfn);
	MEMUNDEFINE(acklogfn);

	if (termsig >= 0) {
		errprintf("Terminated by signal %d\n", termsig);
	}

	return 0;
}
Beispiel #6
0
void do_notifylog(FILE *output, 
		  int maxcount, int maxminutes, char *fromtime, char *totime, 
		  char *pageregex, char *expageregex,
		  char *hostregex, char *exhostregex,
		  char *testregex, char *extestregex,
		  char *rcptregex, char *exrcptregex)
{
	FILE *notifylog;
	char notifylogfilename[PATH_MAX];
	time_t firstevent = 0;
	time_t lastevent = getcurrenttime(NULL);
	notification_t *head, *walk;
	struct stat st;
	char l[MAX_LINE_LEN];
	char title[200];

	/* For the PCRE matching */
	const char *errmsg = NULL;
	int errofs = 0;
	pcre *pageregexp = NULL;
	pcre *expageregexp = NULL;
	pcre *hostregexp = NULL;
	pcre *exhostregexp = NULL;
	pcre *testregexp = NULL;
	pcre *extestregexp = NULL;
	pcre *rcptregexp = NULL;
	pcre *exrcptregexp = NULL;

	if (maxminutes && (fromtime || totime)) {
		fprintf(output, "<B>Only one time interval type is allowed!</B>");
		return;
	}

	if (fromtime) {
		firstevent = convert_time(fromtime);
		if(firstevent < 0) {
			fprintf(output,"<B>Invalid 'from' time: %s</B>", htmlquoted(fromtime));
			return;
		}
	}
	else if (maxminutes) {
		firstevent = getcurrenttime(NULL) - maxminutes*60;
	}
	else {
		firstevent = getcurrenttime(NULL) - 86400;
	}

	if (totime) {
		lastevent = convert_time(totime);
		if (lastevent < 0) {
			fprintf(output,"<B>Invalid 'to' time: %s</B>", htmlquoted(totime));
			return;
		}
		if (lastevent < firstevent) {
			fprintf(output,"<B>'to' time must be after 'from' time.</B>");
			return;
		}
	}

	if (!maxcount) maxcount = 100;

	if (pageregex && *pageregex) pageregexp = pcre_compile(pageregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (expageregex && *expageregex) expageregexp = pcre_compile(expageregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (hostregex && *hostregex) hostregexp = pcre_compile(hostregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (exhostregex && *exhostregex) exhostregexp = pcre_compile(exhostregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (testregex && *testregex) testregexp = pcre_compile(testregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (extestregex && *extestregex) extestregexp = pcre_compile(extestregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (rcptregex && *rcptregex) rcptregexp = pcre_compile(rcptregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (exrcptregex && *exrcptregex) exrcptregexp = pcre_compile(exrcptregex, PCRE_CASELESS, &errmsg, &errofs, NULL);

	sprintf(notifylogfilename, "%s/notifications.log", xgetenv("XYMONSERVERLOGS"));
	notifylog = fopen(notifylogfilename, "r");

	if (notifylog && (stat(notifylogfilename, &st) == 0)) {
		time_t curtime;
		int done = 0;

		/* Find a spot in the notification log file close to where the firstevent time is */
		fseeko(notifylog, 0, SEEK_END);
		do {
			/* Go back maxcount*80 bytes - one entry is ~80 bytes */
			if (ftello(notifylog) > maxcount*80) {
				unsigned int uicurtime;
				fseeko(notifylog, -maxcount*80, SEEK_CUR); 
				if (fgets(l, sizeof(l), notifylog) && /* Skip to start of line */
				    fgets(l, sizeof(l), notifylog)) {
					/* Sun Jan  7 10:29:08 2007 myhost.disk (130.225.226.90) [email protected] 1168162147 100 */
					sscanf(l, "%*s %*s %*u %*u:%*u:%*u %*u %*s %*s %*s %u %*d", &uicurtime);
					curtime = uicurtime;
					done = (curtime < firstevent);
				}
				else { 
					fprintf(output, "Error reading logfile %s: %s\n", notifylogfilename, strerror(errno));
					return;
				}
			}
			else {
				rewind(notifylog);
				done = 1;
			}
		} while (!done);
	}
	
	head = NULL;

	while (notifylog && (fgets(l, sizeof(l), notifylog))) {

		unsigned int etim;
		time_t eventtime;
		char hostsvc[MAX_LINE_LEN];
		char recipient[MAX_LINE_LEN];
		char *hostname, *svcname, *p;
		int itemsfound, pagematch, hostmatch, testmatch, rcptmatch;
		notification_t *newrec;
		void *eventhost;
		struct htnames_t *eventcolumn;
		int ovector[30];

		itemsfound = sscanf(l, "%*s %*s %*u %*u:%*u:%*u %*u %s %*s %s %u %*d", hostsvc, recipient, &etim);
		eventtime = etim;
		if (itemsfound != 3) continue;
		if (eventtime < firstevent) continue;
		if (eventtime > lastevent) break;

		hostname = hostsvc; svcname = strrchr(hostsvc, '.'); if (svcname) { *svcname = '\0'; svcname++; } else svcname = "";
		eventhost = hostinfo(hostname);
		if (!eventhost) continue; /* Dont report hosts that no longer exist */
		eventcolumn = getname(svcname, 1);

		p = strchr(recipient, '['); if (p) *p = '\0';

		if (pageregexp) {
			char *pagename;

			pagename = xmh_item_multi(eventhost, XMH_PAGEPATH);
			pagematch = 0;
			while (!pagematch && pagename) {
			pagematch = (pcre_exec(pageregexp, NULL, pagename, strlen(pagename), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
				pagename = xmh_item_multi(NULL, XMH_PAGEPATH);
			}
		}
		else
			pagematch = 1;
		if (!pagematch) continue;

		if (expageregexp) {
			char *pagename;

			pagename = xmh_item_multi(eventhost, XMH_PAGEPATH);
			pagematch = 0;
			while (!pagematch && pagename) {
			pagematch = (pcre_exec(expageregexp, NULL, pagename, strlen(pagename), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
				pagename = xmh_item_multi(NULL, XMH_PAGEPATH);
			}
		}
		else
			pagematch = 0;
		if (pagematch) continue;

		if (hostregexp)
			hostmatch = (pcre_exec(hostregexp, NULL, hostname, strlen(hostname), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			hostmatch = 1;
		if (!hostmatch) continue;

		if (exhostregexp)
			hostmatch = (pcre_exec(exhostregexp, NULL, hostname, strlen(hostname), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			hostmatch = 0;
		if (hostmatch) continue;

		if (testregexp)
			testmatch = (pcre_exec(testregexp, NULL, svcname, strlen(svcname), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			testmatch = 1;
		if (!testmatch) continue;

		if (extestregexp)
			testmatch = (pcre_exec(extestregexp, NULL, svcname, strlen(svcname), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			testmatch = 0;
		if (testmatch) continue;

		if (rcptregexp)
			rcptmatch = (pcre_exec(rcptregexp, NULL, recipient, strlen(recipient), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			rcptmatch = 1;
		if (!rcptmatch) continue;

		if (exrcptregexp)
			rcptmatch = (pcre_exec(exrcptregexp, NULL, recipient, strlen(recipient), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			rcptmatch = 0;
		if (rcptmatch) continue;

		newrec = (notification_t *) malloc(sizeof(notification_t));
		newrec->host       = eventhost;
		newrec->service    = eventcolumn;
		newrec->eventtime  = eventtime;
		newrec->recipient  = strdup(recipient);
		newrec->next       = head;
		head = newrec;
	}

	if (head) {
		char *bgcolors[2] = { "#000000", "#000066" };
		int  bgcolor = 0;
		int  count;
		struct notification_t *lasttoshow = head;

		count=0;
		walk=head; 
		do {
			count++;
			lasttoshow = walk;
			walk = walk->next;
		} while (walk && (count<maxcount));

		if (maxminutes)  { 
			sprintf(title, "%d notifications in the past %u minutes", 
				count, (unsigned int)((getcurrenttime(NULL) - lasttoshow->eventtime) / 60));
		}
		else {
			sprintf(title, "%d notifications sent.", count);
		}

		fprintf(output, "<BR><BR>\n");
		fprintf(output, "<TABLE SUMMARY=\"Notification log\" BORDER=0>\n");
		fprintf(output, "<TR BGCOLOR=\"#333333\">\n");
		fprintf(output, "<TD ALIGN=CENTER COLSPAN=4><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", htmlquoted(title));
		fprintf(output, "<TR BGCOLOR=\"#333333\"><TH>Time</TH><TH>Host</TH><TH>Service</TH><TH>Recipient</TH></TR>\n");

		for (walk=head; (walk != lasttoshow->next); walk=walk->next) {
			char *hostname = xmh_item(walk->host, XMH_HOSTNAME);

			fprintf(output, "<TR BGCOLOR=%s>\n", bgcolors[bgcolor]);
			bgcolor = ((bgcolor + 1) % 2);

			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", ctime(&walk->eventtime));

			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", hostname);
			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->service->name);
			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->recipient);
		}

		fprintf(output, "</TABLE>\n");

		/* Clean up */
		walk = head;
		do {
			struct notification_t *tmp = walk;

			walk = walk->next;
			xfree(tmp->recipient);
			xfree(tmp);
		} while (walk);
	}
	else {
		/* No notifications during the past maxminutes */
		if (notifylog)
			sprintf(title, "No notifications sent in the last %d minutes", maxminutes);
		else
			strcpy(title, "No notifications logged");

		fprintf(output, "<CENTER><BR>\n");
		fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title);
		fprintf(output, "<TR BGCOLOR=\"#333333\">\n");
		fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD>\n", htmlquoted(title));
		fprintf(output, "</TR>\n");
		fprintf(output, "</TABLE>\n");
		fprintf(output, "</CENTER>\n");
	}

	if (notifylog) fclose(notifylog);

	if (pageregexp)   pcre_free(pageregexp);
	if (expageregexp) pcre_free(expageregexp);
	if (hostregexp)   pcre_free(hostregexp);
	if (exhostregexp) pcre_free(exhostregexp);
	if (testregexp)   pcre_free(testregexp);
	if (extestregexp) pcre_free(extestregexp);
	if (rcptregexp)   pcre_free(rcptregexp);
	if (exrcptregexp) pcre_free(exrcptregexp);
}
Beispiel #7
0
xymongen_page_t *load_layout(char *pgset)
{
	char	pagetag[100], subpagetag[100], subparenttag[100], 
		vpagetag[100], vsubpagetag[100], vsubparenttag[100], 
		grouptag[100], summarytag[100], titletag[100], hosttag[100];
	char 	*name, *link, *onlycols, *exceptcols;
	char 	hostname[MAX_LINE_LEN];
	xymongen_page_t 	*toppage, *curpage, *cursubpage, *cursubparent;
	group_t *curgroup;
	host_t	*curhost;
	char	*curtitle;
	int	ip1, ip2, ip3, ip4;
	char	*p;
	int	fqdn = get_fqdn();
	char	*cfgdata, *inbol, *ineol, insavchar = '\0';

	if (loadhostsfromxymond) {
		if (load_hostnames("@", NULL, fqdn) != 0) {
			errprintf("Cannot load host configuration from xymond\n");
			return NULL;
		}
	}
	else {
		if (load_hostnames(xgetenv("HOSTSCFG"), "dispinclude", fqdn) != 0) {
			errprintf("Cannot load host configuration from %s\n", xgetenv("HOSTSCFG"));
			return NULL;
		}
	}

	if (first_host() == NULL) {
		errprintf("Empty configuration from %s\n", (loadhostsfromxymond ? "xymond" : xgetenv("HOSTSCFG")));
		return NULL;
	}

	dbgprintf("load_layout(pgset=%s)\n", textornull(pgset));

	/*
	 * load_hostnames() picks up the hostname definitions, but not the page
	 * layout. So we will scan the file again, this time doing the layout.
	 */

	if (pgset == NULL) pgset = "";
	sprintf(pagetag, "%spage", pgset);
	sprintf(subpagetag, "%ssubpage", pgset);
	sprintf(subparenttag, "%ssubparent", pgset);
	sprintf(vpagetag, "v%spage", pgset);
	sprintf(vsubpagetag, "v%ssubpage", pgset);
	sprintf(vsubparenttag, "v%ssubparent", pgset);
	sprintf(grouptag, "%sgroup", pgset);
	sprintf(summarytag, "%ssummary", pgset);
	sprintf(titletag, "%stitle", pgset);
	sprintf(hosttag, "%s:", pgset); for (p=hosttag; (*p); p++) *p = toupper((int)*p);

	toppage = init_page("", "", 0);
	addtopagelist(toppage);
	curpage = NULL;
	cursubpage = NULL;
	curgroup = NULL;
	curhost = NULL;
	cursubparent = NULL;
	curtitle = NULL;

	inbol = cfgdata = hostscfg_content();
	while (inbol && *inbol) {
		inbol += strspn(inbol, " \t");
		ineol = strchr(inbol, '\n');
		if (ineol) {
			while ((ineol > inbol) && (isspace(*ineol) || (*ineol == '\n'))) ineol--;
			if (*ineol != '\n') ineol++;

			insavchar = *ineol;
			*ineol = '\0';
		}

		dbgprintf("load_layout: -- got line '%s'\n", inbol);

		if ((strncmp(inbol, pagetag, strlen(pagetag)) == 0) || (strncmp(inbol, vpagetag, strlen(vpagetag)) == 0)) {
			getnamelink(inbol, &name, &link);
			if (curpage == NULL) {
				/* First page - hook it on toppage as a subpage from there */
				curpage = toppage->subpages = init_page(name, link, (strncmp(inbol, vpagetag, strlen(vpagetag)) == 0));
			}
			else {
				curpage = curpage->next = init_page(name, link, (strncmp(inbol, vpagetag, strlen(vpagetag)) == 0));
			}

			curpage->parent = toppage;
			if (curtitle) { 
				curpage->pretitle = curtitle; 
				curtitle = NULL; 
			}
			cursubpage = NULL;
			cursubparent = NULL;
			curgroup = NULL;
			curhost = NULL;
			addtopagelist(curpage);
		}
		else if ( (strncmp(inbol, subpagetag, strlen(subpagetag)) == 0) || (strncmp(inbol, vsubpagetag, strlen(vsubpagetag)) == 0) ) {
			if (curpage == NULL) {
				errprintf("'subpage' ignored, no preceding 'page' tag : %s\n", inbol);
				goto nextline;
			}

			getnamelink(inbol, &name, &link);
			if (cursubpage == NULL) {
				cursubpage = curpage->subpages = init_page(name, link, (strncmp(inbol, vsubpagetag, strlen(vsubpagetag)) == 0));
			}
			else {
				cursubpage = cursubpage->next = init_page(name, link, (strncmp(inbol, vsubpagetag, strlen(vsubpagetag)) == 0));
			}
			cursubpage->parent = curpage;
			if (curtitle) { 
				cursubpage->pretitle = curtitle; 
				curtitle = NULL;
			}
			cursubparent = NULL;
			curgroup = NULL;
			curhost = NULL;
			addtopagelist(cursubpage);
		}
		else if ( (strncmp(inbol, subparenttag, strlen(subparenttag)) == 0) || (strncmp(inbol, vsubparenttag, strlen(vsubparenttag)) == 0) ) {
			xymongen_page_t *parentpage, *walk;

			getparentnamelink(inbol, toppage, &parentpage, &name, &link);
			if (parentpage == NULL) {
				errprintf("'subparent' ignored, unknown parent page: %s\n", inbol);
				goto nextline;
			}

			cursubparent = init_page(name, link, (strncmp(inbol, vsubparenttag, strlen(vsubparenttag)) == 0));
			if (parentpage->subpages == NULL) {
				parentpage->subpages = cursubparent;
			} 
			else {
				for (walk = parentpage->subpages; (walk->next); (walk = walk->next)) ;
				walk->next = cursubparent;
			}
			if (curtitle) { 
				cursubparent->pretitle = curtitle; 
				curtitle = NULL;
			}
			cursubparent->parent = parentpage;
			curgroup = NULL;
			curhost = NULL;
			addtopagelist(cursubparent);
		}
		else if (strncmp(inbol, grouptag, strlen(grouptag)) == 0) {
			int sorthosts = (strstr(inbol, "group-sorted") != NULL);

			getgrouptitle(inbol, pgset, &link, &onlycols, &exceptcols);
			if (curgroup == NULL) {
				curgroup = init_group(link, onlycols, exceptcols, sorthosts);
				if (cursubparent != NULL) {
					cursubparent->groups = curgroup;
				}
				else if (cursubpage != NULL) {
					/* We're in a subpage */
					cursubpage->groups = curgroup;
				}
				else if (curpage != NULL) {
					/* We're on a main page */
					curpage->groups = curgroup;
				}
				else {
					/* We're on the top page */
					toppage->groups = curgroup;
				}
			}
			else {
				curgroup->next = init_group(link, onlycols, exceptcols, sorthosts);
				curgroup = curgroup->next;
			}
			if (curtitle) { curgroup->pretitle = curtitle; curtitle = NULL; }
			curhost = NULL;
		}
		else if (sscanf(inbol, "%3d.%3d.%3d.%3d %s", &ip1, &ip2, &ip3, &ip4, hostname) == 5) {
			void *xymonhost = NULL;
			int dialup, nonongreen, crittime = 1;
			double warnpct = reportwarnlevel;
			int warnstops = reportwarnstops;
			char *displayname, *clientalias, *comment, *description;
			char *alertlist, *onwaplist, *reporttime;
			char *nopropyellowlist, *nopropredlist, *noproppurplelist, *nopropacklist;
			char *targetpagelist[MAX_TARGETPAGES_PER_HOST];
			int targetpagecount;
			char *hval;

			/* Check for ".default." hosts - they are ignored. */
			if (*hostname == '.') goto nextline;

			if (!fqdn) {
				/* Strip any domain from the hostname */
				char *p = strchr(hostname, '.');
				if (p) *p = '\0';
			}

			/* Get the info */
			xymonhost = hostinfo(hostname);
			if (xymonhost == NULL) {
				errprintf("Confused - hostname '%s' cannot be found. Ignored\n", hostname);
				goto nextline;
			}

			/* Check for no-display hosts - they are ignored. */
			/* But only when we're building the default pageset */
			if ((strlen(pgset) == 0) && (xmh_item(xymonhost, XMH_FLAG_NODISP) != NULL)) goto nextline;

			for (targetpagecount=0; (targetpagecount < MAX_TARGETPAGES_PER_HOST); targetpagecount++) 
				targetpagelist[targetpagecount] = NULL;
			targetpagecount = 0;

			dialup = (xmh_item(xymonhost, XMH_FLAG_DIALUP) != NULL);
			nonongreen = (xmh_item(xymonhost, XMH_FLAG_NONONGREEN) != NULL);

			alertlist = xmh_item(xymonhost, XMH_NK);
			hval = xmh_item(xymonhost, XMH_NKTIME); if (hval) crittime = within_sla(xmh_item(xymonhost, XMH_HOLIDAYS), hval, 0);

			onwaplist = xmh_item(xymonhost, XMH_WML);
			nopropyellowlist = xmh_item(xymonhost, XMH_NOPROPYELLOW);
			if (nopropyellowlist == NULL) nopropyellowlist = xmh_item(xymonhost, XMH_NOPROP);
			nopropredlist = xmh_item(xymonhost, XMH_NOPROPRED);
			noproppurplelist = xmh_item(xymonhost, XMH_NOPROPPURPLE);
			nopropacklist = xmh_item(xymonhost, XMH_NOPROPACK);
			displayname = xmh_item(xymonhost, XMH_DISPLAYNAME);
			comment = xmh_item(xymonhost, XMH_COMMENT);
			description = xmh_item(xymonhost, XMH_DESCRIPTION);
			hval = xmh_item(xymonhost, XMH_WARNPCT); if (hval) warnpct = atof(hval);
			hval = xmh_item(xymonhost, XMH_WARNSTOPS); if (hval) warnstops = atof(hval);
			reporttime = xmh_item(xymonhost, XMH_REPORTTIME);

			clientalias = xmh_item(xymonhost, XMH_CLIENTALIAS);
			if (xymonhost && (strcmp(xmh_item(xymonhost, XMH_HOSTNAME), clientalias) == 0)) clientalias = NULL;

			if (xymonhost && (strlen(pgset) > 0)) {
				/* Walk the clone-list and pick up the target pages for this host */
				void *cwalk = xymonhost;
				do {
					hval = xmh_item_walk(cwalk);
					while (hval) {
						if (strncasecmp(hval, hosttag, strlen(hosttag)) == 0)
							targetpagelist[targetpagecount++] = strdup(hval+strlen(hosttag));
						hval = xmh_item_walk(NULL);
					}

					cwalk = next_host(cwalk, 1);
				} while (cwalk && 
					 (strcmp(xmh_item(cwalk, XMH_HOSTNAME), xmh_item(xymonhost, XMH_HOSTNAME)) == 0) &&
					 (targetpagecount < MAX_TARGETPAGES_PER_HOST) );

				/*
				 * HACK: Check if the pageset tag is present at all in the host
				 * entry. If it isn't, then drop this incarnation of the host.
				 *
				 * Without this, the following hosts.cfg file will have the
				 * www.hswn.dk host listed twice on the alternate pageset:
				 *
				 * adminpage nyc NYC
				 *
				 * 127.0.0.1   localhost      # bbd http://localhost/ CLIENT:osiris
				 * 172.16.10.2 www.xymon.com  # http://www.xymon.com/ ADMIN:nyc ssh noinfo
				 *
				 * page superdome Superdome
				 * 172.16.10.2 www.xymon.com # noconn
				 *
				 */
				if (strstr(inbol, hosttag) == NULL) targetpagecount = 0;
			}

			if (strlen(pgset) == 0) {
				/*
				 * Default pageset generated. Put the host into
				 * whatever group or page is current.
				 */
				if (curhost == NULL) {
					curhost = init_host(hostname, 0, displayname, clientalias,
							    comment, description,
							    ip1, ip2, ip3, ip4, dialup, 
							    warnpct, warnstops, reporttime,
							    alertlist, crittime, onwaplist,
							    nopropyellowlist, nopropredlist, noproppurplelist, nopropacklist);
					if (curgroup != NULL) {
						curgroup->hosts = curhost;
					}
					else if (cursubparent != NULL) {
						cursubparent->hosts = curhost;
					}
					else if (cursubpage != NULL) {
						cursubpage->hosts = curhost;
					}
					else if (curpage != NULL) {
						curpage->hosts = curhost;
					}
					else {
						toppage->hosts = curhost;
					}
				}
				else {
					curhost = curhost->next = init_host(hostname, 0, displayname, clientalias,
									    comment, description,
									    ip1, ip2, ip3, ip4, dialup,
									    warnpct, warnstops, reporttime,
									    alertlist, crittime, onwaplist,
									    nopropyellowlist,nopropredlist, 
									    noproppurplelist, nopropacklist);
				}
				curhost->parent = (cursubparent ? cursubparent : (cursubpage ? cursubpage : curpage));
				if (curtitle) { curhost->pretitle = curtitle; curtitle = NULL; }
				curhost->nonongreen = nonongreen;
			}
			else if (targetpagecount) {

				int pgnum;

				for (pgnum=0; (pgnum < targetpagecount); pgnum++) {
					char *targetpagename = targetpagelist[pgnum];

					char savechar;
					int wantedgroup = 0;
					xymonpagelist_t *targetpage = NULL;

					/* Put the host into the page specified by the PGSET: tag */
					p = strchr(targetpagename, ',');
					if (p) {
						savechar = *p;
						*p = '\0';
						wantedgroup = atoi(p+1);
					}
					else {
						savechar = '\0';
						p = targetpagename + strlen(targetpagename);
					}

					/* Find the page */
					if (strcmp(targetpagename, "*") == 0) {
						*targetpagename = '\0';
					}
					for (targetpage = pagelisthead; (targetpage && (strcmp(targetpagename, targetpage->pageentry->name) != 0)); targetpage = targetpage->next) ;

					*p = savechar;
					if (targetpage == NULL) {
						errprintf("Warning: Cannot find any target page named '%s' in set '%s' - dropping host '%s'\n", 
							targetpagename, pgset, hostname);
					}
					else {
						host_t *newhost = init_host(hostname, 0, displayname, clientalias,
									    comment, description,
									    ip1, ip2, ip3, ip4, dialup,
									    warnpct, warnstops, reporttime,
									    alertlist, crittime, onwaplist,
									    nopropyellowlist,nopropredlist, 
									    noproppurplelist, nopropacklist);

						if (wantedgroup > 0) {
							group_t *gwalk;
							host_t  *hwalk;
							int i;

							for (gwalk = targetpage->pageentry->groups, i=1; (gwalk && (i < wantedgroup)); i++,gwalk=gwalk->next) ;
							if (gwalk) {
								if (gwalk->hosts == NULL)
									gwalk->hosts = newhost;
								else {
									for (hwalk = gwalk->hosts; (hwalk->next); hwalk = hwalk->next) ;
									hwalk->next = newhost;
								}
							}
							else {
								errprintf("Warning: Cannot find group %d for host %s - dropping host\n",
									wantedgroup, hostname);
							}
						}
						else {
							/* Just put in on the page's hostlist */
							host_t *walk;
	
							if (targetpage->pageentry->hosts == NULL)
								targetpage->pageentry->hosts = newhost;
							else {
								for (walk = targetpage->pageentry->hosts; (walk->next); walk = walk->next) ;
								walk->next = newhost;
							}
						}

						newhost->parent = targetpage->pageentry;
						if (curtitle) newhost->pretitle = curtitle;
					}

					curtitle = NULL;
				}
			}
		}
		else if (strncmp(inbol, summarytag, strlen(summarytag)) == 0) {
			/* summary row.column      IP-ADDRESS-OF-PARENT    http://xymon.com/ */
			char sumname[MAX_LINE_LEN];
			char receiver[MAX_LINE_LEN];
			char url[MAX_LINE_LEN];
			summary_t *newsum;

			if (sscanf(inbol, "summary %s %s %s", sumname, receiver, url) == 3) {
				newsum = init_summary(sumname, receiver, url);
				newsum->next = sumhead;
				sumhead = newsum;
			}
		}
		else if (strncmp(inbol, titletag, strlen(titletag)) == 0) {
			/* Save the title for the next entry */
			curtitle = strdup(skipwhitespace(skipword(inbol)));
		}

nextline:
		if (ineol) {
			*ineol = insavchar;
			if (*ineol != '\n') ineol = strchr(ineol, '\n');

			inbol = (ineol ? ineol+1 : NULL);
		}
		else
			inbol = NULL;
	}

	xfree(cfgdata);
	return toppage;
}
Beispiel #8
0
int main(int argc, char *argv[])
{
	int argi;
	struct sigaction sa;
	namelist_t *hostwalk;
	time_t nexttimeout;

	for (argi=1; (argi < argc); argi++) {
		if (argnmatch(argv[argi], "--server=")) {
			char *p = strchr(argv[argi], '=');
			serverip = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--interval=")) {
			char *p = strchr(argv[argi], '=');
			pollinterval = atoi(p+1);
		}
		else if (argnmatch(argv[argi], "--log-interval=")) {
			char *p = strchr(argv[argi], '=');
			errorloginterval = atoi(p+1);
		}
		else if (argnmatch(argv[argi], "--id=")) {
			char *p = strchr(argv[argi], '=');
			serverid = atoi(p+1);
		}
		else if (strcmp(argv[argi], "--debug") == 0) {
			debug = 1;
		}
	}

	setup_signalhandler("hobbitfetch");
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sigmisc_handler;
	sigaction(SIGHUP, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGUSR1, &sa, NULL);	/* SIGUSR1 triggers logging of active requests */

	clients = rbtNew(name_compare);
	nexttimeout = time(NULL) + 60;

	{
		/* Seed the random number generator */
		struct timeval tv;
		struct timezone tz;

		gettimeofday(&tv, &tz);
		srandom(tv.tv_usec);
	}

	do {
		RbtIterator handle;
		conn_t *connwalk, *cprev;
		fd_set fdread, fdwrite;
		int n, maxfd;
		struct timeval tmo;
		time_t now;
		
		now = time(NULL);
		if (now > reloadtime) {
			/* Time to reload the bb-hosts file */
			reloadtime = now + 600;

			load_hostnames(xgetenv("BBHOSTS"), NULL, get_fqdn());
			for (hostwalk = first_host(); (hostwalk); hostwalk = hostwalk->next) {
				char *hname;
				clients_t *newclient;

				if (!bbh_item(hostwalk, BBH_FLAG_PULLDATA)) continue;

				hname = bbh_item(hostwalk, BBH_HOSTNAME);
				handle = rbtFind(clients, hname);
				if (handle == rbtEnd(clients)) {
					newclient = (clients_t *)calloc(1, sizeof(clients_t));
					newclient->hostname = strdup(hname);
					rbtInsert(clients, newclient->hostname, newclient);
					whentoqueue = now;
				}
			}
		}

		now = time(NULL);
		if (now > nexttimeout) {
			/* Check for connections that have timed out */
			nexttimeout = now + 60;

			for (connwalk = chead; (connwalk); connwalk = connwalk->next) {
				if ((connwalk->tstamp + 60) < now) {
					if (debug || (connwalk->client->nexterrortxt < now)) {
						errprintf("Timeout while talking to %s (req %lu): Aborting session\n",
							  addrstring(&connwalk->caddr), connwalk->seq);
						connwalk->client->nexterrortxt = now + errorloginterval;
					}
					flag_cleanup(connwalk);
				}
			}
		}

		if (needcleanup) {
			/* Remove any finished requests */
			needcleanup = 0;
			connwalk = chead; cprev = NULL;
			dbgprintf("Doing cleanup\n");

			while (connwalk) {
				conn_t *zombie;

				if ((connwalk->action == C_READING) || (connwalk->action == C_WRITING)) {
					/* Active connection - skip to the next conn_t record */
					cprev = connwalk;
					connwalk = connwalk->next;
					continue;
				}

				if (connwalk->action == C_CLEANUP) {
					if (connwalk->ctype == C_CLIENT) {
						/* 
						 * Finished getting data from a client, 
						 * flag idle and set next poll time.
						 */
						connwalk->client->busy = 0;
						set_polltime(connwalk->client);
					}
					else if (connwalk->ctype == C_SERVER) {
						/* Nothing needed for server cleanups */
					}
				}

				/* Unlink the request from the list of active connections */
				zombie = connwalk;
				if (cprev == NULL) {
					chead = zombie->next;
					connwalk = chead;
					cprev = NULL;
				}
				else {
					cprev->next = zombie->next;
					connwalk = zombie->next;
				}

				/* Purge the zombie */
				dbgprintf("Request completed: req %lu, peer %s, action was %d, type was %d\n", 
					zombie->seq, addrstring(&zombie->caddr), 
					zombie->action, zombie->ctype);
				close(zombie->sockfd);
				freestrbuffer(zombie->msgbuf);
				xfree(zombie);
			}

			/* Set the tail pointer correctly */
			ctail = chead;
			if (ctail) { while (ctail->next) ctail = ctail->next; }
		}

		if (dumpsessions) {
			/* Set by SIGUSR1 - dump the list of active requests */
			dumpsessions = 0;
			for (connwalk = chead; (connwalk); connwalk = connwalk->next) {
				char *ctypestr, *actionstr;
				char timestr[30];

				switch (connwalk->ctype) {
				  case C_CLIENT: ctypestr = "client"; break;
				  case C_SERVER: ctypestr = "server"; break;
				}

				switch (connwalk->action) {
				  case C_READING: actionstr = "reading"; break;
				  case C_WRITING: actionstr = "writing"; break;
				  case C_CLEANUP: actionstr = "cleanup"; break;
				}

				strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S",
					 localtime(&connwalk->tstamp));

				errprintf("Request %lu: state %s/%s, peer %s, started %s (%lu secs ago)\n",
					  connwalk->seq, ctypestr, actionstr, addrstring(&connwalk->caddr),
					  timestr, (now - connwalk->tstamp));
			}
		}

		now = time(NULL);
		if (now >= whentoqueue) {
			/* Scan host-tree for clients we need to contact */
			for (handle = rbtBegin(clients); (handle != rbtEnd(clients)); handle = rbtNext(clients, handle)) {
				clients_t *clientwalk;
				char msgline[100];
				strbuffer_t *request;
				char *pullstr, *ip;
				int port;

				clientwalk = (clients_t *)gettreeitem(clients, handle);
				if (clientwalk->busy) continue;
				if (clientwalk->nextpoll > now) continue;

				/* Deleted hosts stay in our tree - but should disappear from the known hosts */
				hostwalk = hostinfo(clientwalk->hostname); if (!hostwalk) continue;
				pullstr = bbh_item(hostwalk, BBH_FLAG_PULLDATA); if (!pullstr) continue;

				ip = strchr(pullstr, '=');
				port = atoi(xgetenv("BBPORT"));

				if (!ip) {
					ip = strdup(bbh_item(hostwalk, BBH_IP));
				}
				else {
					/* There is an explicit IP setting in the pulldata tag */
					char *p;

					ip++; /* Skip the '=' */
					ip = strdup(ip);
					p = strchr(ip, ':');
					if (p) { *p = '\0'; port = atoi(p+1); }

					if (*ip == '\0') {
						/* No IP given, just a port number */
						xfree(ip);
						ip = strdup(bbh_item(hostwalk, BBH_IP));
					}
				}

				if (strcmp(ip, "0.0.0.0") == 0) {
					struct hostent *hent;

					xfree(ip); ip = NULL;
					hent = gethostbyname(clientwalk->hostname);
					if (hent) {
						struct in_addr addr;

						memcpy(&addr, *(hent->h_addr_list), sizeof(addr));
						ip = strdup(inet_ntoa(addr));
					}
				}

				if (!ip) continue;

				/* 
				 * Build the "pullclient" request, which includes the latest
				 * clientdata config we got from the server. Keep the clientdata
				 * here - we send "pullclient" requests more often that we actually
				 * contact the server, but we should provide the config data always.
				 */
				request = newstrbuffer(0);
				sprintf(msgline, "pullclient %d\n", serverid);
				addtobuffer(request, msgline);
				if (clientwalk->clientdata) addtobuffer(request, clientwalk->clientdata);

				/* Put the request on the connection queue */
				addrequest(C_CLIENT, ip, port, request, clientwalk);
				clientwalk->busy = 1;

				xfree(ip);
			}
		}

		/* Handle request queue */
		FD_ZERO(&fdread);
		FD_ZERO(&fdwrite);
		maxfd = -1;
		for (connwalk = chead; (connwalk); connwalk = connwalk->next) {
			switch (connwalk->action) {
			  case C_READING: 
				FD_SET(connwalk->sockfd, &fdread);
				if (connwalk->sockfd > maxfd) maxfd = connwalk->sockfd;
				break;

			  case C_WRITING: 
				FD_SET(connwalk->sockfd, &fdwrite);
				if (connwalk->sockfd > maxfd) maxfd = connwalk->sockfd;
				break;

			  case C_CLEANUP:
				break;
			}
		}

		/* Do select with a 1 second timeout */
		tmo.tv_sec = 1;
		tmo.tv_usec = 0;
		n = select(maxfd+1, &fdread, &fdwrite, NULL, &tmo);

		if (n == -1) {
			if (errno == EINTR) continue;	/* Interrupted, e.g. a SIGHUP */

			/* This is a "cannot-happen" failure. Bail out */
			errprintf("select failure: %s\n", strerror(errno));
			return 0;
		}

		if (n == 0) continue;	/* Timeout */

		for (connwalk = chead; (connwalk); connwalk = connwalk->next) {
			switch (connwalk->action) {
			  case C_READING: 
				if (FD_ISSET(connwalk->sockfd, &fdread)) grabdata(connwalk);
				break;

			  case C_WRITING: 
				if (FD_ISSET(connwalk->sockfd, &fdwrite)) senddata(connwalk);
				break;

			  case C_CLEANUP:
				break;
			}
		}

	} while (running);

	return 0;
}
Beispiel #9
0
int do_ifstat_rrd(char *hostname, char *testname, char *classname, char *pagepaths, char *msg, time_t tstamp)
{
	static int pcres_compiled = 0;
	static pcre **ifstat_linux_pcres = NULL;
	static pcre **ifstat_freebsd_pcres = NULL;
	static pcre **ifstat_freebsdV8_pcres = NULL;
	static pcre **ifstat_openbsd_pcres = NULL;
	static pcre **ifstat_netbsd_pcres = NULL;
	static pcre **ifstat_darwin_pcres = NULL;
	static pcre **ifstat_solaris_pcres = NULL;
	static pcre **ifstat_aix_pcres = NULL;
	static pcre **ifstat_hpux_pcres = NULL;
	static pcre **ifstat_sco_sv_pcres = NULL;
	static pcre **ifstat_bbwin_pcres = NULL;

	enum ostype_t ostype;
	char *datapart = msg;
	char *bol, *eoln, *ifname, *rxstr, *txstr, *dummy;
	int dmatch;

	void *xmh;
	pcre *ifname_filter_pcre = NULL;

	xmh = hostinfo(hostname);
	if (xmh) {
		char *ifname_filter_expr = xmh_item(xmh, XMH_INTERFACES);
		if (ifname_filter_expr && *ifname_filter_expr) 
			ifname_filter_pcre = compileregex(ifname_filter_expr);
	}

	if (pcres_compiled == 0) {
		pcres_compiled = 1;
		ifstat_linux_pcres = compile_exprs("LINUX", ifstat_linux_exprs, 
						 (sizeof(ifstat_linux_exprs) / sizeof(ifstat_linux_exprs[0])));
		ifstat_freebsd_pcres = compile_exprs("FREEBSD", ifstat_freebsd_exprs, 
						 (sizeof(ifstat_freebsd_exprs) / sizeof(ifstat_freebsd_exprs[0])));
		ifstat_freebsdV8_pcres = compile_exprs("FREEBSD", ifstat_freebsdV8_exprs, 
						 (sizeof(ifstat_freebsdV8_exprs) / sizeof(ifstat_freebsdV8_exprs[0])));
		ifstat_openbsd_pcres = compile_exprs("OPENBSD", ifstat_openbsd_exprs, 
						 (sizeof(ifstat_openbsd_exprs) / sizeof(ifstat_openbsd_exprs[0])));
		ifstat_netbsd_pcres = compile_exprs("NETBSD", ifstat_netbsd_exprs, 
						 (sizeof(ifstat_netbsd_exprs) / sizeof(ifstat_netbsd_exprs[0])));
		ifstat_darwin_pcres = compile_exprs("DARWIN", ifstat_darwin_exprs, 
						 (sizeof(ifstat_darwin_exprs) / sizeof(ifstat_darwin_exprs[0])));
		ifstat_solaris_pcres = compile_exprs("SOLARIS", ifstat_solaris_exprs, 
						 (sizeof(ifstat_solaris_exprs) / sizeof(ifstat_solaris_exprs[0])));
		ifstat_aix_pcres = compile_exprs("AIX", ifstat_aix_exprs, 
						 (sizeof(ifstat_aix_exprs) / sizeof(ifstat_aix_exprs[0])));
		ifstat_hpux_pcres = compile_exprs("HPUX", ifstat_hpux_exprs, 
						 (sizeof(ifstat_hpux_exprs) / sizeof(ifstat_hpux_exprs[0])));
		ifstat_sco_sv_pcres = compile_exprs("SCO_SV", ifstat_sco_sv_exprs, 
						 (sizeof(ifstat_sco_sv_exprs) / sizeof(ifstat_sco_sv_exprs[0])));
		ifstat_bbwin_pcres = compile_exprs("BBWIN", ifstat_bbwin_exprs, 
						 (sizeof(ifstat_bbwin_exprs) / sizeof(ifstat_bbwin_exprs[0])));
	}


	if (ifstat_tpl == NULL) ifstat_tpl = setup_template(ifstat_params);

	if ((strncmp(msg, "status", 6) == 0) || (strncmp(msg, "data", 4) == 0)) {
		/* Skip the first line of full status- and data-messages. */
		datapart = strchr(msg, '\n');
		if (datapart) datapart++; else datapart = msg;
	}

	ostype = get_ostype(datapart);
	datapart = strchr(datapart, '\n');
	if (datapart) {
		datapart++; 
	}
	else {
		errprintf("Too few lines in ifstat report from %s\n", hostname);
		return -1;
	}

	dmatch = 0;
	ifname = rxstr = txstr = dummy = NULL;

	bol = datapart;
	while (bol) {
		eoln = strchr(bol, '\n'); if (eoln) *eoln = '\0';

		switch (ostype) {
		  case OS_LINUX22:
		  case OS_LINUX:
		  case OS_RHEL3:
		  case OS_ZVM:
		  case OS_ZVSE:
		  case OS_ZOS:
			if (pickdata(bol, ifstat_linux_pcres[0], 1, &ifname)) {
				/*
				 * Linux' netif aliases mess up things. 
				 * Clear everything when we see an interface name.
				 * But we dont want to track the "lo" interface.
				 */

				/* Strip off the last character if it is a colon (:) */
				if (ifname[strlen(ifname)-1] == ':') ifname[strlen(ifname)-1] = '\0';

				if (strcmp(ifname, "lo") == 0) {
					xfree(ifname); ifname = NULL;
				}
				else {
					dmatch = 1;
					if (rxstr) { xfree(rxstr); rxstr = NULL; }
					if (txstr) { xfree(txstr); txstr = NULL; }
				}
			}
			else if (pickdata(bol, ifstat_linux_pcres[1], 1, &rxstr, &txstr)) dmatch |= 6;
			else if (pickdata(bol, ifstat_linux_pcres[2], 1, &rxstr)) dmatch |= 2;
			else if (pickdata(bol, ifstat_linux_pcres[3], 1, &txstr)) dmatch |= 4;
			break;

		  case OS_FREEBSD:
			/*
			 * FreeBSD 8 added an "Idrop" counter in the middle of the data.
			 * See if we match this expression, and if not then fall back to
			 * the old regex without that field.
			 */
			if (pickdata(bol, ifstat_freebsdV8_pcres[0], 0, &ifname, &rxstr, &txstr)) dmatch = 7;
			else if (pickdata(bol, ifstat_freebsd_pcres[0], 0, &ifname, &rxstr, &txstr)) dmatch = 7;
			break;

		  case OS_OPENBSD:
			if (pickdata(bol, ifstat_openbsd_pcres[0], 0, &ifname, &rxstr, &txstr)) dmatch = 7;
			break;

		  case OS_NETBSD:
			if (pickdata(bol, ifstat_netbsd_pcres[0], 0, &ifname, &rxstr, &txstr)) dmatch = 7;
			break;

		  case OS_SOLARIS: 
			if (pickdata(bol, ifstat_solaris_pcres[0], 0, &ifname, &txstr)) dmatch |= 1;
			else if (pickdata(bol, ifstat_solaris_pcres[1], 0, &dummy, &rxstr)) dmatch |= 6;

			if (ifname && dummy && (strcmp(ifname, dummy) != 0)) {
				/* They must match, drop the data */
				errprintf("Host %s has weird ifstat data - device name mismatch %s:%s\n", hostname, ifname, dummy);
				xfree(ifname); xfree(txstr); xfree(rxstr); xfree(dummy);
				dmatch = 0;
			}

			/* Ignore "mac" and "wrsmd" entries - these are for sub-devices for multiple nic's aggregated into one */
			/* See http://www.xymon.com/archive/2009/06/msg00204.html for more info */
			if (ifname && ((strcmp(ifname, "mac") == 0) || (strcmp(ifname, "wrsmd") == 0)) ) {
				xfree(ifname); xfree(txstr);
				dmatch = 0;
			}
			if (dummy && ((strcmp(dummy, "mac") == 0) || (strcmp(dummy, "wrsmd") == 0)) ) {
				xfree(dummy); xfree(rxstr);
				dmatch = 0;
			}
			break;

		  case OS_AIX: 
			if (pickdata(bol, ifstat_aix_pcres[0], 1, &ifname)) {
				/* Interface names comes first, so any rx/tx data is discarded */
				dmatch |= 1;
				if (rxstr) { xfree(rxstr); rxstr = NULL; }
				if (txstr) { xfree(txstr); txstr = NULL; }
			}
			else if (pickdata(bol, ifstat_aix_pcres[1], 1, &txstr, &rxstr)) dmatch |= 6;
			break;

		  case OS_HPUX: 
			if (pickdata(bol, ifstat_hpux_pcres[0], 1, &ifname)) {
				/* Interface names comes first, so any rx/tx data is discarded */
				dmatch |= 1;
				if (rxstr) { xfree(rxstr); rxstr = NULL; }
				if (txstr) { xfree(txstr); txstr = NULL; }
			}
			else if (pickdata(bol, ifstat_hpux_pcres[1], 1, &rxstr)) dmatch |= 2;
			else if (pickdata(bol, ifstat_hpux_pcres[2], 1, &txstr)) dmatch |= 4;
			break;

		  case OS_DARWIN:
			if (pickdata(bol, ifstat_darwin_pcres[0], 0, &ifname, &rxstr, &txstr)) dmatch = 7;
			break;
			
 		  case OS_SCO_SV:
		        if (pickdata(bol, ifstat_sco_sv_pcres[0], 0, &ifname, &rxstr, &txstr)) dmatch = 7;
			break;
			
		  case OS_WIN32_BBWIN:
			if (pickdata(bol, ifstat_bbwin_pcres[0], 0, &ifname, &rxstr, &txstr)) dmatch = 7;
			break;

		  default:
			break;
		}

		if ((dmatch == 7) && ifname && rxstr && txstr) {
			if (!ifname_filter_pcre || matchregex(ifname, ifname_filter_pcre)) {
				setupfn2("%s.%s.rrd", "ifstat", ifname);
				snprintf(rrdvalues, sizeof(rrdvalues), "%d:%s:%s", (int)tstamp, txstr, rxstr);
				create_and_update_rrd(hostname, testname, classname, pagepaths, ifstat_params, ifstat_tpl);
			}

			xfree(ifname); xfree(rxstr); xfree(txstr);
			if (dummy) xfree(dummy);
			ifname = rxstr = txstr = dummy = NULL;
			dmatch = 0;
		}

		if (eoln) {
			*eoln = '\n';
			bol = eoln+1;
			if (*bol == '\0') bol = NULL;
		}
		else {
			bol = NULL;
		}
	}

	if (ifname_filter_pcre) freeregex(ifname_filter_pcre);

	if (ifname) xfree(ifname);
	if (rxstr) xfree(rxstr);
	if (txstr) xfree(txstr);
	if (dummy) xfree(dummy);

	return 0;
}
Beispiel #10
0
int main(int argc, char *argv[])
{
    int argi, hosti, testi;
    char *pagepattern = NULL, *hostpattern = NULL;
    char *envarea = NULL, *cookie = NULL, *nexthost;
    char *hobbitcmd, *procscmd, *svcscmd;
    int alertcolors, alertinterval;
    char configfn[PATH_MAX];
    char *respbuf = NULL, *procsbuf = NULL, *svcsbuf = NULL;
    hostlist_t *hwalk;
    htnames_t *twalk;
    hostlist_t **allhosts = NULL;
    htnames_t **alltests = NULL;
    int hostcount = 0, maxtests = 0;
    time_t now = getcurrenttime(NULL);
    sendreturn_t *sres;

    for (argi=1; (argi < argc); argi++) {
        if (argnmatch(argv[argi], "--env=")) {
            char *p = strchr(argv[argi], '=');
            loadenv(p+1, envarea);
        }
        else if (argnmatch(argv[argi], "--area=")) {
            char *p = strchr(argv[argi], '=');
            envarea = strdup(p+1);
        }
        else if (strcmp(argv[argi], "--debug") == 0) {
            debug = 1;
        }
        else if (argnmatch(argv[argi], "--delimiter=")) {
            char *p = strchr(argv[argi], '=');
            coldelim = strdup(p+1);
        }
        else if (strcmp(argv[argi], "--critical") == 0) {
            nkonly = 1;
        }
        else if (strcmp(argv[argi], "--old-nk-config") == 0) {
            newnkconfig = 0;
        }
    }

    redirect_cgilog("hobbit-confreport");

    load_hostnames(xgetenv("BBHOSTS"), NULL, get_fqdn());
    load_nkconfig(NULL);

    /* Setup the filter we use for the report */
    cookie = get_cookie("pagepath");
    if (cookie && *cookie) pagepattern = strdup(cookie);
    cookie = get_cookie("host");
    if (cookie && *cookie) hostpattern = strdup(cookie);

    /* Fetch the list of host+test statuses we currently know about */
    if (pagepattern) {
        hobbitcmd = (char *)malloc(2*strlen(pagepattern) + 1024);
        procscmd = (char *)malloc(2*strlen(pagepattern) + 1024);
        svcscmd = (char *)malloc(2*strlen(pagepattern) + 1024);

        sprintf(hobbitcmd, "hobbitdboard page=^%s$|^%s/.+ fields=hostname,testname",
                pagepattern, pagepattern);
        sprintf(procscmd,  "hobbitdboard page=^%s$|^%s/.+ test=procs fields=hostname,msg",
                pagepattern, pagepattern);
        sprintf(svcscmd,   "hobbitdboard page=^%s$|^%s/.+ test=svcs fields=hostname,msg",
                pagepattern, pagepattern);
    }
    else if (hostpattern) {
        hobbitcmd = (char *)malloc(strlen(hostpattern) + 1024);
        procscmd = (char *)malloc(strlen(hostpattern) + 1024);
        svcscmd = (char *)malloc(strlen(hostpattern) + 1024);

        sprintf(hobbitcmd, "hobbitdboard host=^%s$ fields=hostname,testname", hostpattern);
        sprintf(procscmd,  "hobbitdboard host=^%s$ test=procs fields=hostname,msg", hostpattern);
        sprintf(svcscmd,   "hobbitdboard host=^%s$ test=svcs fields=hostname,msg", hostpattern);
    }
    else {
        hobbitcmd = (char *)malloc(1024);
        procscmd = (char *)malloc(1024);
        svcscmd = (char *)malloc(1024);

        sprintf(hobbitcmd, "hobbitdboard fields=hostname,testname");
        sprintf(procscmd,  "hobbitdboard test=procs fields=hostname,msg");
        sprintf(svcscmd,   "hobbitdboard test=svcs fields=hostname,msg");
    }

    sres = newsendreturnbuf(1, NULL);

    if (sendmessage(hobbitcmd, NULL, BBTALK_TIMEOUT, sres) != BB_OK) {
        errormsg("Cannot contact the Hobbit server\n");
        return 1;
    }
    respbuf = getsendreturnstr(sres, 1);
    if (sendmessage(procscmd, NULL, BBTALK_TIMEOUT, sres) != BB_OK) {
        errormsg("Cannot contact the Hobbit server\n");
        return 1;
    }
    procsbuf = getsendreturnstr(sres, 1);
    if (sendmessage(svcscmd, NULL, BBTALK_TIMEOUT, sres) != BB_OK) {
        errormsg("Cannot contact the Hobbit server\n");
        return 1;
    }
    svcsbuf = getsendreturnstr(sres, 1);

    freesendreturnbuf(sres);

    if (!respbuf) {
        errormsg("Unable to find host information\n");
        return 1;
    }

    /* Parse it into a usable list */
    nexthost = respbuf;
    do {
        char *hname, *tname, *eoln;
        int wanted = 1;

        eoln = strchr(nexthost, '\n');
        if (eoln) *eoln = '\0';
        hname = nexthost;
        tname = strchr(nexthost, '|');
        if (tname) {
            *tname = '\0';
            tname++;
        }

        if (nkonly) {
            void *hinfo = hostinfo(hname);
            char *nkalerts = bbh_item(hinfo, BBH_NK);

            if (newnkconfig) {
                if (strcmp(nkval(hname, tname, nkalerts), "No") == 0 ) wanted = 0;
            } else {
                if (!nkalerts) wanted = 0;
            }
        }

        if (wanted && hname && tname && strcmp(hname, "summary") && strcmp(tname, xgetenv("INFOCOLUMN")) && strcmp(tname, xgetenv("TRENDSCOLUMN"))) {
            htnames_t *newitem = (htnames_t *)malloc(sizeof(htnames_t));

            for (hwalk = hosthead; (hwalk && strcmp(hwalk->hostname, hname)); hwalk = hwalk->next);
            if (!hwalk) {
                hwalk = (hostlist_t *)calloc(1, sizeof(hostlist_t));
                hwalk->hostname = strdup(hname);
                hwalk->procs = get_proclist(hname, procsbuf);
                hwalk->svcs  = get_proclist(hname, svcsbuf);
                hwalk->next = hosthead;
                hosthead = hwalk;
                hostcount++;
            }

            newitem->name = strdup(tname);
            newitem->next = hwalk->tests;
            hwalk->tests = newitem;
            hwalk->testcount++;
        }

        if (eoln) {
            nexthost = eoln+1;
            if (*nexthost == '\0') nexthost = NULL;
        }
    } while (nexthost);

    allhosts = (hostlist_t **) malloc(hostcount * sizeof(hostlist_t *));
    for (hwalk = hosthead, hosti=0; (hwalk); hwalk = hwalk->next, hosti++) {
        allhosts[hosti] = hwalk;
        if (hwalk->testcount > maxtests) maxtests = hwalk->testcount;
    }
    alltests = (htnames_t **) malloc(maxtests * sizeof(htnames_t *));
    qsort(&allhosts[0], hostcount, sizeof(hostlist_t **), host_compare);

    /* Get the static info */
    load_all_links();
    init_tcp_services();
    pingcolumn = xgetenv("PINGCOLUMN");
    pingplus = (char *)malloc(strlen(pingcolumn) + 2);
    sprintf(pingplus, "%s=", pingcolumn);

    /* Load alert config */
    alertcolors = colorset(xgetenv("ALERTCOLORS"), ((1 << COL_GREEN) | (1 << COL_BLUE)));
    alertinterval = 60*atoi(xgetenv("ALERTREPEAT"));
    sprintf(configfn, "%s/etc/hobbit-alerts.cfg", xgetenv("BBHOME"));
    load_alertconfig(configfn, alertcolors, alertinterval);
    load_columndocs();


    printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE"));
    sethostenv("", "", "", colorname(COL_BLUE), NULL);
    headfoot(stdout, "confreport", "", "header", COL_BLUE);

    fprintf(stdout, "<table width=\"100%%\" border=0>\n");
    fprintf(stdout, "<tr><th align=center colspan=2><font size=\"+2\">Hobbit configuration Report</font></th></tr>\n");
    fprintf(stdout, "<tr><th valign=top align=left>Date</th><td>%s</td></tr>\n", ctime(&now));
    fprintf(stdout, "<tr><th valign=top align=left>%d hosts included</th><td>\n", hostcount);
    for (hosti=0; (hosti < hostcount); hosti++) {
        fprintf(stdout, "%s ", allhosts[hosti]->hostname);
    }
    fprintf(stdout, "</td></tr>\n");
    if (nkonly) {
        fprintf(stdout, "<tr><th valign=top align=left>Filter</th><td>Only data for the &quot;Critical Systems&quot; view reported</td></tr>\n");
    }
    fprintf(stdout, "</table>\n");

    headfoot(stdout, "confreport", "", "front", COL_BLUE);

    for (hosti=0; (hosti < hostcount); hosti++) {
        for (twalk = allhosts[hosti]->tests, testi = 0; (twalk); twalk = twalk->next, testi++) {
            alltests[testi] = twalk;
        }
        qsort(&alltests[0], allhosts[hosti]->testcount, sizeof(htnames_t **), test_compare);

        print_host(allhosts[hosti], alltests, allhosts[hosti]->testcount);
    }

    headfoot(stdout, "confreport", "", "back", COL_BLUE);
    print_columndocs();

    headfoot(stdout, "confreport", "", "footer", COL_BLUE);

    return 0;
}
Beispiel #11
0
void print_hoststatus(FILE *output, hstatus_t *itm, void * statetree, void * columns, int prio, int firsthost, int firsthostever)
{
	void *hinfo;
	char *dispname, *ip, *key;
	time_t now;
	xtreePos_t colhandle;

	now = getcurrenttime(NULL);
	hinfo = hostinfo(itm->hostname);
	dispname = xmh_item(hinfo, XMH_DISPLAYNAME);
	ip = xmh_item(hinfo, XMH_IP);

	fprintf(output, "<TR>\n");

	/* Print the priority */
	fprintf(output, "<TD ALIGN=LEFT VALIGN=TOP WIDTH=10%% NOWRAP>");
	if (firsthost) 
		if (prio == 99) {
			if (firsthostever)
				/* Only non-prioritised hosts, so just drop that text */
				fprintf(output, "&nbsp;");
			else
				fprintf(output, "<FONT %s>No priority</FONT>", xgetenv("XYMONPAGEROWFONT"));
		}
		else {
			fprintf(output, "<FONT %s>PRIO %d</FONT>", xgetenv("XYMONPAGEROWFONT"), prio);
		}

	else 
		fprintf(output, "&nbsp;");
	fprintf(output, "</TD>\n");

	/* Print the hostname with a link to the critical systems info page */
	fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", hostnamehtml(itm->hostname, NULL, usetooltips));

	key = (char *)malloc(1024);
	for (colhandle = xtreeFirst(columns); (colhandle != xtreeEnd(columns)); colhandle = xtreeNext(columns, colhandle)) {
		char *colname;
		xtreePos_t sthandle;

		fprintf(output, "<TD ALIGN=CENTER>");

		colname = (char *)xtreeKey(columns, colhandle);
		key = (char *)realloc(key, 2 + strlen(itm->hostname) + strlen(colname));
		sprintf(key, "%s|%s", itm->hostname, colname);
		sthandle = xtreeFind(statetree, key);
		if (sthandle == xtreeEnd(statetree)) {
			fprintf(output, "-");
		}
		else {
			hstatus_t *column;
			char *htmlalttag;
			char *htmlackstr;

			column = (hstatus_t *)xtreeData(statetree, sthandle);
			if (column->config->priority != prio) 
				fprintf(output, "-");
			else {
				time_t age = now - column->lastchange;
				char *htmlgroupstr;
				char *htmlextrastr;

				htmlalttag = alttag(colname, column->color, 0, 1, agestring(age));
				htmlackstr = (column->ackmsg ? column->ackmsg : "");
				htmlgroupstr = strdup(urlencode(column->config->ttgroup ? column->config->ttgroup : ""));
				htmlextrastr = strdup(urlencode(column->config->ttextra ? column->config->ttextra : ""));
				fprintf(output, "<A HREF=\"%s&amp;NKPRIO=%d&amp;NKTTGROUP=%s&amp;NKTTEXTRA=%s\">",
					hostsvcurl(itm->hostname, colname, 1),
					prio, 
					htmlgroupstr, htmlextrastr);
				fprintf(output, "<IMG SRC=\"%s/%s\" ALT=\"%s\" TITLE=\"%s %s\" HEIGHT=\"%s\" WIDTH=\"%s\" BORDER=0></A>",
					xgetenv("XYMONSKIN"), 
					dotgiffilename(column->color, (column->acktime > 0), (age > oldlimit)),
					colorname(column->color), htmlalttag, htmlackstr,
					xgetenv("DOTHEIGHT"), xgetenv("DOTWIDTH"));
				xfree(htmlgroupstr);
				xfree(htmlextrastr);
			}
		}

		fprintf(output, "</TD>\n");
	}
	xfree(key);

	fprintf(output, "</TR>\n");
}
Beispiel #12
0
int loadstatus(int maxprio, time_t maxage, int mincolor, int wantacked)
{
	char *board, *bol, *eol;
	time_t now;

	/* 
	 * We leak memory by dup'ing this and not freeing it. 
	 * But we cannot free it, because the tree holding the data
	 * for later printing contains pointers into this string buffer.
	 */
	board = strdup(boardmaster);

	now = getcurrenttime(NULL);
	treecount++;
	if (treecount == 1) {
		rbstate = malloc(sizeof(void *));
		hostsonpage = malloc(sizeof(void *));
	}
	else {
		rbstate = realloc(rbstate, (treecount) * sizeof(void *));
		hostsonpage = realloc(hostsonpage, (treecount) * sizeof(void *));
	}
	rbstate[treecount-1] = xtreeNew(strcasecmp);
	hostsonpage[treecount-1] = xtreeNew(strcasecmp);

	bol = board;
	while (bol && (*bol)) {
		char *endkey;
		eol = strchr(bol, '\n'); if (eol) *eol = '\0';

		/* Find the config entry */
		endkey = strchr(bol, '|'); if (endkey) endkey = strchr(endkey+1, '|'); 
		if (endkey) {
			critconf_t *cfg;
			char *ackstr, *ackrtimestr, *ackvtimestr, *acklevelstr, *ackbystr, *ackmsgstr;

			*endkey = '\0';
			cfg = get_critconfig(bol, CRITCONF_TIMEFILTER, NULL);
			*endkey = '|';

			if (cfg) {
				hstatus_t *newitem = (hstatus_t *)calloc(1, sizeof(hstatus_t));
				newitem->config     = cfg;
				newitem->hostname   = gettok(bol, "|");
				newitem->testname   = gettok(NULL, "|");
				newitem->color      = parse_color(gettok(NULL, "|"));
				newitem->lastchange = atoi(gettok(NULL, "|"));
				newitem->logtime    = atoi(gettok(NULL, "|"));
				newitem->validtime  = atoi(gettok(NULL, "|"));
				ackstr              = gettok(NULL, "|");
				ackrtimestr = ackvtimestr = acklevelstr = ackbystr = ackmsgstr = NULL;

				if (ackstr) {
					nldecode(ackstr);
					ackrtimestr = strtok(ackstr, ":");
					if (ackrtimestr) ackvtimestr = strtok(NULL, ":");
					if (ackvtimestr) acklevelstr = strtok(NULL, ":");
					if (acklevelstr) ackbystr = strtok(NULL, ":");
					if (ackbystr)    ackmsgstr = strtok(NULL, ":");
				}

				if ( (hostinfo(newitem->hostname) == NULL)  ||
				     ((newitem->config->priority > maxprio)  && (newitem->config->priority != 99)) ||
				     ((now - newitem->lastchange) > maxage) ||
				     (newitem->color < mincolor)            ||
				     (ackmsgstr && !wantacked)              ) {
					xfree(newitem);
				}
				else {
					if (ackvtimestr && ackbystr && ackmsgstr) {
						newitem->acktime = atoi(ackvtimestr);
						newitem->ackedby = strdup(ackbystr);
						newitem->ackmsg  = strdup(ackmsgstr);
					}

					newitem->key = (char *)malloc(strlen(newitem->hostname) + strlen(newitem->testname) + 2);
					sprintf(newitem->key, "%s|%s", newitem->hostname, newitem->testname);
					xtreeAdd(rbstate[treecount-1], newitem->key, newitem);
				}
			}
		}

		bol = (eol ? (eol+1) : NULL);
	}

	return 0;
}
Beispiel #13
0
void print_hoststatus(FILE *output, hstatus_t *itm, RbtHandle columns, int prio, int firsthost)
{
	void *hinfo;
	char *dispname, *ip, *key;
	time_t now;
	RbtIterator colhandle;

	now = getcurrenttime(NULL);
	hinfo = hostinfo(itm->hostname);
	dispname = xmh_item(hinfo, XMH_DISPLAYNAME);
	ip = xmh_item(hinfo, XMH_IP);

	fprintf(output, "<TR>\n");

	/* Print the priority */
	fprintf(output, "<TD ALIGN=LEFT VALIGN=TOP WIDTH=25%% NOWRAP>");
	if (firsthost) 
		fprintf(output, "<FONT %s>PRIO %d</FONT>", xgetenv("XYMONPAGEROWFONT"), prio);
	else 
		fprintf(output, "&nbsp;");
	fprintf(output, "</TD>\n");

	/* Print the hostname with a link to the critical systems info page */
	fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", hostnamehtml(itm->hostname, NULL, usetooltips));

	key = (char *)malloc(strlen(itm->hostname) + 1024);
	for (colhandle = rbtBegin(columns); (colhandle != rbtEnd(columns)); colhandle = rbtNext(columns, colhandle)) {
		void *k1, *k2;
		char *colname;
		RbtIterator sthandle;

		fprintf(output, "<TD ALIGN=CENTER>");

		rbtKeyValue(columns, colhandle, &k1, &k2);
		colname = (char *)k1;
		sprintf(key, "%s|%s", itm->hostname, colname);
		sthandle = rbtFind(rbstate, key);
		if (sthandle == rbtEnd(rbstate)) {
			fprintf(output, "-");
		}
		else {
			hstatus_t *column;
			char *htmlalttag;
			char *htmlackstr;

			rbtKeyValue(rbstate, sthandle, &k1, &k2);
			column = (hstatus_t *)k2;
			if (column->config->priority != prio) 
				fprintf(output, "-");
			else {
				time_t age = now - column->lastchange;
				char *htmlgroupstr;
				char *htmlextrastr;

				htmlalttag = alttag(colname, column->color, 0, 1, agestring(age));
				htmlackstr = (column->ackmsg ? column->ackmsg : "");
				htmlgroupstr = strdup(urlencode(column->config->ttgroup ? column->config->ttgroup : ""));
				htmlextrastr = strdup(urlencode(column->config->ttextra ? column->config->ttextra : ""));
				fprintf(output, "<A HREF=\"%s&amp;NKPRIO=%d&amp;NKTTGROUP=%s&amp;NKTTEXTRA=%s\">",
					hostsvcurl(itm->hostname, colname, 1),
					prio, 
					htmlgroupstr, htmlextrastr);
				fprintf(output, "<IMG SRC=\"%s/%s\" ALT=\"%s\" TITLE=\"%s %s\" HEIGHT=\"%s\" WIDTH=\"%s\" BORDER=0></A>",
					xgetenv("XYMONSKIN"), 
					dotgiffilename(column->color, (column->acktime > 0), (age > oldlimit)),
					colorname(column->color), htmlalttag, htmlackstr,
					xgetenv("DOTHEIGHT"), xgetenv("DOTWIDTH"));
				xfree(htmlgroupstr);
				xfree(htmlextrastr);
			}
		}

		fprintf(output, "</TD>\n");
	}
	xfree(key);

	fprintf(output, "</TR>\n");
}
Beispiel #14
0
void generate_compactitems(state_t **topstate)
{
	void *bbh;
	compact_t **complist = NULL;
	int complistsz = 0;
	hostlist_t 	*h;
	entry_t		*e;
	char *compacted;
	char *tok1, *tok2, *savep1, *savep2;
	compact_t *itm;
	int i;
	state_t *newstate;
	time_t now = getcurrenttime(NULL);

	for (h = hostlistBegin(); (h); h = hostlistNext()) {
		bbh = hostinfo(h->hostentry->hostname);
		compacted = bbh_item(bbh, BBH_COMPACT);
		if (!compacted) continue;

		tok1 = strtok_r(compacted, ",", &savep1);
		while (tok1) {
			char *members;

			itm = (compact_t *)calloc(1, sizeof(compact_t));
			itm->compactname = strdup(strtok_r(tok1, "=", &savep2));
			members = strtok_r(NULL, "\n", &savep2);
			itm->members = (char *)malloc(3 + strlen(members));
			sprintf(itm->members, "|%s|", members);

			if (complistsz == 0) {
				complist = (compact_t **)calloc(2, sizeof(compact_t *));
			}
			else {
				complist = (compact_t **)realloc(complist, (complistsz+2)*sizeof(compact_t *));
			}

			complist[complistsz++] = itm;
			complist[complistsz] = NULL;

			tok1 = strtok_r(NULL, ",", &savep1);
		}

		for (e = h->hostentry->entries; (e); e = e->next) {
			for (i = 0; (i < complistsz); i++) {
				if (wantedcolumn(e->column->name, complist[i]->members)) {
					e->compacted = 1;
					if (e->color > complist[i]->color) complist[i]->color = e->color;
					if (e->fileage > complist[i]->fileage) complist[i]->fileage = e->fileage;
				}
			}
		}

		for (i = 0; (i < complistsz); i++) {
			logdata_t log;
			char fn[PATH_MAX];

			memset(&log, 0, sizeof(log));
			sprintf(fn, "%s.%s", commafy(h->hostentry->hostname), complist[i]->compactname);
			log.hostname = h->hostentry->hostname;
			log.testname = complist[i]->compactname;
			log.color = complist[i]->color;
			log.testflags = "";
			log.lastchange = now - complist[i]->fileage;
			log.logtime = getcurrenttime(NULL);
			log.validtime = log.logtime + 300;
			log.sender = "";
			log.msg = "";
			newstate = init_state(fn, &log);
			if (newstate) {
				newstate->next = *topstate;
				*topstate = newstate;
			}
		}
	}
}
Beispiel #15
0
void do_acklog(FILE *output, int maxcount, int maxminutes)
{
	FILE *acklog;
	char acklogfilename[PATH_MAX];
	time_t cutoff;
	struct stat st;
	char l[MAX_LINE_LEN];
	char title[200];
	ack_t *acks;
	int num, ackintime_count;

	havedoneacklog = 1;

	cutoff = ( (maxminutes) ? (getcurrenttime(NULL) - maxminutes*60) : 0);
	if ((!maxcount) || (maxcount > 100)) maxcount = 100;

	sprintf(acklogfilename, "%s/acknowledge.log", xgetenv("BBSERVERLOGS"));
	acklog = fopen(acklogfilename, "r");
	if (!acklog) {
		/* BB compatible naming */
		sprintf(acklogfilename, "%s/acklog", xgetenv("BBACKS"));
		acklog = fopen(acklogfilename, "r");
	}
	if (!acklog) {
		/* If no acklog, that is OK - some people dont use acks */
		dbgprintf("Cannot open acklog\n");
		return;
	}

	/* HACK ALERT! */
	if (stat(acklogfilename, &st) == 0) {
		if (st.st_size != 0) {
			/* Assume a log entry is max 150 bytes */
			if (150*maxcount < st.st_size) {
				fseeko(acklog, -150*maxcount, SEEK_END);
				fgets(l, sizeof(l), acklog);
				if (strchr(l, '\n') == NULL) {
					errprintf("Oops - couldnt find a newline in acklog\n");
				}
			}
		}
	}

	acks = (ack_t *) calloc(maxcount, sizeof(ack_t));
	ackintime_count = num = 0;

	while (fgets(l, sizeof(l), acklog)) {
		char ackedby[MAX_LINE_LEN], hosttest[MAX_LINE_LEN], color[10], ackmsg[MAX_LINE_LEN];
		char ackfn[PATH_MAX];
		char *testname;
		void *hinfo;
		int ok;

		if (atol(l) >= cutoff) {
			int c_used;
			char *p, *p1, *hobbitdacker = NULL;

			sscanf(l, "%u\t%d\t%d\t%d\t%s\t%s\t%s\t%n",
				(time_t *)&acks[num].acktime, &acks[num].acknum,
				&acks[num].duration, &acks[num].acknum2,
				ackedby, hosttest, color, &c_used);

			p1 = ackmsg;
			for (p=l+c_used, p1=ackmsg; (*p); ) {
				/*
				 * Need to de-code the ackmsg - it may have been entered
				 * via a web page that did "%asciival" encoding.
				 */
				if ((*p == '%') && (strlen(p) >= 3) && isxdigit((int)*(p+1)) && isxdigit((int)*(p+2))) {
					char hexnum[3];

					hexnum[0] = *(p+1);
					hexnum[1] = *(p+2);
					hexnum[2] = '\0';
					*p1 = (char) strtol(hexnum, NULL, 16);
					p1++;
					p += 3;
				}
				else {
					*p1 = *p;
					p1++;
					p++;
				}
			}
			*p1 = '\0';

			/* Hobbit uses \n in the ack message, for the "acked by" data. Cut it off. */
			nldecode(ackmsg); p = strchr(ackmsg, '\n'); 
			if (p) {
				if (strncmp(p, "\nAcked by:", 10) == 0) hobbitdacker = p+10;
				*p = '\0';
			}

			/* Show only the first 30 characters in message */
			if (strlen(ackmsg) > 30) ackmsg[30] = '\0';

			sprintf(ackfn, "%s/ack.%s", xgetenv("BBACKS"), hosttest);

			testname = strrchr(hosttest, '.');
			if (testname) {
				*testname = '\0'; testname++; 
			}
			else testname = "unknown";

			ok = 1;

			/* Ack occurred within wanted timerange ? */
			if (ok && (acks[num].acktime < cutoff)) ok = 0;

			/* Unknown host ? */
			hinfo = hostinfo(hosttest);
			if (!hinfo) ok = 0;
			if (hinfo && bbh_item(hinfo, BBH_FLAG_NOBB2)) ok = 0;

			if (ok) {
				char *ackerp;

				/* If ack has expired or tag file is gone, the ack is no longer valid */
				acks[num].ackvalid = 1;
				if ((acks[num].acktime + 60*acks[num].duration) < getcurrenttime(NULL)) acks[num].ackvalid = 0;
				if (acks[num].ackvalid && (stat(ackfn, &st) != 0)) acks[num].ackvalid = 0;

				if (strcmp(ackedby, "np_filename_not_used") != 0) {
					ackerp = ackedby;
					if (strncmp(ackerp, "np_", 3) == 0) ackerp += 3;
					p = strrchr(ackerp, '_');
					if (p > ackerp) *p = '\0';
					acks[num].ackedby = strdup(ackerp);
				}
				else if (hobbitdacker) {
					acks[num].ackedby = strdup(hobbitdacker);
				}
				else {
					acks[num].ackedby = "";
				}

				acks[num].hostname = strdup(hosttest);
				acks[num].testname = strdup(testname);
				strcat(color, " "); acks[num].color = parse_color(color);
				acks[num].ackmsg = strdup(ackmsg);
				ackintime_count++;

				num = (num + 1) % maxcount;
			}
		}
	}

	if (ackintime_count > 0) {
		int firstack, lastack;
		int period = maxminutes;

		if (ackintime_count <= maxcount) {
			firstack = 0;
			lastack = ackintime_count-1;
			period = maxminutes;
		}
		else {
			firstack = num;
			lastack = ( (num == 0) ? maxcount : (num-1));
			ackintime_count = maxcount;
			period = ((getcurrenttime(NULL)-acks[firstack].acktime) / 60);
		}

		sprintf(title, "%d events acknowledged in the past %u minutes", ackintime_count, period);

		fprintf(output, "<BR><BR>\n");
		fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title);
		fprintf(output, "<TR BGCOLOR=\"#333333\">\n");
		fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", title);

		for (num = lastack; (ackintime_count); ackintime_count--, num = ((num == 0) ? (maxcount-1) : (num - 1)) ) {
			fprintf(output, "<TR BGCOLOR=#000000>\n");

			fprintf(output, "<TD ALIGN=CENTER><FONT COLOR=white>%s</FONT></TD>\n", ctime(&acks[num].acktime));
			fprintf(output, "<TD ALIGN=CENTER BGCOLOR=%s><FONT COLOR=black>%s</FONT></TD>\n", colorname(acks[num].color), acks[num].hostname);
			fprintf(output, "<TD ALIGN=CENTER><FONT COLOR=white>%s</FONT></TD>\n", acks[num].testname);

			if (acks[num].color != -1) {
   				fprintf(output, "<TD ALIGN=CENTER><IMG SRC=\"%s/%s\"></TD>\n", 
					xgetenv("BBSKIN"), 
					dotgiffilename(acks[num].color, acks[num].ackvalid, 1));
			}
			else
   				fprintf(output, "<TD ALIGN=CENTER><FONT COLOR=white>&nbsp;</FONT></TD>\n");

			fprintf(output, "<TD ALIGN=LEFT BGCOLOR=#000033>%s</TD>\n", acks[num].ackedby);
			fprintf(output, "<TD ALIGN=LEFT>%s</TD></TR>\n", acks[num].ackmsg);
		}

	}
	else {
		sprintf(title, "No events acknowledged in the last %u minutes", maxminutes);

		fprintf(output, "<BR><BR>\n");
		fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title);
		fprintf(output, "<TR BGCOLOR=\"#333333\">\n");
		fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", title);
	}

	fprintf(output, "</TABLE>\n");

	fclose(acklog);
}
Beispiel #16
0
int web_access_allowed(char *username, char *hostname, char *testname, web_access_type_t acc)
{

	void *hinfo;
	char *pages, *onepg, *key;

	hinfo = hostinfo(hostname);
	if (!hinfo || !acctree || !username) return 0;

	/* Check for "root" access first */
	key = (char *)malloc(strlen(username) + 6);
	sprintf(key, "root %s", username);
	if (xtreeFind(acctree, key) != xtreeEnd(acctree)) {
		xfree(key);
		return 1;
	}
	xfree(key);

	pages = strdup(xmh_item(hinfo, XMH_ALLPAGEPATHS));
	onepg = strtok(pages, ",");
	while (onepg) {
		char *p;

		p = strchr(onepg, '/'); if (p) *p = '\0'; /* Will only look at the top-level path element */

		key = (char *)malloc(strlen(onepg) + strlen(username) + 2);
		sprintf(key, "%s %s", onepg, username);
		if (xtreeFind(acctree, key) != xtreeEnd(acctree)) {
			xfree(key);
			xfree(pages);
			return 1;
		}

		xfree(key);
		onepg = strtok(NULL, ",");
	}
	xfree(pages);

	if (hostname) {
		/* See if user is a member of a group named by the hostname */
		key = (char *)malloc(strlen(hostname) + strlen(username) + 2);
		sprintf(key, "%s %s", hostname, username);
		if (xtreeFind(acctree, key) != xtreeEnd(acctree)) {
			xfree(key);
			return 1;
		}
		xfree(key);
	}

	if (testname) {
		/* See if user is a member of a group named by the testname */
		key = (char *)malloc(strlen(testname) + strlen(username) + 2);
		sprintf(key, "%s %s", testname, username);
		if (xtreeFind(acctree, key) != xtreeEnd(acctree)) {
			xfree(key);
			return 1;
		}
		xfree(key);
	}

	return 0;
}
Beispiel #17
0
int main(int argc, char *argv[])
{
	int argi;
	namelist_t *h;
	char *val;

	load_hostnames(argv[1], NULL, get_fqdn());

	for (argi = 2; (argi < argc); argi++) {
		char s[1024];
		char *p;
		char *hname;
		char hostip[IP_ADDR_STRLEN];

handlehost:
		hname = knownhost(argv[argi], hostip, 1);
		if (hname == NULL) {
			printf("Unknown host '%s'\n", argv[argi]);
			continue;
		}
		if (strcmp(hname, argv[argi])) {
			printf("Using canonical name '%s'\n", hname);
		}
		h = hostinfo(hname);

		if (h == NULL) { printf("Host %s not found\n", argv[argi]); continue; }

		val = bbh_item_walk(h);
		printf("Entry for host %s\n", h->bbhostname);
		while (val) {
			printf("\t%s\n", val);
			val = bbh_item_walk(NULL);
		}

		do {
			*s = '\0';
			printf("Pick item:"); fflush(stdout); fgets(s, sizeof(s), stdin);
			p = strchr(s, '\n'); if (p) *p = '\0';
			if (*s == '!') {
				load_hostnames(argv[1], NULL, get_fqdn());
				/* Must restart! The "h" handle is no longer valid. */
				goto handlehost;
			}
			else if (*s == '>') {
				val = bbh_item_multi(h, BBH_PAGEPATH);
				while (val) {
					printf("\t%s value is: '%s'\n", s, val);
					val = bbh_item_multi(NULL, BBH_PAGEPATH);
				}
			}
			else if (strncmp(s, "set ", 4) == 0) {
				bbh_set_item(h, BBH_DATA, strdup(s+4));
			}
			else if (*s) {
				val = bbh_item_byname(h, s);
				if (val) printf("\t%s value is: '%s'\n", s, val);
				else printf("\t%s not found\n", s);
			}
		} while (*s);
	}

	return 0;
}
Beispiel #18
0
void do_eventlog(FILE *output, int maxcount, int maxminutes, char *fromtime, char *totime, 
		char *pageregex, char *expageregex,
		char *hostregex, char *exhostregex,
		char *testregex, char *extestregex,
		char *colrregex, int ignoredialups,
		f_hostcheck hostcheck,
		event_t **eventlist, countlist_t **hostcounts, countlist_t **servicecounts,
		countsummary_t counttype, eventsummary_t sumtype, char *periodstring)
{
	FILE *eventlog;
	char eventlogfilename[PATH_MAX];
	time_t firstevent = 0;
	time_t lastevent = getcurrenttime(NULL);
	event_t	*eventhead = NULL;
	struct stat st;
	char l[MAX_LINE_LEN];
	char title[200];

	/* For the PCRE matching */
	const char *errmsg = NULL;
	int errofs = 0;
	pcre *pageregexp = NULL;
	pcre *expageregexp = NULL;
	pcre *hostregexp = NULL;
	pcre *exhostregexp = NULL;
	pcre *testregexp = NULL;
	pcre *extestregexp = NULL;
	pcre *colrregexp = NULL;
	countlist_t *hostcounthead = NULL, *svccounthead = NULL;

	if (eventlist) *eventlist = NULL;
	if (hostcounts) *hostcounts = NULL;
	if (servicecounts) *servicecounts = NULL;

	havedoneeventlog = 1;

	if ((maxminutes > 0) && (fromtime || totime)) {
		fprintf(output, "<B>Only one time interval type is allowed!</B>");
		return;
	}

	if (fromtime) {
		firstevent = eventreport_time(fromtime);
		if(firstevent < 0) {
			if (output) fprintf(output,"<B>Invalid 'from' time: %s</B>", htmlquoted(fromtime));
			return;
		}
	}
	else if (maxminutes == -1) {
		/* Unlimited number of minutes */
		firstevent = 0;
	}
	else if (maxminutes > 0) {
		firstevent = getcurrenttime(NULL) - maxminutes*60;
	}
	else {
		firstevent = getcurrenttime(NULL) - 86400;
	}

	if (totime) {
		lastevent = eventreport_time(totime);
		if (lastevent < 0) {
			if (output) fprintf(output,"<B>Invalid 'to' time: %s</B>", htmlquoted(totime));
			return;
		}
		if (lastevent < firstevent) {
			if (output) fprintf(output,"<B>'to' time must be after 'from' time.</B>");
			return;
		}
	}

	if (!maxcount) maxcount = 100;

	if (pageregex && *pageregex) pageregexp = pcre_compile(pageregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (expageregex && *expageregex) expageregexp = pcre_compile(expageregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (hostregex && *hostregex) hostregexp = pcre_compile(hostregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (exhostregex && *exhostregex) exhostregexp = pcre_compile(exhostregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (testregex && *testregex) testregexp = pcre_compile(testregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (extestregex && *extestregex) extestregexp = pcre_compile(extestregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (colrregex && *colrregex) colrregexp = pcre_compile(colrregex, PCRE_CASELESS, &errmsg, &errofs, NULL);

	sprintf(eventlogfilename, "%s/allevents", xgetenv("XYMONHISTDIR"));
	eventlog = fopen(eventlogfilename, "r");

	if (eventlog && (stat(eventlogfilename, &st) == 0)) {
		time_t curtime;
		int done = 0;
		int unlimited = (maxcount == -1);

		if (unlimited) maxcount = 1000;
		do {
			/* Find a spot in the eventlog file close to where the firstevent time is */
			fseeko(eventlog, 0, SEEK_END);
			do {
				/* Go back maxcount*80 bytes - one entry is ~80 bytes */
				if (ftello(eventlog) > maxcount*80) {
					unsigned int uicurtime;
					fseeko(eventlog, -maxcount*80, SEEK_CUR); 
					if (fgets(l, sizeof(l), eventlog) &&  /* Skip to start of line */
					    fgets(l, sizeof(l), eventlog)) {
						sscanf(l, "%*s %*s %u %*u %*u %*s %*s %*d", &uicurtime);
						curtime = uicurtime;
						done = (curtime < firstevent);
						if (unlimited && !done) maxcount += 1000;
					}
					else {
						if (output) fprintf(output,"Error reading eventlog file %s: %s\n", eventlogfilename, strerror(errno));
						return;
					}
				}
				else {
					rewind(eventlog);
					curtime = 0;
					done = 1;
				}
			} while (!done);

			if (unlimited) unlimited = ((curtime > firstevent) && (ftello(eventlog) > 0));
		} while (unlimited);
	}
	
	eventhead = NULL;

	while (eventlog && (fgets(l, sizeof(l), eventlog))) {

		time_t eventtime, changetime, duration;
		unsigned int uievt, uicht, uidur;
		char hostname[MAX_LINE_LEN], svcname[MAX_LINE_LEN], newcol[MAX_LINE_LEN], oldcol[MAX_LINE_LEN];
		char *newcolname, *oldcolname;
		int state, itemsfound, colrmatch;
		event_t *newevent;
		void *eventhost;
		struct htnames_t *eventcolumn;
		int ovector[30];
		eventcount_t *countrec;

		itemsfound = sscanf(l, "%s %s %u %u %u %s %s %d",
			hostname, svcname,
			&uievt, &uicht, &uidur, 
			newcol, oldcol, &state);
		eventtime = uievt; changetime = uicht; duration = uidur;
		oldcolname = colorname(eventcolor(oldcol));
		newcolname = colorname(eventcolor(newcol));
		/* For DURATION counts, we must parse all events until now */
		if ((counttype != XYMON_COUNT_DURATION) && (eventtime > lastevent)) break;
		eventhost = hostinfo(hostname);
		eventcolumn = getname(svcname, 1);

		if ( (itemsfound == 8) && 
		     (eventtime >= firstevent) && 
		     (eventhost && !xmh_item(eventhost, XMH_FLAG_NONONGREEN)) && 
		     (wanted_eventcolumn(svcname)) ) {

			if (eventfilter(eventhost, svcname, 
					pageregexp, expageregexp, 
					hostregexp, exhostregexp,
					testregexp, extestregexp,
					ignoredialups, hostcheck) == 0) continue;

			/* For duration counts, record all events. We'll filter out the colors later. */
			if (colrregexp && (counttype != XYMON_COUNT_DURATION)) {
				colrmatch = ( (pcre_exec(colrregexp, NULL, newcolname, strlen(newcolname), 0, 0,
							ovector, (sizeof(ovector)/sizeof(int))) >= 0) ||
					      (pcre_exec(colrregexp, NULL, oldcolname, strlen(oldcolname), 0, 0,
							ovector, (sizeof(ovector)/sizeof(int))) >= 0) );
			}
			else
				colrmatch = 1;
			if (!colrmatch) continue;

			newevent = (event_t *) malloc(sizeof(event_t));
			newevent->host       = eventhost;
			newevent->service    = eventcolumn;
			newevent->eventtime  = eventtime;
			newevent->changetime = changetime;
			newevent->duration   = duration;
			newevent->newcolor   = eventcolor(newcol);
			newevent->oldcolor   = eventcolor(oldcol);
			newevent->next = eventhead;
			eventhead = newevent;

			if (counttype != XYMON_COUNT_DURATION) {
				countrec = (eventcount_t *)xmh_item(eventhost, XMH_DATA);
				while (countrec && (countrec->service != eventcolumn)) countrec = countrec->next;
				if (countrec == NULL) {
					countrec = (eventcount_t *)calloc(1, sizeof(eventcount_t));
					countrec->service = eventcolumn;
					countrec->next = (eventcount_t *)xmh_item(eventhost, XMH_DATA);
					xmh_set_item(eventhost, XMH_DATA, (void *)countrec);
				}
				countrec->count++;
			}
		}
	}

	/* Count the state changes per host */
	svccounthead = hostcounthead = NULL;
	switch (counttype) {
	  case XYMON_COUNT_EVENTS: count_events(&hostcounthead, &svccounthead); break;
	  case XYMON_COUNT_DURATION: count_duration(firstevent, lastevent,
					       pageregexp, expageregexp,
					       hostregexp, exhostregexp,
					       testregexp, extestregexp,
					       ignoredialups, hostcheck,
					       eventhead, &hostcounthead, &svccounthead); break;
	  default: break;
	}

	if (hostcounthead) hostcounthead = msort(hostcounthead, record_compare, record_getnext, record_setnext);
	if (svccounthead)  svccounthead = msort(svccounthead, record_compare, record_getnext, record_setnext);

	if (eventhead && (output != NULL)) {
		char *bgcolors[2] = { "#000000", "#000033" };
		int  bgcolor = 0;
		struct event_t *ewalk, *lasttoshow = eventhead;
		countlist_t *cwalk;
		unsigned long totalcount = 0;

		if (periodstring) fprintf(output, "<p><font size=+1>%s</font></p>\n", htmlquoted(periodstring));

		switch (sumtype) {
		  case XYMON_S_HOST_BREAKDOWN:
			/* Request for a specific service, show breakdown by host */
			for (cwalk = hostcounthead; (cwalk); cwalk = cwalk->next) totalcount += cwalk->total;
			fprintf(output, "<table summary=\"Breakdown by host\" border=0>\n");
			fprintf(output, "<tr><th align=left>Host</th><th colspan=2>%s</th></tr>\n",
				(counttype == XYMON_COUNT_EVENTS) ? "State changes" : "Seconds red/yellow");
			fprintf(output, "<tr><td colspan=3><hr width=\"100%%\"></td></tr>\n");
			for (cwalk = hostcounthead; (cwalk && (cwalk->total > 0)); cwalk = cwalk->next) {
				fprintf(output, "<tr><td align=left>%s</td><td align=right>%lu</td><td align=right>(%6.2f %%)</tr>\n",
					xmh_item(cwalk->src, XMH_HOSTNAME), 
					cwalk->total, ((100.0 * cwalk->total) / totalcount));
			}
			fprintf(output, "</table>\n");
			break;

		  case XYMON_S_SERVICE_BREAKDOWN:
			/* Request for a specific host, show breakdown by service */
			for (cwalk = svccounthead; (cwalk); cwalk = cwalk->next) totalcount += cwalk->total;
			fprintf(output, "<table summary=\"Breakdown by service\" border=0>\n");
			fprintf(output, "<tr><th align=left>Service</th><th colspan=2>%s</th></tr>\n",
				(counttype == XYMON_COUNT_EVENTS) ? "State changes" : "Seconds red/yellow");
			fprintf(output, "<tr><td colspan=3><hr width=\"100%%\"></td></tr>\n");
			for (cwalk = svccounthead; (cwalk && (cwalk->total > 0)); cwalk = cwalk->next) {
				fprintf(output, "<tr><td align=left>%s</td><td align=right>%lu</td><td align=right>(%6.2f %%)</tr>\n",
					((htnames_t *)cwalk->src)->name, 
					cwalk->total, ((100.0 * cwalk->total) / totalcount));
			}
			fprintf(output, "</table>\n");
			break;

		  case XYMON_S_NONE:
			break;
		}

		if (sumtype == XYMON_S_NONE) {
			int  count;
			count=0;
			ewalk=eventhead; 
			do {
				count++;
				lasttoshow = ewalk;
				ewalk = ewalk->next;
			} while (ewalk && (count<maxcount));
			if (ewalk) ewalk->next = NULL;	/* Terminate list if any items left */

			if (maxminutes > 0)  { 
				sprintf(title, "%d events received in the past %u minutes", 
					count, (unsigned int)((getcurrenttime(NULL) - lasttoshow->eventtime) / 60));
			}
			else {
				sprintf(title, "%d events received.", count);
			}
		}
		else {
			strcpy(title, "Events in summary");
		}

		fprintf(output, "<BR><BR>\n");
		fprintf(output, "<TABLE SUMMARY=\"$EVENTSTITLE\" BORDER=0>\n");
		fprintf(output, "<TR BGCOLOR=\"#333333\">\n");
		fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", htmlquoted(title));

		for (ewalk=eventhead; (ewalk); ewalk=ewalk->next) {
			char *hostname = xmh_item(ewalk->host, XMH_HOSTNAME);

			if ( (counttype == XYMON_COUNT_DURATION) &&
			     (ewalk->oldcolor < COL_YELLOW) &&
			     (ewalk->newcolor < COL_YELLOW) ) continue;

			if ( (counttype == XYMON_COUNT_DURATION) &&
			     (ewalk->eventtime >= lastevent) ) continue;

			fprintf(output, "<TR BGCOLOR=%s>\n", bgcolors[bgcolor]);
			bgcolor = ((bgcolor + 1) % 2);

			fprintf(output, "<TD ALIGN=CENTER>%s</TD>\n", ctime(&ewalk->eventtime));

			if (ewalk->newcolor == COL_CLEAR) {
				fprintf(output, "<TD ALIGN=CENTER BGCOLOR=black><FONT COLOR=white>%s</FONT></TD>\n",
					hostname);
			}
			else {
				fprintf(output, "<TD ALIGN=CENTER BGCOLOR=%s><FONT COLOR=black>%s</FONT></TD>\n",
					colorname(ewalk->newcolor), hostname);
			}

			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", ewalk->service->name);
			fprintf(output, "<TD><A HREF=\"%s\">\n", 
				histlogurl(hostname, ewalk->service->name, ewalk->changetime, NULL));
			fprintf(output, "<IMG SRC=\"%s/%s\"  HEIGHT=\"%s\" WIDTH=\"%s\" BORDER=0 ALT=\"%s\" TITLE=\"%s\"></A>\n", 
				xgetenv("XYMONSKIN"), dotgiffilename(ewalk->oldcolor, 0, 0), 
				xgetenv("DOTHEIGHT"), xgetenv("DOTWIDTH"), 
				colorname(ewalk->oldcolor), colorname(ewalk->oldcolor));
			fprintf(output, "<IMG SRC=\"%s/arrow.gif\" BORDER=0 ALT=\"From -&gt; To\">\n", 
				xgetenv("XYMONSKIN"));
			fprintf(output, "<TD><A HREF=\"%s\">\n", 
				histlogurl(hostname, ewalk->service->name, ewalk->eventtime, NULL));
			fprintf(output, "<IMG SRC=\"%s/%s\"  HEIGHT=\"%s\" WIDTH=\"%s\" BORDER=0 ALT=\"%s\" TITLE=\"%s\"></A></TD>\n", 
				xgetenv("XYMONSKIN"), dotgiffilename(ewalk->newcolor, 0, 0), 
				xgetenv("DOTHEIGHT"), xgetenv("DOTWIDTH"), 
				colorname(ewalk->newcolor), colorname(ewalk->newcolor));
			fprintf(output, "</TR>\n");
		}

		fprintf(output, "</TABLE>\n");

	}
	else if (output != NULL) {
		/* No events during the past maxminutes */
		if (eventlog)
			sprintf(title, "No events received in the last %d minutes", maxminutes);
		else
			strcpy(title, "No events logged");

		fprintf(output, "<CENTER><BR>\n");
		fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title);
		fprintf(output, "<TR BGCOLOR=\"#333333\">\n");
		fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD>\n", htmlquoted(title));
		fprintf(output, "</TR>\n");
		fprintf(output, "</TABLE>\n");
		fprintf(output, "</CENTER>\n");
	}

	if (eventlog) fclose(eventlog);

	if (pageregexp) pcre_free(pageregexp);
	if (hostregexp) pcre_free(hostregexp);
	if (testregexp) pcre_free(testregexp);
	if (colrregexp) pcre_free(colrregexp);

	/* Return the event- and count-lists, if wanted - or clean them up */
	if (eventlist) {
		*eventlist = eventhead;
	}
	else {
		event_t	*zombie, *ewalk = eventhead;
		while (ewalk) { zombie = ewalk; ewalk = ewalk->next; xfree(zombie); }
	}

	if (hostcounts) {
		*hostcounts = hostcounthead;
	}
	else {
		countlist_t *zombie, *hwalk = hostcounthead;
		while (hwalk) { zombie = hwalk; hwalk = hwalk->next; xfree(zombie); }

	}

	if (servicecounts) {
		*servicecounts = svccounthead;
	}
	else {
		countlist_t *zombie, *swalk = svccounthead;
		while (swalk) { zombie = swalk; swalk = swalk->next; xfree(zombie); }
	}
}
Beispiel #19
0
int loadstatus(int maxprio, time_t maxage, int mincolor, int wantacked)
{
	int xymondresult;
	char *board = NULL;
	char *bol, *eol;
	time_t now;
	char msg[1024];
	int i;
	sendreturn_t *sres;

	sprintf(msg, "xymondboard acklevel=%d fields=hostname,testname,color,lastchange,logtime,validtime,acklist color=%s", critacklevel,colorname(mincolor));
	for (i=mincolor+1; (i < COL_COUNT); i++) sprintf(msg+strlen(msg), ",%s", colorname(i));

	sres = newsendreturnbuf(1, NULL);
	xymondresult = sendmessage(msg, NULL, XYMON_TIMEOUT, sres);
	if (xymondresult != XYMONSEND_OK) {
		freesendreturnbuf(sres);
		errormsg("Unable to fetch current status\n");
		return 1;
	}
	else {
		board = getsendreturnstr(sres, 1);
		freesendreturnbuf(sres);
	}

	now = getcurrenttime(NULL);
	rbstate = rbtNew(name_compare);

	bol = board;
	while (bol && (*bol)) {
		char *endkey;
		RbtStatus status;

		eol = strchr(bol, '\n'); if (eol) *eol = '\0';

		/* Find the config entry */
		endkey = strchr(bol, '|'); if (endkey) endkey = strchr(endkey+1, '|'); 
		if (endkey) {
			critconf_t *cfg;
			char *ackstr, *ackrtimestr, *ackvtimestr, *acklevelstr, *ackbystr, *ackmsgstr;

			*endkey = '\0';
			cfg = get_critconfig(bol, CRITCONF_TIMEFILTER, NULL);
			*endkey = '|';

			if (cfg) {
				hstatus_t *newitem = (hstatus_t *)calloc(1, sizeof(hstatus_t));
				newitem->config     = cfg;
				newitem->hostname   = gettok(bol, "|");
				newitem->testname   = gettok(NULL, "|");
				newitem->color      = parse_color(gettok(NULL, "|"));
				newitem->lastchange = atoi(gettok(NULL, "|"));
				newitem->logtime    = atoi(gettok(NULL, "|"));
				newitem->validtime  = atoi(gettok(NULL, "|"));
				ackstr              = gettok(NULL, "|");
				ackrtimestr = ackvtimestr = acklevelstr = ackbystr = ackmsgstr = NULL;

				if (ackstr) {
					nldecode(ackstr);
					ackrtimestr = strtok(ackstr, ":");
					if (ackrtimestr) ackvtimestr = strtok(NULL, ":");
					if (ackvtimestr) acklevelstr = strtok(NULL, ":");
					if (acklevelstr) ackbystr = strtok(NULL, ":");
					if (ackbystr)    ackmsgstr = strtok(NULL, ":");
				}

				if ( (hostinfo(newitem->hostname) == NULL)  ||
				     (newitem->config->priority > maxprio)  ||
				     ((now - newitem->lastchange) > maxage) ||
				     (newitem->color < mincolor)            ||
				     (ackmsgstr && !wantacked)              ) {
					xfree(newitem);
				}
				else {
					if (ackvtimestr && ackbystr && ackmsgstr) {
						newitem->acktime = atoi(ackvtimestr);
						newitem->ackedby = strdup(ackbystr);
						newitem->ackmsg  = strdup(ackmsgstr);
					}

					newitem->key = (char *)malloc(strlen(newitem->hostname) + strlen(newitem->testname) + 2);
					sprintf(newitem->key, "%s|%s", newitem->hostname, newitem->testname);
					status = rbtInsert(rbstate, newitem->key, newitem);
				}
			}
		}

		bol = (eol ? (eol+1) : NULL);
	}

	return 0;
}
Beispiel #20
0
void send_alert(activealerts_t *alert, FILE *logfd)
{
    recip_t *recip;
    int first = 1;
    int alertcount = 0;
    time_t now = getcurrenttime(NULL);
    /* A_PAGING, A_NORECIP, A_ACKED, A_RECOVERED, A_DISABLED, A_NOTIFY, A_DEAD */
    char *alerttxt[A_DEAD+1] = { "Paging", "Norecip", "Acked", "Recovered", "Disabled", "Notify", "Dead" };

    dbgprintf("send_alert %s:%s state %d\n", alert->hostname, alert->testname, (int)alert->state);
    traceprintf("send_alert %s:%s state %s\n",
                alert->hostname, alert->testname, alerttxt[alert->state]);

    stoprulefound = 0;

    while (!stoprulefound && ((recip = next_recipient(alert, &first, NULL, NULL)) != NULL)) {
        /* If this is an "UNMATCHED" rule, ignore it if we have already sent out some alert */
        if (recip->unmatchedonly && (alertcount != 0)) {
            traceprintf("Recipient '%s' dropped, not unmatched (count=%d)\n", recip->recipient, alertcount);
            continue;
        }

        if (recip->noalerts && ((alert->state == A_PAGING) || (alert->state == A_RECOVERED) || (alert->state == A_DISABLED))) {
            traceprintf("Recipient '%s' dropped (NOALERT)\n", recip->recipient);
            continue;
        }

        if (recip->method == M_IGNORE) {
            traceprintf("IGNORE rule found\n");
            continue;
        }

        if (alert->state == A_PAGING) {
            repeat_t *rpt = NULL;

            /*
             * This runs in a child-process context, so the record we
             * might create here is NOT used later on.
             */
            rpt = find_repeatinfo(alert, recip, 1);
            if (!rpt) continue;	/* Happens for e.g. M_IGNORE recipients */

            dbgprintf("  repeat %s at %d\n", rpt->recipid, rpt->nextalert);
            if (rpt->nextalert > now) {
                traceprintf("Recipient '%s' dropped, next alert due at %ld > %ld\n",
                            rpt->recipid, (long)rpt->nextalert, (long)now);
                continue;
            }
            alertcount++;
        }
        else if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
            /* RECOVERED messages require that we've sent out an alert before */
            repeat_t *rpt = NULL;

            rpt = find_repeatinfo(alert, recip, 0);
            if (!rpt) continue;
            alertcount++;
        }

        dbgprintf("  Alert for %s:%s to %s\n", alert->hostname, alert->testname, recip->recipient);
        switch (recip->method) {
        case M_IGNORE:
            break;

        case M_MAIL:
        {
            char cmd[32768];
            char *mailsubj;
            char *mailrecip;
            FILE *mailpipe;

            MEMDEFINE(cmd);

            mailsubj = message_subject(alert, recip);
            mailrecip = message_recipient(recip->recipient, alert->hostname, alert->testname, colorname(alert->color));

            if (mailsubj) {
                if (xgetenv("MAIL"))
                    sprintf(cmd, "%s \"%s\" ", xgetenv("MAIL"), mailsubj);
                else if (xgetenv("MAILC"))
                    sprintf(cmd, "%s -s \"%s\" ", xgetenv("MAILC"), mailsubj);
                else
                    sprintf(cmd, "mail -s \"%s\" ", mailsubj);
            }
            else {
                if (xgetenv("MAILC"))
                    sprintf(cmd, "%s ", xgetenv("MAILC"));
                else
                    sprintf(cmd, "mail ");
            }
            strcat(cmd, mailrecip);

            traceprintf("Mail alert with command '%s'\n", cmd);
            if (testonly) {
                MEMUNDEFINE(cmd);
                break;
            }

            mailpipe = popen(cmd, "w");
            if (mailpipe) {
                fprintf(mailpipe, "%s", message_text(alert, recip));
                pclose(mailpipe);
                if (logfd) {
                    init_timestamp();
                    fprintf(logfd, "%s %s.%s (%s) %s[%d] %ld %d",
                            timestamp, alert->hostname, alert->testname,
                            alert->ip, mailrecip, recip->cfid,
                            (long)now, servicecode(alert->testname));
                    if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
                        fprintf(logfd, " %ld\n", (long)(now - alert->eventstart));
                    }
                    else {
                        fprintf(logfd, "\n");
                    }
                    fflush(logfd);
                }
            }
            else {
                errprintf("ERROR: Cannot open command pipe for '%s' - alert lost!\n", cmd);
                traceprintf("Mail pipe failed - alert lost\n");
            }

            MEMUNDEFINE(cmd);
        }
        break;

        case M_SCRIPT:
        {
            pid_t scriptpid;
            char *scriptrecip;

            traceprintf("Script alert with command '%s' and recipient %s\n", recip->scriptname, recip->recipient);
            if (testonly) break;

            scriptrecip = message_recipient(recip->recipient, alert->hostname, alert->testname, colorname(alert->color));
            scriptpid = fork();
            if (scriptpid == 0) {
                /* Setup all of the environment for a paging script */
                void *hinfo;
                char *p;
                int ip1=0, ip2=0, ip3=0, ip4=0;
                char *bbalphamsg, *ackcode, *rcpt, *bbhostname, *bbhostsvc, *bbhostsvccommas, *bbnumeric, *machip, *bbsvcname, *bbsvcnum, *bbcolorlevel, *recovered, *downsecs, *eventtstamp, *downsecsmsg, *cfidtxt;
                char *alertid, *alertidenv;
                int msglen;

                cfidtxt = (char *)malloc(strlen("CFID=") + 10);
                sprintf(cfidtxt, "CFID=%d", recip->cfid);
                putenv(cfidtxt);

                p = message_text(alert, recip);
                msglen = strlen(p);
                if (msglen > MAX_ALERTMSG_SCRIPTS) {
                    dbgprintf("Cropping large alert message from %d to %d bytes\n", msglen, MAX_ALERTMSG_SCRIPTS);
                    msglen = MAX_ALERTMSG_SCRIPTS;
                }
                msglen += strlen("BBALPHAMSG=");
                bbalphamsg = (char *)malloc(msglen + 1);
                snprintf(bbalphamsg, msglen+1, "BBALPHAMSG=%s", p);
                putenv(bbalphamsg);

                ackcode = (char *)malloc(strlen("ACKCODE=") + 10);
                sprintf(ackcode, "ACKCODE=%d", alert->cookie);
                putenv(ackcode);

                rcpt = (char *)malloc(strlen("RCPT=") + strlen(scriptrecip) + 1);
                sprintf(rcpt, "RCPT=%s", scriptrecip);
                putenv(rcpt);

                bbhostname = (char *)malloc(strlen("BBHOSTNAME=") + strlen(alert->hostname) + 1);
                sprintf(bbhostname, "BBHOSTNAME=%s", alert->hostname);
                putenv(bbhostname);

                bbhostsvc = (char *)malloc(strlen("BBHOSTSVC=") + strlen(alert->hostname) + 1 + strlen(alert->testname) + 1);
                sprintf(bbhostsvc, "BBHOSTSVC=%s.%s", alert->hostname, alert->testname);
                putenv(bbhostsvc);

                bbhostsvccommas = (char *)malloc(strlen("BBHOSTSVCCOMMAS=") + strlen(alert->hostname) + 1 + strlen(alert->testname) + 1);
                sprintf(bbhostsvccommas, "BBHOSTSVCCOMMAS=%s.%s", commafy(alert->hostname), alert->testname);
                putenv(bbhostsvccommas);

                bbnumeric = (char *)malloc(strlen("BBNUMERIC=") + 22 + 1);
                p = bbnumeric;
                p += sprintf(p, "BBNUMERIC=");
                p += sprintf(p, "%03d", servicecode(alert->testname));
                sscanf(alert->ip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
                p += sprintf(p, "%03d%03d%03d%03d", ip1, ip2, ip3, ip4);
                p += sprintf(p, "%d", alert->cookie);
                putenv(bbnumeric);

                machip = (char *)malloc(strlen("MACHIP=") + 13);
                sprintf(machip, "MACHIP=%03d%03d%03d%03d", ip1, ip2, ip3, ip4);
                putenv(machip);

                bbsvcname = (char *)malloc(strlen("BBSVCNAME=") + strlen(alert->testname) + 1);
                sprintf(bbsvcname, "BBSVCNAME=%s", alert->testname);
                putenv(bbsvcname);

                bbsvcnum = (char *)malloc(strlen("BBSVCNUM=") + 10);
                sprintf(bbsvcnum, "BBSVCNUM=%d", servicecode(alert->testname));
                putenv(bbsvcnum);

                bbcolorlevel = (char *)malloc(strlen("BBCOLORLEVEL=") + strlen(colorname(alert->color)) + 1);
                sprintf(bbcolorlevel, "BBCOLORLEVEL=%s", colorname(alert->color));
                putenv(bbcolorlevel);

                recovered = (char *)malloc(strlen("RECOVERED=") + 2);
                switch (alert->state) {
                case A_RECOVERED:
                    strcpy(recovered, "RECOVERED=1");
                    break;
                case A_DISABLED:
                    strcpy(recovered, "RECOVERED=2");
                    break;
                default:
                    strcpy(recovered, "RECOVERED=0");
                    break;
                }
                putenv(recovered);

                downsecs = (char *)malloc(strlen("DOWNSECS=") + 20);
                sprintf(downsecs, "DOWNSECS=%ld", (long)(getcurrenttime(NULL) - alert->eventstart));
                putenv(downsecs);

                eventtstamp = (char *)malloc(strlen("EVENTSTART=") + 20);
                sprintf(eventtstamp, "EVENTSTART=%ld", (long)alert->eventstart);
                putenv(eventtstamp);

                if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
                    downsecsmsg = (char *)malloc(strlen("DOWNSECSMSG=Event duration :") + 20);
                    sprintf(downsecsmsg, "DOWNSECSMSG=Event duration : %ld", (long)(getcurrenttime(NULL) - alert->eventstart));
                }
                else {
                    downsecsmsg = strdup("DOWNSECSMSG=");
                }
                putenv(downsecsmsg);

                alertid = make_alertid(alert->hostname, alert->testname, alert->eventstart);
                alertidenv = (char *)malloc(strlen("ALERTID=") + strlen(alertid) + 10);
                sprintf(alertidenv, "ALERTID=%s", alertid);
                putenv(alertidenv);

                hinfo = hostinfo(alert->hostname);
                if (hinfo) {
                    enum xmh_item_t walk;
                    char *itm, *id, *bbhenv;

                    for (walk = 0; (walk < XMH_LAST); walk++) {
                        itm = xmh_item(hinfo, walk);
                        id = xmh_item_id(walk);
                        if (itm && id) {
                            bbhenv = (char *)malloc(strlen(id) + strlen(itm) + 2);
                            sprintf(bbhenv, "%s=%s", id, itm);
                            putenv(bbhenv);
                        }
                    }
                }

                /* The child starts the script */
                execlp(recip->scriptname, recip->scriptname, NULL);
                errprintf("Could not launch paging script %s: %s\n",
                          recip->scriptname, strerror(errno));
                exit(0);
            }
            else if (scriptpid > 0) {
                /* Parent waits for child to complete */
                int childstat;

                wait(&childstat);
                if (WIFEXITED(childstat) && (WEXITSTATUS(childstat) != 0)) {
                    errprintf("Paging script %s terminated with status %d\n",
                              recip->scriptname, WEXITSTATUS(childstat));
                }
                else if (WIFSIGNALED(childstat)) {
                    errprintf("Paging script %s terminated by signal %d\n",
                              recip->scriptname, WTERMSIG(childstat));
                }

                if (logfd) {
                    init_timestamp();
                    fprintf(logfd, "%s %s.%s (%s) %s %ld %d",
                            timestamp, alert->hostname, alert->testname,
                            alert->ip, scriptrecip, (long)now,
                            servicecode(alert->testname));
                    if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
                        fprintf(logfd, " %ld\n", (long)(now - alert->eventstart));
                    }
                    else {
                        fprintf(logfd, "\n");
                    }
                    fflush(logfd);
                }
            }
            else {
                errprintf("ERROR: Fork failed to launch script '%s' - alert lost\n", recip->scriptname);
                traceprintf("Script fork failed - alert lost\n");
            }
        }
        break;
        }
    }
}
Beispiel #21
0
static void count_duration(time_t fromtime, time_t totime,
			   pcre *pageregexp, pcre *expageregexp,
			   pcre *hostregexp, pcre *exhostregexp,
			   pcre *testregexp, pcre *extestregexp,
			   int ignoredialups, f_hostcheck hostcheck,
			   event_t *eventhead, countlist_t **hostcounthead, countlist_t **svccounthead)
{
	void *hwalk;
	elist_t *lwalk;
	event_t *ewalk;
	ed_t *ed;
	sendreturn_t *bdata;

	/*
	 * Restructure the event-list so we have a tree instead:
	 *
	 *      HostRecord
	 *      |  *Data ---->  EventList
	 *      |               |  *Service
	 *      |               |  *EventHead --> Event --> Event --> Event
	 *      |               |  *EventTail --------------------------^
	 *      |               |
	 *      |               v
	 *      |
	 *      v
	 *
	 */
	for (ewalk = eventhead; (ewalk); ewalk = ewalk->next) {
		lwalk = (elist_t *)xmh_item(ewalk->host, XMH_DATA);
		while (lwalk && (lwalk->svc != ewalk->service)) lwalk = lwalk->next;
		if (lwalk == NULL) {
			lwalk = (elist_t *)calloc(1, sizeof(elist_t));
			lwalk->svc = ewalk->service;
			lwalk->next = (elist_t *)xmh_item(ewalk->host, XMH_DATA);
			xmh_set_item(ewalk->host, XMH_DATA, (void *)lwalk);
		}

		ed = (ed_t *)calloc(1, sizeof(ed_t));
		ed->event = ewalk;
		ed->next = lwalk->head;
		if (lwalk->head == NULL) lwalk->tail = ed;
		lwalk->head = ed;
	}

	if (debug) {
		printf("\n\nEventtree before fixups\n\n");
		dump_eventtree();
	}
	
	/* 
	 * Next, we must add a pseudo record for the current state.
	 * This is for those statuses that haven't changed since the 
	 * start of our data-collection period - they won't have any events
	 * so we cannot tell what color they are. By grabbing the current
	 * color we can add a pseudo-event that lets us determine what the 
	 * color has been since the start of the event-period.
	 */
	bdata = newsendreturnbuf(1, NULL);
	if (sendmessage("xymondboard fields=hostname,testname,color,lastchange", NULL, XYMON_TIMEOUT, bdata) == XYMONSEND_OK) {
		char *bol, *eol;
		char *hname, *tname;
		int color;
		time_t lastchange;
		void *hrec;
		htnames_t *srec;
		char *icname = xgetenv("INFOCOLUMN");
		char *tcname = xgetenv("TRENDSCOLUMN");

		bol = getsendreturnstr(bdata, 0);
		while (bol) {
			eol = strchr(bol, '\n'); if (eol) *eol = '\0';
			hname = strtok(bol, "|");
			tname = (hname ? strtok(NULL, "|") : NULL);
			color = (tname ? parse_color(strtok(NULL, "|")) : -1);
			lastchange = ((color != -1) ? atol(strtok(NULL, "\n")) : totime+1);

			if (hname && tname && (color != -1) && (strcmp(tname, icname) != 0) && (strcmp(tname, tcname) != 0)) {
				hrec = hostinfo(hname);
				srec = getname(tname, 1);

				if (eventfilter(hrec, tname, 
						pageregexp, expageregexp, 
						hostregexp, exhostregexp,
						testregexp, extestregexp,
						ignoredialups, hostcheck) == 0) goto nextrecord;

				lwalk = (elist_t *)xmh_item(hrec, XMH_DATA);
				while (lwalk && (lwalk->svc != srec)) lwalk = lwalk->next;
				if (lwalk == NULL) {
					lwalk = (elist_t *)calloc(1, sizeof(elist_t));
					lwalk->svc = srec;
					lwalk->next = (elist_t *)xmh_item(hrec, XMH_DATA);
					xmh_set_item(hrec, XMH_DATA, (void *)lwalk);
				}

				/* See if we already have an event past the "totime" value */
				if (lwalk->head) {
					ed = lwalk->head;
					while (ed && (ed->event->eventtime < totime)) ed = ed->next;

					if (ed) {
						ed->next = NULL;
						lwalk->tail = ed;
					}
					else {
						ed = (ed_t *)calloc(1, sizeof(ed_t));
						ed->event = (event_t *)calloc(1, sizeof(event_t));
						lwalk->tail->next = ed;

						ed->event->host = hrec;
						ed->event->service = srec;
						ed->event->eventtime = totime;
						ed->event->changetime = lwalk->tail->event->eventtime;
						ed->event->duration = (totime - lwalk->tail->event->eventtime);
						ed->event->newcolor = -1;
						ed->event->oldcolor = lwalk->tail->event->newcolor;
						ed->event->next = NULL;
						ed->next = NULL;

						lwalk->tail = ed;
					}
				}
				else if (lastchange < totime) {
					ed = (ed_t *)calloc(1, sizeof(ed_t));
					ed->event = (event_t *)calloc(1, sizeof(event_t));
					ed->event->host = hrec;
					ed->event->service = srec;
					ed->event->eventtime = totime;
					ed->event->changetime = (lwalk->tail ? lwalk->tail->event->eventtime : fromtime);
					ed->event->duration = (totime - ed->event->changetime);
					ed->event->newcolor = color;
					ed->event->oldcolor = (lwalk->tail ? lwalk->tail->event->newcolor : color);
					ed->event->next = NULL;
					ed->next = NULL;

					lwalk->head = lwalk->tail = ed;
				}
			}

nextrecord:
			bol = (eol ? eol+1 : NULL);
		}

		freesendreturnbuf(bdata);
	}
	else {
		errprintf("Cannot get the current state\n");
		freesendreturnbuf(bdata);
		return;
	}

	if (debug) {
		printf("\n\nEventtree after pseudo-events\n\n");
		dump_eventtree();
	}
	
	/* 
	 * Fixup the beginning-time (and duration) of the first events recorded.
	 * This is to handle events that begin BEFORE our event-logging period.
	 * Fixup the end-time (and duration) of the last events recorded.
	 * This is to handle events that end AFTER our event-logging period.
	 */
	for (hwalk = first_host(); (hwalk); hwalk = next_host(hwalk, 0)) {
		elist_t *lwalk;
		event_t *erec;
		ed_t *ewalk;

		lwalk = (elist_t *)xmh_item(hwalk, XMH_DATA); 
		while (lwalk) {
			if (lwalk->head) {
				erec = lwalk->head->event;
				if (erec->changetime > totime) {
					/* First event is after our start-time. Drop the events */
					lwalk->head = lwalk->tail = NULL;
				}
				else if (erec->changetime < fromtime) {
					/* First event is before our start-time. Adjust to starttime. */
					erec->changetime = fromtime;
					erec->duration = (erec->eventtime - fromtime);
				}

				ewalk = lwalk->head;
				while (ewalk && (ewalk->event->eventtime < totime)) ewalk = ewalk->next;
				if (ewalk) {
					lwalk->tail = ewalk;
					lwalk->tail->next = 0;
				}

				if (lwalk->tail) {
					erec = lwalk->tail->event;
					if (erec->eventtime > totime) {
						/* Last event is after our end-time. Adjust to end-time */
						erec->eventtime = totime;
						erec->duration = (totime - erec->changetime);
					}
				}
			}

			lwalk = lwalk->next;
		}
	}

	if (debug) {
		printf("\n\nEventtree after fixups\n\n");
		dump_eventtree();
	}

	for (hwalk = first_host(); (hwalk); hwalk = next_host(hwalk, 0)) {
		countlist_t *hrec, *srec;

		hrec = (countlist_t *)malloc(sizeof(countlist_t));
		hrec->src = hwalk;
		hrec->total = 0;
		hrec->next = *hostcounthead;
		*hostcounthead = hrec;

		lwalk = (elist_t *)xmh_item(hwalk, XMH_DATA);
		while (lwalk) {
			for (srec = *svccounthead; (srec && (srec->src != (void *)lwalk->svc)); srec = srec->next) ;
			if (!srec) {
				srec = (countlist_t *)malloc(sizeof(countlist_t));
				srec->src = (void *)lwalk->svc;
				srec->total = 0;
				srec->next = *svccounthead;
				*svccounthead = srec;
			}

			if (lwalk->head) {
				ed_t *ewalk = lwalk->head;

				while (ewalk) {
					if (ewalk->event->oldcolor >= COL_YELLOW) {
						hrec->total += ewalk->event->duration;
						srec->total += ewalk->event->duration;
					}
					ewalk = ewalk->next;
				}
			}

			lwalk = lwalk->next;
		}
	}

	if (debug) dump_countlists(*hostcounthead, *svccounthead);
}
Beispiel #22
0
void do_acknowledgementslog(FILE *output, 
		  int maxcount, int maxminutes, char *fromtime, char *totime, 
		  char *pageregex, char *expageregex,
		  char *hostregex, char *exhostregex,
		  char *testregex, char *extestregex,
		  char *rcptregex, char *exrcptregex)
{
	FILE *acknowledgementslog;
	char acknowledgementslogfilename[PATH_MAX];
	time_t firstevent = 0;
	time_t lastevent = getcurrenttime(NULL);
	acknowledgements_t *head, *walk;
	struct stat st;
	char l[MAX_LINE_LEN];
	char title[200];

	/* For the PCRE matching */
	const char *errmsg = NULL;
	int errofs = 0;
	pcre *pageregexp = NULL;
	pcre *expageregexp = NULL;
	pcre *hostregexp = NULL;
	pcre *exhostregexp = NULL;
	pcre *testregexp = NULL;
	pcre *extestregexp = NULL;
	pcre *rcptregexp = NULL;
	pcre *exrcptregexp = NULL;

	if (maxminutes && (fromtime || totime)) {
		fprintf(output, "<B>Only one time interval type is allowed!</B>");
		return;
	}

	if (fromtime) {
		firstevent = convert_time(fromtime);
		if(firstevent < 0) {
			fprintf(output,"<B>Invalid 'from' time: %s</B>", htmlquoted(fromtime));
			return;
		}
	}
	else if (maxminutes) {
		firstevent = getcurrenttime(NULL) - maxminutes*60;
	}
	else {
		firstevent = getcurrenttime(NULL) - 86400;
	}

	if (totime) {
		lastevent = convert_time(totime);
		if (lastevent < 0) {
			fprintf(output,"<B>Invalid 'to' time: %s</B>", htmlquoted(totime));
			return;
		}
		if (lastevent < firstevent) {
			fprintf(output,"<B>'to' time must be after 'from' time.</B>");
			return;
		}
	}

	if (!maxcount) maxcount = 100;

	if (pageregex && *pageregex) pageregexp = pcre_compile(pageregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (expageregex && *expageregex) expageregexp = pcre_compile(expageregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (hostregex && *hostregex) hostregexp = pcre_compile(hostregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (exhostregex && *exhostregex) exhostregexp = pcre_compile(exhostregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (testregex && *testregex) testregexp = pcre_compile(testregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (extestregex && *extestregex) extestregexp = pcre_compile(extestregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (rcptregex && *rcptregex) rcptregexp = pcre_compile(rcptregex, PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (exrcptregex && *exrcptregex) exrcptregexp = pcre_compile(exrcptregex, PCRE_CASELESS, &errmsg, &errofs, NULL);

	sprintf(acknowledgementslogfilename, "%s/acknowledge.log", xgetenv("XYMONSERVERLOGS"));
	acknowledgementslog = fopen(acknowledgementslogfilename, "r");

	if (acknowledgementslog && (stat(acknowledgementslogfilename, &st) == 0)) {
		time_t curtime;
		int done = 0;

		/* Find a spot in the acknowledgements log file close to where the firstevent time is */
		fseeko(acknowledgementslog, 0, SEEK_END);
		do {
			/* Go back maxcount*80 bytes - one entry is ~80 bytes */
			if (ftello(acknowledgementslog) > maxcount*80) {
				unsigned int uicurtime;
				fseeko(acknowledgementslog, -maxcount*80, SEEK_CUR); 
				if (fgets(l, sizeof(l), acknowledgementslog) && /* Skip to start of line */
				    fgets(l, sizeof(l), acknowledgementslog)) {
                                        /* 2015-03-07 18:17:03 myserver disk andy 1 1425724570 1425752223 1425838623 testing message */
					if ( sscanf(l, "%*u-%*u-%*u %*u:%*u:%*u %*s %*s %*s %*u %*u %u %*u %*s", &uicurtime) == 0 ) {
					    /* that didnt work - try the old format
						1430040985      630949  30      630949  np_filename_not_used    myserver.procs red     testing log format \nAcked by: andy (127.0.0.1) */
					    sscanf(l, "%u\t%*u\t%*u\t%*u\tnp_filename_not_used\t%*s\t%*s\t%*s", &uicurtime);
					}
					curtime = uicurtime;
					done = (curtime < firstevent);
				}
				else { 
					fprintf(output, "Error reading logfile %s: %s\n", acknowledgementslogfilename, strerror(errno));
					return;
				}
			}
			else {
				rewind(acknowledgementslog);
				done = 1;
			}
		} while (!done);
	}
	
	head = NULL;

	while (acknowledgementslog && (fgets(l, sizeof(l), acknowledgementslog))) {

		unsigned int etim;
		unsigned int valid;
		int duration;
		time_t eventtime;
		time_t validity;
		char host[MAX_LINE_LEN];
		char svc[MAX_LINE_LEN];
		char recipient[MAX_LINE_LEN];
		char message[MAX_LINE_LEN];
		char *hostname, *svcname, *p;
		int itemsfound, pagematch, hostmatch, testmatch, rcptmatch;
		acknowledgements_t *newrec;
		void *eventhost;
		struct htnames_t *eventcolumn;
		int ovector[30];

                /* 2015-03-07 18:17:03 myserver disk andy 1 1425724570 1425752223 1425838623 testing message */
		itemsfound = sscanf(l, "%*u-%*u-%*u %*u:%*u:%*u %s %s %s %*u %*u %u %u %[^\t\n]", host, svc, recipient, &etim, &valid, message);
		if (itemsfound != 6) {
		    /* 1430040985      630949  30      630949  np_filename_not_used    myserver.procs red     testing log format \nAcked by: andy (127.0.0.1) */
		    itemsfound = sscanf(l, "%u\t%*u\t%d\t%*u\tnp_filename_not_used\t%s\t%*s\t%[^\n]", &etim, &duration, host, message);
		    if (itemsfound != 4) continue;
		    p = strrchr(host, '.');
		    if (p) {
                        *p = '\0';
			strcpy(svc,p+1);
                    }
		    /* Xymon uses \n in the ack message, for the "acked by" data. Cut it off. */
		    p = strstr(message, "\\nAcked by:");
		    if (p) {
			strcpy(recipient,p+12);
                        *(p-1) = '\0';
		    }
		    else {
			strcpy(recipient,"UnknownUser");
                    }
		    p = strchr(recipient, '('); if (p) *(p-1) = '\0';
                }
		eventtime = etim;
		if (eventtime < firstevent) continue;
		if (eventtime > lastevent) break;

		validity = duration ? (etim + duration * 60) : valid;

		hostname = host; svcname = svc;
		eventhost = hostinfo(hostname);
		if (!eventhost) continue; /* Dont report hosts that no longer exist */
		eventcolumn = getname(svcname, 1);

		p = strchr(recipient, '['); if (p) *p = '\0';

		if (pageregexp) {
			char *pagename;

			pagename = xmh_item_multi(eventhost, XMH_PAGEPATH);
			pagematch = 0;
			while (!pagematch && pagename) {
			pagematch = (pcre_exec(pageregexp, NULL, pagename, strlen(pagename), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
				pagename = xmh_item_multi(NULL, XMH_PAGEPATH);
			}
		}
		else
			pagematch = 1;
		if (!pagematch) continue;

		if (expageregexp) {
			char *pagename;

			pagename = xmh_item_multi(eventhost, XMH_PAGEPATH);
			pagematch = 0;
			while (!pagematch && pagename) {
			pagematch = (pcre_exec(expageregexp, NULL, pagename, strlen(pagename), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
				pagename = xmh_item_multi(NULL, XMH_PAGEPATH);
			}
		}
		else
			pagematch = 0;
		if (pagematch) continue;

		if (hostregexp)
			hostmatch = (pcre_exec(hostregexp, NULL, hostname, strlen(hostname), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			hostmatch = 1;
		if (!hostmatch) continue;

		if (exhostregexp)
			hostmatch = (pcre_exec(exhostregexp, NULL, hostname, strlen(hostname), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			hostmatch = 0;
		if (hostmatch) continue;

		if (testregexp)
			testmatch = (pcre_exec(testregexp, NULL, svcname, strlen(svcname), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			testmatch = 1;
		if (!testmatch) continue;

		if (extestregexp)
			testmatch = (pcre_exec(extestregexp, NULL, svcname, strlen(svcname), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			testmatch = 0;
		if (testmatch) continue;

		if (rcptregexp)
			rcptmatch = (pcre_exec(rcptregexp, NULL, recipient, strlen(recipient), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			rcptmatch = 1;
		if (!rcptmatch) continue;

		if (exrcptregexp)
			rcptmatch = (pcre_exec(exrcptregexp, NULL, recipient, strlen(recipient), 0, 0, 
					ovector, (sizeof(ovector)/sizeof(int))) >= 0);
		else
			rcptmatch = 0;
		if (rcptmatch) continue;

		newrec = (acknowledgements_t *) malloc(sizeof(acknowledgements_t));
		newrec->host       = eventhost;
		newrec->service    = eventcolumn;
		newrec->eventtime  = eventtime;
		newrec->validity   = validity;
		newrec->recipient  = strdup(recipient);
		newrec->message  = strdup(message);
		newrec->next       = head;
		head = newrec;
	}

	if (head) {
		char *bgcolors[2] = { "#000000", "#000066" };
		int  bgcolor = 0;
		int  count;
		struct acknowledgements_t *lasttoshow = head;

		count=0;
		walk=head; 
		do {
			count++;
			lasttoshow = walk;
			walk = walk->next;
		} while (walk && (count<maxcount));

		if (maxminutes)  { 
			sprintf(title, "%d acknowledgements in the past %u minutes", 
				count, (unsigned int)((getcurrenttime(NULL) - lasttoshow->eventtime) / 60));
		}
		else {
			sprintf(title, "%d events acknowledged.", count);
		}

		fprintf(output, "<BR><BR>\n");
		fprintf(output, "<TABLE SUMMARY=\"Acknowledgements log\" BORDER=0>\n");
		fprintf(output, "<TR BGCOLOR=\"#333333\">\n");
		fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", htmlquoted(title));
		fprintf(output, "<TR BGCOLOR=\"#333333\"><TH>Time</TH><TH>Valid Until</TH><TH>Host</TH><TH>Service</TH><TH>Acknowledged By</TH><TH>Message</TH></TR>\n");

		for (walk=head; (walk != lasttoshow->next); walk=walk->next) {
			char *hostname = xmh_item(walk->host, XMH_HOSTNAME);

			fprintf(output, "<TR BGCOLOR=%s>\n", bgcolors[bgcolor]);
			bgcolor = ((bgcolor + 1) % 2);

			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", ctime(&walk->eventtime));
			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", ctime(&walk->validity));

			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", hostname);
			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->service->name);
			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->recipient);
			fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->message);
		}

		fprintf(output, "</TABLE>\n");

		/* Clean up */
		walk = head;
		do {
			struct acknowledgements_t *tmp = walk;

			walk = walk->next;
			xfree(tmp->recipient);
			xfree(tmp->message);
			xfree(tmp);
		} while (walk);
	}
	else {
		/* No acknowledgements during the past maxminutes */
		if (acknowledgementslog)
			sprintf(title, "No events acknowledged in the last %d minutes", maxminutes);
		else
			strcpy(title, "No acknowledgements logged");

		fprintf(output, "<CENTER><BR>\n");
		fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title);
		fprintf(output, "<TR BGCOLOR=\"#333333\">\n");
		fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD>\n", htmlquoted(title));
		fprintf(output, "</TR>\n");
		fprintf(output, "</TABLE>\n");
		fprintf(output, "</CENTER>\n");
	}

	if (acknowledgementslog) fclose(acknowledgementslog);

	if (pageregexp)   pcre_free(pageregexp);
	if (expageregexp) pcre_free(expageregexp);
	if (hostregexp)   pcre_free(hostregexp);
	if (exhostregexp) pcre_free(exhostregexp);
	if (testregexp)   pcre_free(testregexp);
	if (extestregexp) pcre_free(extestregexp);
	if (rcptregexp)   pcre_free(rcptregexp);
	if (exrcptregexp) pcre_free(exrcptregexp);
}
Beispiel #23
0
static void print_host(hostlist_t *host, htnames_t *testnames[], int testcount)
{
    int testi, rowcount, netcount;
    void *hinfo = hostinfo(host->hostname);
    char *dispname = NULL, *clientalias = NULL, *comment = NULL, *description = NULL, *pagepathtitle = NULL;
    char *net = NULL, *nkalerts = NULL;
    char *nktime = NULL, *downtime = NULL, *reporttime = NULL;
    char *itm;
    tag_t *taghead = NULL;
    int contidx = 0, haveping = 0;
    char contcol[1024];
    activealerts_t *alert;
    strbuffer_t *buf = newstrbuffer(0);

    fprintf(stdout, "<p style=\"page-break-before: always\">\n");
    fprintf(stdout, "<table width=\"100%%\" border=1 summary=\"%s configuration\">\n", host->hostname);

    pagepathtitle = bbh_item(hinfo, BBH_PAGEPATHTITLE);
    if (!pagepathtitle || (strlen(pagepathtitle) == 0)) pagepathtitle = "Top page";
    dispname = bbh_item(hinfo, BBH_DISPLAYNAME);
    if (dispname && (strcmp(dispname, host->hostname) == 0)) dispname = NULL;
    clientalias = bbh_item(hinfo, BBH_CLIENTALIAS);
    if (clientalias && (strcmp(clientalias, host->hostname) == 0)) clientalias = NULL;
    comment = bbh_item(hinfo, BBH_COMMENT);
    description = bbh_item(hinfo, BBH_DESCRIPTION);
    net = bbh_item(hinfo, BBH_NET);
    nkalerts = bbh_item(hinfo, BBH_NK);
    nktime = bbh_item(hinfo, BBH_NKTIME);
    if (!nktime) nktime = "24x7";
    else nktime = strdup(timespec_text(nktime));
    downtime = bbh_item(hinfo, BBH_DOWNTIME);
    if (downtime) downtime = strdup(timespec_text(downtime));
    reporttime = bbh_item(hinfo, BBH_REPORTTIME);
    if (!reporttime) reporttime = "24x7";
    else reporttime = strdup(timespec_text(reporttime));

    rowcount = 1;
    if (pagepathtitle) rowcount++;
    if (dispname || clientalias) rowcount++;
    if (comment) rowcount++;
    if (description) rowcount++;
    if (!newnkconfig && nktime) rowcount++;
    if (downtime) rowcount++;
    if (reporttime) rowcount++;

    fprintf(stdout, "<tr>\n");
    fprintf(stdout, "<th rowspan=%d align=left width=\"25%%\" valign=top>Basics</th>\n", rowcount);
    fprintf(stdout, "<th align=center>%s (%s)</th>\n",
            (dispname ? dispname : host->hostname), bbh_item(hinfo, BBH_IP));
    fprintf(stdout, "</tr>\n");

    if (dispname || clientalias) {
        fprintf(stdout, "<tr><td>Aliases:");
        if (dispname) fprintf(stdout, " %s", dispname);
        if (clientalias) fprintf(stdout, " %s", clientalias);
        fprintf(stdout, "</td></tr>\n");
    }
    if (pagepathtitle) fprintf(stdout, "<tr><td>Monitoring location: %s</td></tr>\n", pagepathtitle);
    if (comment) fprintf(stdout, "<tr><td>Comment: %s</td></tr>\n", comment);
    if (description) fprintf(stdout, "<tr><td>Description: %s</td></tr>\n", description);
    if (!newnkconfig && nktime) fprintf(stdout, "<tr><td>NK monitoring period: %s</td></tr>\n", nktime);
    if (downtime) fprintf(stdout, "<tr><td>Planned downtime: %s</td></tr>\n", downtime);
    if (reporttime) fprintf(stdout, "<tr><td>SLA Reporting Period: %s</td></tr>\n", reporttime);


    /* Build a list of the network tests */
    itm = bbh_item_walk(hinfo);
    while (itm) {
        char *visdata = NULL, *colname = NULL, *expdata = NULL;
        bburl_t bu;
        int dialuptest = 0, reversetest = 0, alwaystruetest = 0, httpextra = 0;

        if (*itm == '?') {
            dialuptest=1;
            itm++;
        }
        if (*itm == '!') {
            reversetest=1;
            itm++;
        }
        if (*itm == '~') {
            alwaystruetest=1;
            itm++;
        }

        if ( argnmatch(itm, "http")         ||
                argnmatch(itm, "content=http") ||
                argnmatch(itm, "cont;http")    ||
                argnmatch(itm, "cont=")        ||
                argnmatch(itm, "nocont;http")  ||
                argnmatch(itm, "nocont=")      ||
                argnmatch(itm, "post;http")    ||
                argnmatch(itm, "post=")        ||
                argnmatch(itm, "nopost;http")  ||
                argnmatch(itm, "nopost=")      ||
                argnmatch(itm, "type;http")    ||
                argnmatch(itm, "type=")        ) {
            visdata = decode_url(itm, &bu);
            colname = bu.columnname;
            if (!colname) {
                if (bu.expdata) {
                    httpextra = 1;
                    if (contidx == 0) {
                        colname = "content";
                        contidx++;
                    }
                    else {
                        sprintf(contcol, "content%d", contidx);
                        colname = contcol;
                        contidx++;
                    }
                }
                else {
                    colname = "http";
                }
            }
            expdata = bu.expdata;
        }
        else if (strncmp(itm, "rpc=", 4) == 0) {
            colname = "rpc";
            visdata = strdup(itm+4);
        }
        else if (strncmp(itm, "dns=", 4) == 0) {
            colname = "dns";
            visdata = strdup(itm+4);
        }
        else if (strncmp(itm, "dig=", 4) == 0) {
            colname = "dns";
            visdata = strdup(itm+4);
        }
        else if (strncmp(itm, pingplus, strlen(pingplus)) == 0) {
            haveping = 1;
            colname = pingcolumn;
            visdata = strdup(itm+strlen(pingplus));
        }
        else if (is_net_test(itm)) {
            colname = strdup(itm);
        }


        if (colname) {
            tag_t *newitem;

addtolist:
            for (newitem = taghead; (newitem && strcmp(newitem->columnname, colname)); newitem = newitem->next);

            if (!newitem) {
                newitem = (tag_t *)calloc(1, sizeof(tag_t));
                newitem->columnname = strdup(colname);
                newitem->visualdata = (visdata ? strdup(visdata) : NULL);
                newitem->expdata = (expdata ? strdup(expdata) : NULL);
                newitem->next = taghead;
                taghead = newitem;
            }
            else {
                /* Multiple tags for one column - must be http */
                newitem->visualdata = (char *)realloc(newitem->visualdata, strlen(newitem->visualdata) + strlen(visdata) + 5);
                strcat(newitem->visualdata, "<br>");
                strcat(newitem->visualdata, visdata);
            }

            if (httpextra) {
                httpextra = 0;
                colname = "http";
                expdata = NULL;
                goto addtolist;
            }
        }

        itm = bbh_item_walk(NULL);
    }

    if (!haveping && !bbh_item(hinfo, BBH_FLAG_NOCONN)) {
        for (testi = 0; (testi < testcount); testi++) {
            if (strcmp(testnames[testi]->name, pingcolumn) == 0) {
                tag_t *newitem = (tag_t *)calloc(1, sizeof(tag_t));
                newitem->columnname = strdup(pingcolumn);
                newitem->next = taghead;
                taghead = newitem;
            }
        }
    }

    /* Add the "badFOO" settings */
    itm = bbh_item_walk(hinfo);
    while (itm) {
        if (strncmp(itm, "bad", 3) == 0) {
            char *tname, *p;
            int b1, b2, b3, n = -1;
            tag_t *tag = NULL;

            tname = itm+3;
            p = strchr(tname, ':');
            if (p) {
                *p = '\0';
                n = sscanf(p+1, "%d:%d:%d", &b1, &b2, &b3);
                for (tag = taghead; (tag && strcmp(tag->columnname, tname)); tag = tag->next);
                *p = ':';
            }

            if (tag && (n == 3)) {
                tag->b1 = b1;
                tag->b2 = b2;
                tag->b3 = b3;
            }
        }

        itm = bbh_item_walk(NULL);
    }

    if (taghead) {
        fprintf(stdout, "<tr>\n");
        fprintf(stdout, "<th align=left valign=top>Network tests");
        if (net) fprintf(stdout, "<br>(from %s)", net);
        fprintf(stdout, "</th>\n");

        fprintf(stdout, "<td><table border=0 cellpadding=\"3\" cellspacing=\"5\" summary=\"%s network tests\">\n", host->hostname);
        fprintf(stdout, "<tr><th align=left valign=top>Service</th><th align=left valign=top>NK</th><th align=left valign=top>C/Y/R limits</th><th align=left valign=top>Specifics</th></tr>\n");
    }
    for (testi = 0, netcount = 0; (testi < testcount); testi++) {
        tag_t *twalk;

        for (twalk = taghead; (twalk && strcasecmp(twalk->columnname, testnames[testi]->name)); twalk = twalk->next);
        if (!twalk) continue;

        use_columndoc(testnames[testi]->name);
        fprintf(stdout, "<tr>");
        fprintf(stdout, "<td valign=top>%s</td>", testnames[testi]->name);
        fprintf(stdout, "<td valign=top>%s</td>", nkval(host->hostname, testnames[testi]->name, nkalerts));

        fprintf(stdout, "<td valign=top>");
        if (twalk->b1 || twalk->b2 || twalk->b3) {
            fprintf(stdout, "%d/%d/%d", twalk->b1, twalk->b2, twalk->b3);
        }
        else {
            fprintf(stdout, "-/-/-");
        }
        fprintf(stdout, "</td>");

        fprintf(stdout, "<td valign=top>");
        fprintf(stdout, "<i>%s</i>", (twalk->visualdata ? twalk->visualdata : "&nbsp;"));
        if (twalk->expdata) fprintf(stdout, " must return <i>'%s'</i>", twalk->expdata);
        fprintf(stdout, "</td>");

        fprintf(stdout, "</tr>");
        netcount++;
    }
    if (taghead) {
        fprintf(stdout, "</table></td>\n");
        fprintf(stdout, "</tr>\n");
    }


    if (netcount != testcount) {
        fprintf(stdout, "<tr>\n");
        fprintf(stdout, "<th align=left valign=top>Local tests</th>\n");
        fprintf(stdout, "<td><table border=0 cellpadding=\"3\" cellspacing=\"5\" summary=\"%s local tests\">\n", host->hostname);
        fprintf(stdout, "<tr><th align=left valign=top>Service</th><th align=left valign=top>NK</th><th align=left valign=top>C/Y/R limits</th><th align=left valign=top>Configuration <i>(NB: Thresholds on client may differ)</i></th></tr>\n");
    }
    for (testi = 0; (testi < testcount); testi++) {
        tag_t *twalk;

        for (twalk = taghead; (twalk && strcasecmp(twalk->columnname, testnames[testi]->name)); twalk = twalk->next);
        if (twalk) continue;

        use_columndoc(testnames[testi]->name);
        fprintf(stdout, "<tr>");
        fprintf(stdout, "<td valign=top>%s</td>", testnames[testi]->name);
        fprintf(stdout, "<td valign=top>%s</td>", nkval(host->hostname, testnames[testi]->name, nkalerts));
        fprintf(stdout, "<td valign=top>-/-/-</td>");

        /* Make up some default configuration data */
        fprintf(stdout, "<td valign=top>");
        if (strcmp(testnames[testi]->name, "cpu") == 0) {
            fprintf(stdout, "UNIX - Yellow: Load average > 1.5, Red: Load average > 3.0<br>");
            fprintf(stdout, "Windows - Yellow: CPU utilisation > 80%%, Red: CPU utilisation > 95%%");
        }
        else if (strcmp(testnames[testi]->name, "disk") == 0) {
            fprintf(stdout, "Default limits: Yellow 90%% full, Red 95%% full<br>\n");
            print_disklist(host->hostname);
        }
        else if (strcmp(testnames[testi]->name, "memory") == 0) {
            fprintf(stdout, "Yellow: swap/pagefile use > 80%%, Red: swap/pagefile use > 90%%");
        }
        else if (strcmp(testnames[testi]->name, "procs") == 0) {
            htnames_t *walk;

            if (!host->procs) fprintf(stdout, "No processes monitored<br>\n");

            for (walk = host->procs; (walk); walk = walk->next) {
                fprintf(stdout, "%s<br>\n", walk->name);
            }
        }
        else if (strcmp(testnames[testi]->name, "svcs") == 0) {
            htnames_t *walk;

            if (!host->svcs) fprintf(stdout, "No services monitored<br>\n");

            for (walk = host->svcs; (walk); walk = walk->next) {
                fprintf(stdout, "%s<br>\n", walk->name);
            }
        }
        else {
            fprintf(stdout, "&nbsp;");
        }
        fprintf(stdout, "</td>");

        fprintf(stdout, "</tr>");
    }
    if (netcount != testcount) {
        fprintf(stdout, "</table></td>\n");
        fprintf(stdout, "</tr>\n");
    }

    /* Do the alerts */
    alert = (activealerts_t *)calloc(1, sizeof(activealerts_t));
    alert->hostname = host->hostname;
    alert->location = bbh_item(hinfo, BBH_ALLPAGEPATHS);
    strcpy(alert->ip, "127.0.0.1");
    alert->color = COL_RED;
    alert->pagemessage = "";
    alert->state = A_PAGING;
    alert->cookie = 12345;
    alert_printmode(2);
    for (testi = 0; (testi < testcount); testi++) {
        alert->testname = testnames[testi]->name;
        if (have_recipient(alert, NULL)) print_alert_recipients(alert, buf);
    }
    xfree(alert);

    if (STRBUFLEN(buf) > 0) {
        fprintf(stdout, "<tr>\n");
        fprintf(stdout, "<th align=left valign=top>Alerts</th>\n");
        fprintf(stdout, "<td><table border=0 cellpadding=\"3\" cellspacing=\"5\" summary=\"%s alerts\">\n", host->hostname);
        fprintf(stdout, "<tr><th>Service</th><th>Recipient</th><th>1st Delay</th><th>Stop after</th><th>Repeat</th><th>Time of Day</th><th>Colors</th></tr>\n");

        fprintf(stdout, "%s", STRBUF(buf));

        fprintf(stdout, "</table></td>\n");
        fprintf(stdout, "</tr>\n");
    }

    /* Finish off this host */
    fprintf(stdout, "</table>\n");

    freestrbuffer(buf);
}
Beispiel #24
0
int main(int argc, char *argv[])
{
	char histlogfn[PATH_MAX];
	FILE *fd;
	char textrepfullfn[PATH_MAX], textrepfn[1024], textrepurl[PATH_MAX];
	FILE *textrep;
	reportinfo_t repinfo;
	int argi;
	char *envarea = NULL;
	void *hinfo;

	for (argi=1; (argi < argc); argi++) {
		if (argnmatch(argv[argi], "--env=")) {
			char *p = strchr(argv[argi], '=');
			loadenv(p+1, envarea);
		}
		else if (argnmatch(argv[argi], "--area=")) {
			char *p = strchr(argv[argi], '=');
			envarea = strdup(p+1);
		}
	}

	redirect_cgilog("reportlog");

	cgidata = cgi_request();
	parse_query();
	load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn());
        if ((hinfo = hostinfo(hostname)) == NULL) {
		errormsg("No such host");
		return 1;
	}
	ip = xmh_item(hinfo, XMH_IP);
	displayname = xmh_item(hinfo, XMH_DISPLAYNAME);
	if (!displayname) displayname = hostname;

	sprintf(histlogfn, "%s/%s.%s", xgetenv("XYMONHISTDIR"), commafy(hostname), service);
	fd = fopen(histlogfn, "r");
	if (fd == NULL) {
		errormsg("Cannot open history file");
	}

	color = parse_historyfile(fd, &repinfo, hostname, service, st, end, 0, reportwarnlevel, reportgreenlevel, reportwarnstops, reporttime);
	fclose(fd);

	sprintf(textrepfn, "avail-%s-%s-%u-%u.txt", hostname, service, (unsigned int)getcurrenttime(NULL), (int)getpid());
	sprintf(textrepfullfn, "%s/%s", xgetenv("XYMONREPDIR"), textrepfn);
	sprintf(textrepurl, "%s/%s", xgetenv("XYMONREPURL"), textrepfn);
	textrep = fopen(textrepfullfn, "w");

	/* Now generate the webpage */
	printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE"));

	generate_replog(stdout, textrep, textrepurl, 
			hostname, service, color, style, 
			ip, displayname,
			st, end, reportwarnlevel, reportgreenlevel, reportwarnstops, 
			&repinfo);

	if (textrep) fclose(textrep);
	return 0;
}
Beispiel #25
0
void add_http_test(testitem_t *t)
{
	http_data_t *httptest;

	char *dnsip = NULL;
	ssloptions_t *sslopt = NULL;
	char *sslopt_ciphers = NULL;
	int sslopt_version = SSLVERSION_DEFAULT;
	char *sslopt_clientcert = NULL;
	int  httpversion = HTTPVER_11;
	cookielist_t *ck = NULL;
	int firstcookie = 1;
	char *decodedurl;
	strbuffer_t *httprequest = newstrbuffer(0);

	/* Allocate the private data and initialize it */
	httptest = (http_data_t *) calloc(1, sizeof(http_data_t));
	t->privdata = (void *) httptest;

	decodedurl = decode_url(t->testspec, &httptest->weburl);
	if (!decodedurl) {
		errprintf("Invalid URL for http check: %s\n", t->testspec);
		return;
	}

	httptest->url = strdup(decodedurl);
	httptest->contlen = -1;
	httptest->parsestatus = (httptest->weburl.proxyurl ? httptest->weburl.proxyurl->parseerror : httptest->weburl.desturl->parseerror);

	/* If there was a parse error in the URL, dont run the test */
	if (httptest->parsestatus) return;


	if (httptest->weburl.proxyurl && (httptest->weburl.proxyurl->ip == NULL)) {
		dnsip = dnsresolve(httptest->weburl.proxyurl->host);
		if (dnsip) {
			httptest->weburl.proxyurl->ip = strdup(dnsip);
		}
		else {
			dbgprintf("Could not resolve URL hostname '%s'\n", httptest->weburl.proxyurl->host);
		}
	}
	else if (httptest->weburl.desturl->ip == NULL) {
		dnsip = dnsresolve(httptest->weburl.desturl->host);
		if (dnsip) {
			httptest->weburl.desturl->ip = strdup(dnsip);
		}
		else {
			dbgprintf("Could not resolve URL hostname '%s'\n", httptest->weburl.desturl->host);
		}
	}

	switch (httptest->weburl.testtype) {
	  case WEBTEST_PLAIN:
	  case WEBTEST_STATUS:
		httptest->contentcheck = CONTENTCHECK_NONE;
		break;

	  case WEBTEST_CONTENT:
		{
			FILE *contentfd;
			char contentfn[PATH_MAX];
			sprintf(contentfn, "%s/content/%s.substring", xgetenv("XYMONHOME"), commafy(t->host->hostname));
			contentfd = fopen(contentfn, "r");
			if (contentfd) {
				char l[MAX_LINE_LEN];
				char *p;

				if (fgets(l, sizeof(l), contentfd)) {
					p = strchr(l, '\n'); if (p) { *p = '\0'; };
					httptest->weburl.expdata = strdup(l);
				}
				else {
					httptest->contstatus = STATUS_CONTENTMATCH_NOFILE;
				}
				fclose(contentfd);
			}
			else {
				httptest->contstatus = STATUS_CONTENTMATCH_NOFILE;
			}
			httptest->contentcheck = CONTENTCHECK_REGEX;
		}
		break;

	  case WEBTEST_CONT:
		httptest->contentcheck = ((*httptest->weburl.expdata == '#') ?  CONTENTCHECK_DIGEST : CONTENTCHECK_REGEX);
		break;

	  case WEBTEST_NOCONT:
		httptest->contentcheck = CONTENTCHECK_NOREGEX;
		break;

	  case WEBTEST_POST:
	  case WEBTEST_SOAP:
		if (httptest->weburl.expdata == NULL) {
			httptest->contentcheck = CONTENTCHECK_NONE;
		}
		else {
			httptest->contentcheck = ((*httptest->weburl.expdata == '#') ?  CONTENTCHECK_DIGEST : CONTENTCHECK_REGEX);
		}
		break;

	  case WEBTEST_NOPOST:
	  case WEBTEST_NOSOAP:
		if (httptest->weburl.expdata == NULL) {
			httptest->contentcheck = CONTENTCHECK_NONE;
		}
		else {
			httptest->contentcheck = CONTENTCHECK_NOREGEX;
		}
		break;

	  case WEBTEST_TYPE:
		httptest->contentcheck = CONTENTCHECK_CONTENTTYPE;
		break;
	}

	/* Compile the hashes and regex's for those tests that use it */
	switch (httptest->contentcheck) {
	  case CONTENTCHECK_DIGEST:
		{
			char *hashfunc;

			httptest->exp = (void *) strdup(httptest->weburl.expdata+1);
			hashfunc = strchr(httptest->exp, ':');
			if (hashfunc) {
				*hashfunc = '\0';
				httptest->digestctx = digest_init(httptest->exp);
				*hashfunc = ':';
			}
		}
		break;

	  case CONTENTCHECK_REGEX:
	  case CONTENTCHECK_NOREGEX:
		{
			int status;

			httptest->exp = (void *) malloc(sizeof(regex_t));
			status = regcomp((regex_t *)httptest->exp, httptest->weburl.expdata, REG_EXTENDED|REG_NOSUB);
			if (status) {
				errprintf("Failed to compile regexp '%s' for URL %s\n", httptest->weburl.expdata, httptest->url);
				httptest->contstatus = STATUS_CONTENTMATCH_BADREGEX;
			}
		}
		break;

	  case CONTENTCHECK_CONTENTTYPE:
		httptest->exp = httptest->weburl.expdata;
		break;
	}

	if (httptest->weburl.desturl->schemeopts) {
		if      (strstr(httptest->weburl.desturl->schemeopts, "3"))      sslopt_version = SSLVERSION_V3;
		else if (strstr(httptest->weburl.desturl->schemeopts, "2"))      sslopt_version = SSLVERSION_V2;

		if      (strstr(httptest->weburl.desturl->schemeopts, "h"))      sslopt_ciphers = ciphershigh;
		else if (strstr(httptest->weburl.desturl->schemeopts, "m"))      sslopt_ciphers = ciphersmedium;

		if      (strstr(httptest->weburl.desturl->schemeopts, "10"))     httpversion    = HTTPVER_10;
		else if (strstr(httptest->weburl.desturl->schemeopts, "11"))     httpversion    = HTTPVER_11;
	}

	/* Get any cookies */
	load_cookies();

	/* Generate the request */
	addtobuffer(httprequest, (httptest->weburl.postdata ? "POST " : "GET "));
	switch (httpversion) {
		case HTTPVER_10: 
			addtobuffer(httprequest, (httptest->weburl.proxyurl ? httptest->url : httptest->weburl.desturl->relurl));
			addtobuffer(httprequest, " HTTP/1.0\r\n"); 
			break;

		case HTTPVER_11: 
			/*
			 * Experience shows that even though HTTP/1.1 says you should send the
			 * full URL, some servers (e.g. SunOne App server 7) choke on it.
			 * So just send the good-old relative URL unless we're proxying.
			 */
			addtobuffer(httprequest, (httptest->weburl.proxyurl ? httptest->url : httptest->weburl.desturl->relurl));
			addtobuffer(httprequest, " HTTP/1.1\r\n"); 
			addtobuffer(httprequest, "Connection: close\r\n"); 
			break;
	}

	addtobuffer(httprequest, "Host: ");
	addtobuffer(httprequest, httptest->weburl.desturl->host);
	if ((httptest->weburl.desturl->port != 80) && (httptest->weburl.desturl->port != 443)) {
		char hostporthdr[20];

		sprintf(hostporthdr, ":%d", httptest->weburl.desturl->port);
		addtobuffer(httprequest, hostporthdr);
	}
	addtobuffer(httprequest, "\r\n");

	if (httptest->weburl.postdata) {
		char hdr[100];
		int contlen = strlen(httptest->weburl.postdata);

		if (strncmp(httptest->weburl.postdata, "file:", 5) == 0) {
			/* Load the POST data from a file */
			FILE *pf = fopen(httptest->weburl.postdata+5, "r");
			if (pf == NULL) {
				errprintf("Cannot open POST data file %s\n", httptest->weburl.postdata+5);
				xfree(httptest->weburl.postdata);
				httptest->weburl.postdata = strdup("");
				contlen = 0;
			}
			else {
				struct stat st;

				if (fstat(fileno(pf), &st) == 0) {
					int n;

					xfree(httptest->weburl.postdata);
					httptest->weburl.postdata = (char *)malloc(st.st_size + 1); *(httptest->weburl.postdata) = '\0';
					n = fread(httptest->weburl.postdata, 1, st.st_size, pf);
					if (n == st.st_size) {
						*(httptest->weburl.postdata+n) = '\0';
						contlen = n;
					}
					else {
						errprintf("Cannot read file %s: %s\n", httptest->weburl.postdata+5, strerror(errno));
						contlen = 0;
					}
				}
				else {
					errprintf("Cannot stat file %s\n", httptest->weburl.postdata+5);
					httptest->weburl.postdata = strdup("");
					contlen = 0;
				}

				fclose(pf);
			}
		}

		addtobuffer(httprequest, "Content-type: ");
		if      (httptest->weburl.postcontenttype) 
			addtobuffer(httprequest, httptest->weburl.postcontenttype);
		else if ((httptest->weburl.testtype == WEBTEST_SOAP) || (httptest->weburl.testtype == WEBTEST_NOSOAP)) 
			addtobuffer(httprequest, "application/soap+xml; charset=utf-8");
		else 
			addtobuffer(httprequest, "application/x-www-form-urlencoded");
		addtobuffer(httprequest, "\r\n");

		sprintf(hdr, "Content-Length: %d\r\n", contlen);
		addtobuffer(httprequest, hdr);
	}
	{
		char useragent[100];
		void *hinfo;
		char *browser = NULL;

		hinfo = hostinfo(t->host->hostname);
		if (hinfo) browser = xmh_item(hinfo, XMH_BROWSER);

		if (browser) {
			sprintf(useragent, "User-Agent: %s\r\n", browser);
		}
		else {
			sprintf(useragent, "User-Agent: Xymon xymonnet/%s\r\n", VERSION);
		}

		addtobuffer(httprequest, useragent);
	}
	if (httptest->weburl.desturl->auth) {
		if (strncmp(httptest->weburl.desturl->auth, "CERT:", 5) == 0) {
			sslopt_clientcert = httptest->weburl.desturl->auth+5;
		}
		else {
			addtobuffer(httprequest, "Authorization: Basic ");
			addtobuffer(httprequest, base64encode(httptest->weburl.desturl->auth));
			addtobuffer(httprequest, "\r\n");
		}
	}
	if (httptest->weburl.proxyurl && httptest->weburl.proxyurl->auth) {
		addtobuffer(httprequest, "Proxy-Authorization: Basic ");
		addtobuffer(httprequest, base64encode(httptest->weburl.proxyurl->auth));
		addtobuffer(httprequest, "\r\n");
	}
	for (ck = cookiehead; (ck); ck = ck->next) {
		int useit = 0;

		if (ck->tailmatch) {
			int startpos = strlen(httptest->weburl.desturl->host) - strlen(ck->host);

			if (startpos > 0) useit = (strcmp(httptest->weburl.desturl->host+startpos, ck->host) == 0);
		}
		else useit = (strcmp(httptest->weburl.desturl->host, ck->host) == 0);
		if (useit) useit = (strncmp(ck->path, httptest->weburl.desturl->relurl, strlen(ck->path)) == 0);

		if (useit) {
			if (firstcookie) {
				addtobuffer(httprequest, "Cookie: ");
				firstcookie = 0;
			}
			addtobuffer(httprequest, ck->name);
			addtobuffer(httprequest, "=");
			addtobuffer(httprequest, ck->value);
			addtobuffer(httprequest, "\r\n");
		}
	}

	/* Some standard stuff */
	addtobuffer(httprequest, "Accept: */*\r\n");
	addtobuffer(httprequest, "Pragma: no-cache\r\n");

	if ((httptest->weburl.testtype == WEBTEST_SOAP) || (httptest->weburl.testtype == WEBTEST_NOSOAP)) {
		/* Must provide a SOAPAction header */
		addtobuffer(httprequest, "SOAPAction: ");
		addtobuffer(httprequest, httptest->url);
		addtobuffer(httprequest, "\r\n");
	}
	
	/* The final blank line terminates the headers */
	addtobuffer(httprequest, "\r\n");

	/* Post data goes last */
	if (httptest->weburl.postdata) addtobuffer(httprequest, httptest->weburl.postdata);

	/* Pickup any SSL options the user wants */
	if (sslopt_ciphers || (sslopt_version != SSLVERSION_DEFAULT) || sslopt_clientcert){
		sslopt = (ssloptions_t *) malloc(sizeof(ssloptions_t));
		sslopt->cipherlist = sslopt_ciphers;
		sslopt->sslversion = sslopt_version;
		sslopt->clientcert = sslopt_clientcert;
	}

	/* Add to TCP test queue */
	if (httptest->weburl.proxyurl == NULL) {
		httptest->tcptest = add_tcp_test(httptest->weburl.desturl->ip, 
						 httptest->weburl.desturl->port, 
						 httptest->weburl.desturl->scheme,
						 sslopt, t->srcip,
						 t->testspec, t->silenttest, grabstrbuffer(httprequest), 
						 httptest, tcp_http_data_callback, tcp_http_final_callback);
	}
	else {
		httptest->tcptest = add_tcp_test(httptest->weburl.proxyurl->ip, 
						 httptest->weburl.proxyurl->port, 
						 httptest->weburl.proxyurl->scheme,
						 sslopt, t->srcip,
						 t->testspec, t->silenttest, grabstrbuffer(httprequest), 
						 httptest, tcp_http_data_callback, tcp_http_final_callback);
	}
}
Beispiel #26
0
static int criteriamatch(activealerts_t *alert, criteria_t *crit, criteria_t *rulecrit, int *anymatch, time_t *nexttime)
{
	/*
	 * See if the "crit" matches the "alert".
	 * Match on pagespec, dgspec, hostspec, svcspec, classspec, groupspec, colors, timespec, minduration, maxduration, sendrecovered
	 */

	static char *pgnames = NULL;
	int pgmatchres, pgexclres;
	time_t duration = (getcurrenttime(NULL) - alert->eventstart);
	int result, cfid = 0;
	char *pgtok, *cfline = NULL;
	void *hinfo = hostinfo(alert->hostname);

	/* The top-level page needs a name - cannot match against an empty string */
	if (pgnames) xfree(pgnames);
	pgnames = strdup((*alert->location == '\0') ? "/" : alert->location);

	if (crit) { cfid = crit->cfid; cfline = crit->cfline; }
	if (!cfid && rulecrit) cfid = rulecrit->cfid;
	if (!cfline && rulecrit) cfline = rulecrit->cfline;
	if (!cfline) cfline = "<undefined>";

	traceprintf("Matching host:service:dgroup:page '%s:%s:%s:%s' against rule line %d\n",
			alert->hostname, alert->testname, xmh_item(hinfo, XMH_DGNAME), alert->location, cfid);

	if (alert->state == A_PAGING) {
		/* Check max-duration now - it's fast and easy. */
		if (crit && crit->maxduration && (duration > crit->maxduration)) { 
			traceprintf("Failed '%s' (max. duration %d>%d)\n", cfline, duration, crit->maxduration);
			if (!printmode) return 0; 
		}
	}

	if (crit && crit->classspec && !namematch(alert->classname, crit->classspec, crit->classspecre)) { 
		traceprintf("Failed '%s' (class not in include list)\n", cfline);
		return 0; 
	}
	if (crit && crit->exclassspec && namematch(alert->classname, crit->exclassspec, crit->exclassspecre)) { 
		traceprintf("Failed '%s' (class excluded)\n", cfline);
		return 0; 
	}

	/* alert->groups is a comma-separated list of groups, so it needs some special handling */
	/* 
	 * NB: Dont check groups when RECOVERED - the group list for recovery messages is always empty.
	 * It doesn't matter if we match a recipient who was not in the group that originally
	 * got the alert - we will later check who has received the alert, and only those that
	 * have will get the recovery message.
	 */
	if (crit && (crit->groupspec || crit->exgroupspec) && (alert->state != A_RECOVERED)) {
		char *grouplist;
		char *tokptr;

		grouplist = (alert->groups && (*(alert->groups))) ? strdup(alert->groups) : NULL;
		if (crit->groupspec) {
			char *onegroup;
			int iswanted = 0;

			if (grouplist) {
				/* There is a group label on the alert, so it must match */
				onegroup = strtok_r(grouplist, ",", &tokptr);
				while (onegroup && !iswanted) {
					iswanted = (namematch(onegroup, crit->groupspec, crit->groupspecre));
					onegroup = strtok_r(NULL, ",", &tokptr);
				}
			}

			if (!iswanted) {
				/*
				 * Either the alert had a group list that didn't match, or
				 * there was no group list and the rule listed one.
				 * In both cases, it's a failed match.
				 */
				traceprintf("Failed '%s' (group not in include list)\n", cfline);
				if (grouplist) xfree(grouplist);
				return 0; 
			}
		}

		if (crit->exgroupspec && grouplist) {
			char *onegroup;

			/* Excluded groups are only handled when the alert does have a group list */

			strcpy(grouplist, alert->groups); /* Might have been used in the include list */
			onegroup = strtok_r(grouplist, ",", &tokptr);
			while (onegroup) {
				if (namematch(onegroup, crit->exgroupspec, crit->exgroupspecre)) { 
					traceprintf("Failed '%s' (group excluded)\n", cfline);
					xfree(grouplist);
					return 0; 
				}
				onegroup = strtok_r(NULL, ",", &tokptr);
			}
		}

		if (grouplist) xfree(grouplist);
	}

	pgmatchres = pgexclres = -1;
	pgtok = strtok(pgnames, ",");
	while (pgtok) {
		if (crit && crit->pagespec && (pgmatchres != 1))
			pgmatchres = (namematch(pgtok, crit->pagespec, crit->pagespecre) ? 1 : 0);

		if (crit && crit->expagespec && (pgexclres != 1))
			pgexclres = (namematch(pgtok, crit->expagespec, crit->expagespecre) ? 1 : 0);

		pgtok = strtok(NULL, ",");
	}
	if (pgexclres == 1) {
		traceprintf("Failed '%s' (pagename excluded)\n", cfline);
		return 0; 
	}
	if (pgmatchres == 0) {
		traceprintf("Failed '%s' (pagename not in include list)\n", cfline);
		return 0;
	}

	if (crit && crit->dgspec && !namematch(xmh_item(hinfo, XMH_DGNAME), crit->dgspec, crit->dgspecre)) { 
		traceprintf("Failed '%s' (displaygroup not in include list)\n", cfline);
		return 0; 
	}
	if (crit && crit->exdgspec && namematch(xmh_item(hinfo, XMH_DGNAME), crit->exdgspec, crit->exdgspecre)) { 
		traceprintf("Failed '%s' (displaygroup excluded)\n", cfline);
		return 0; 
	}

	if (crit && crit->hostspec && !namematch(alert->hostname, crit->hostspec, crit->hostspecre)) { 
		traceprintf("Failed '%s' (hostname not in include list)\n", cfline);
		return 0; 
	}
	if (crit && crit->exhostspec && namematch(alert->hostname, crit->exhostspec, crit->exhostspecre)) { 
		traceprintf("Failed '%s' (hostname excluded)\n", cfline);
		return 0; 
	}

	if (crit && crit->svcspec && !namematch(alert->testname, crit->svcspec, crit->svcspecre))  { 
		traceprintf("Failed '%s' (service not in include list)\n", cfline);
		return 0; 
	}
	if (crit && crit->exsvcspec && namematch(alert->testname, crit->exsvcspec, crit->exsvcspecre))  { 
		traceprintf("Failed '%s' (service excluded)\n", cfline);
		return 0; 
	}

	if (alert->state == A_NOTIFY) {
		/*
		 * Dont do the check until we are checking individual recipients (rulecrit is set).
		 * You dont need to have NOTICE on the top-level rule, it's enough if a recipient
		 * has it set. However, we do want to allow there to be a default defined in the
		 * rule; but it doesn't take effect until we start checking the recipients.
		 */
		if (rulecrit) {
			int n = (crit ? crit->sendnotice : -1);
			traceprintf("Checking NOTICE setting %d (rule:%d)\n", n, rulecrit->sendnotice);
			if (crit && (crit->sendnotice == SR_NOTWANTED)) result = 0;	/* Explicit NONOTICE */
			else if (crit && (crit->sendnotice == SR_WANTED)) result = 1;	/* Explicit NOTICE */
			else result = (rulecrit->sendnotice == SR_WANTED);		/* Not set, but rule has NOTICE */
		}
		else {
			result = 1;
		}

		if (!result) traceprintf("Failed '%s' (notice not wanted)\n", cfline);
		return result;
	}

	/* At this point, we know the configuration may result in an alert. */
	if (anymatch) (*anymatch)++;

	/* 
	 * Duration checks should be done on real paging messages only. 
	 * Not on recovery- or notify-messages.
	 */
	if (alert->state == A_PAGING) {
		if (crit && crit->minduration && (duration < crit->minduration)) { 
			if (nexttime) {
				time_t mynext = alert->eventstart + crit->minduration;

				if ((*nexttime == -1) || (*nexttime > mynext)) *nexttime = mynext;
			}
			traceprintf("Failed '%s' (min. duration %d<%d)\n", cfline, duration, crit->minduration);
			if (!printmode) return 0; 
		}
	}

	/*
	 * Time restrictions apply to ALL messages.
	 * Before 4.2, these were only applied to ALERT messages,
	 * not RECOVERED and NOTIFY messages. This caused some
	 * unfortunate alerts in the middle of the night because
	 * some random system recovered ... not good. So apply
	 * this check to all messages.
	 */
	if (crit && crit->timespec && !timematch(xmh_item(hinfo, XMH_HOLIDAYS), crit->timespec)) {
		traceprintf("Failed '%s' (time criteria)\n", cfline);
		if (!printmode) return 0; 
	}

	/* Check color. For RECOVERED messages, this holds the color of the alert, not the recovery state */
	if (crit && crit->colors) {
		result = (((1 << alert->color) & crit->colors) != 0);
		if (printmode) return 1;
	}
	else {
		result = (((1 << alert->color) & defaultcolors) != 0);
		if (printmode) return 1;
	}
	if (!result) {
		traceprintf("Failed '%s' (color)\n", cfline);
		return result;
	}

	if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
		/*
		 * Dont do the check until we are checking individual recipients (rulecrit is set).
		 * You dont need to have RECOVERED on the top-level rule, it's enough if a recipient
		 * has it set. However, we do want to allow there to be a default defined in the
		 * rule; but it doesn't take effect until we start checking the recipients.
		 */
		if (rulecrit) {
			int n = (crit ? crit->sendrecovered : -1);
			traceprintf("Checking recovered setting %d (rule:%d)\n", n, rulecrit->sendrecovered);
			if (crit && (crit->sendrecovered == SR_NOTWANTED)) result = 0;		/* Explicit NORECOVERED */
			else if (crit && (crit->sendrecovered == SR_WANTED)) result = 1;	/* Explicit RECOVERED */
			else result = (rulecrit->sendrecovered == SR_WANTED);	/* Not set, but rule has RECOVERED */
		}
		else {
			result = 1;
		}

		if (printmode) return result;
	}

	if (result) {
		traceprintf("*** Match with '%s' ***\n", cfline);
	}

	return result;
}