hostinfo_t *register_host(char *hostname, enum locator_servicetype_t servicetype, char *servername) { xtreePos_t handle; hostinfo_t *itm = NULL; handle = xtreeFind(hitree[servicetype], hostname); if (handle == xtreeEnd(hitree[servicetype])) { itm = (hostinfo_t *)calloc(1, sizeof(hostinfo_t)); itm->hostname = strdup(hostname); xtreeAdd(hitree[servicetype], itm->hostname, itm); } else { itm = xtreeData(hitree[servicetype], handle); } /* If we dont know this server, then we must register it. If we do, just update the host record */ handle = xtreeFind(sitree[servicetype], servername); if (handle == xtreeEnd(sitree[servicetype])) { dbgprintf("Registering default server '%s'\n", servername); itm->server = register_server(servername, servicetype, 1, 1, NULL); } else { serverinfo_t *newserver = xtreeData(sitree[servicetype], handle); if (itm->server && (itm->server != newserver)) { errprintf("Warning: Host %s:%s moved from %s to %s\n", hostname, servicetype_names[servicetype], itm->server->servername, newserver->servername); } itm->server = newserver; } return itm; }
static holiday_t *findholiday(char *key, int dayinyear) { xtreePos_t handle; holidayset_t *hset; holiday_t *p; if (key && *key) { handle = xtreeFind(holidays, key); if (handle == xtreeEnd(holidays)) { key = NULL; handle = xtreeFind(holidays, ""); } } else { key = NULL; handle = xtreeFind(holidays, ""); } if (handle != xtreeEnd(holidays)) hset = (holidayset_t *)xtreeData(holidays, handle); else return NULL; p = hset->head; while (p) { if (dayinyear == p->yday) { return p; } p = p->next; } return NULL; }
static void locator_updatecache(enum locator_servicetype_t svc, char *key, char *resp) { xtreePos_t handle; cacheitm_t *newitm; if (!havecache[svc]) return; handle = xtreeFind(locatorcache[svc], key); if (handle == xtreeEnd(locatorcache[svc])) { newitm = (cacheitm_t *)calloc(1, sizeof(cacheitm_t)); newitm->key = strdup(key); newitm->resp = strdup(resp); if (xtreeAdd(locatorcache[svc], newitm->key, newitm) != XTREE_STATUS_OK) { xfree(newitm->key); xfree(newitm->resp); xfree(newitm); } } else { newitm = (cacheitm_t *)xtreeData(locatorcache[svc], handle); if (newitm->resp) xfree(newitm->resp); newitm->resp = strdup(resp); newitm->tstamp = getcurrenttime(NULL); } }
serverinfo_t *register_server(char *servername, enum locator_servicetype_t servicetype, int weight, enum locator_sticky_t sticky, char *extras) { xtreePos_t handle; serverinfo_t *itm = NULL; handle = xtreeFind(sitree[servicetype], servername); if (handle == xtreeEnd(sitree[servicetype])) { itm = (serverinfo_t *)calloc(1, sizeof(serverinfo_t)); itm->servername = strdup(servername); xtreeAdd(sitree[servicetype], itm->servername, itm); } else { /* Update existing item */ itm = xtreeData(sitree[servicetype], handle); } itm->serverconfweight = itm->serveractualweight = weight; itm->serverweightleft = 0; itm->sticky = sticky; if (itm->serverextras) xfree(itm->serverextras); itm->serverextras = (extras ? strdup(extras) : NULL); if (weight < 0) recalc_current(servicetype); return itm; }
void update_session_cookies(char *hostname, char *urlhost, char *headers) { char *ckhdr, *onecookie; if (!headers) return; ckhdr = headers; do { ckhdr = strstr(ckhdr, "\nSet-Cookie:"); if (ckhdr) { /* Set-Cookie: JSESSIONID=rKy8HZbLgT5W9N8; path=/ */ char *eoln, *cknam, *ckval, *ckpath; cknam = ckval = ckpath = NULL; onecookie = strchr(ckhdr, ':') + 1; onecookie += strspn(onecookie, " \t"); eoln = strchr(onecookie, '\n'); if (eoln) *eoln = '\0'; ckhdr = (eoln ? eoln : NULL); onecookie = strdup(onecookie); if (eoln) *eoln = '\n'; cknam = strtok(onecookie, "="); if (cknam) ckval = strtok(NULL, ";"); if (ckval) { char *tok, *key; xtreePos_t h; hcookie_t *itm; do { tok = strtok(NULL, ";\r"); if (tok) { tok += strspn(tok, " "); if (strncmp(tok, "path=", 5) == 0) { ckpath = tok+5; } } } while (tok); if (ckpath == NULL) ckpath = "/"; key = (char *)malloc(strlen(urlhost) + strlen(cknam) + strlen(ckpath) + 3); sprintf(key, "%s\t%s\t%s", urlhost, cknam, ckpath); h = xtreeFind(cookietree, key); if (h == xtreeEnd(cookietree)) { itm = (hcookie_t *)malloc(sizeof(hcookie_t)); itm->key = key; itm->val = strdup(ckval); xtreeAdd(cookietree, itm->key, itm); } else { itm = (hcookie_t *)xtreeData(cookietree, h); xfree(itm->val); itm->val = strdup(ckval); xfree(key); } } xfree(onecookie); } } while (ckhdr); }
activealerts_t *find_active(char *hostname, char *testname) { xtreePos_t handle; alertanchor_t *anchor; char *twalk; activealerts_t *awalk; handle = xtreeFind(hostnames, hostname); if (handle == xtreeEnd(hostnames)) return NULL; anchor = (alertanchor_t *)xtreeData(hostnames, handle); handle = xtreeFind(testnames, testname); if (handle == xtreeEnd(testnames)) return NULL; twalk = (char *)xtreeData(testnames, handle); for (awalk = anchor->head; (awalk && (awalk->testname != twalk)); awalk=awalk->next) ; return awalk; }
static link_t *find_link(char *key) { link_t *l = NULL; xtreePos_t handle; handle = xtreeFind(linkstree, key); if (handle != xtreeEnd(linkstree)) l = (link_t *)xtreeData(linkstree, handle); return l; }
void add_active(char *hostname, activealerts_t *rec) { xtreePos_t handle; alertanchor_t *anchor; handle = xtreeFind(hostnames, hostname); if (handle == xtreeEnd(hostnames)) return; anchor = (alertanchor_t *)xtreeData(hostnames, handle); rec->next = anchor->head; anchor->head = rec; }
hostinfo_t *rename_host(char *oldhostname, enum locator_servicetype_t servicetype, char *newhostname) { xtreePos_t handle, newhandle; hostinfo_t *itm = NULL; handle = xtreeFind(hitree[servicetype], oldhostname); if (handle == xtreeEnd(hitree[servicetype])) return NULL; newhandle = xtreeFind(hitree[servicetype], newhostname); if (newhandle != xtreeEnd(hitree[servicetype])) { errprintf("Ignored rename of %s to %s - new name already exists\n", oldhostname, newhostname); return NULL; } itm = xtreeData(hitree[servicetype], handle); xtreeDelete(hitree[servicetype], oldhostname); xfree(itm->hostname); itm->hostname = strdup(newhostname); xtreeAdd(hitree[servicetype], itm->hostname, itm); return itm; }
char *get_clientconfig(char *hostname, char *hostclass, char *hostos) { xtreePos_t handle; char *result = NULL; if (!clientconfigs) return NULL; /* * Find the client config. Search for a HOSTNAME entry first, * then the CLIENTCLASS, then CLIENTOS. */ handle = xtreeFind(rbconfigs, hostname); if ((handle == xtreeEnd(rbconfigs)) && hostclass && *hostclass) handle = xtreeFind(rbconfigs, hostclass); if ((handle == xtreeEnd(rbconfigs)) && hostos && *hostos) handle = xtreeFind(rbconfigs, hostos); if (handle != xtreeEnd(rbconfigs)) result = (char *)xtreeData(rbconfigs, handle); return result; }
serverinfo_t *find_server_by_host(enum locator_servicetype_t servicetype, char *hostname) { xtreePos_t handle; hostinfo_t *hinfo; handle = xtreeFind(hitree[servicetype], hostname); if (handle == xtreeEnd(hitree[servicetype])) { return NULL; } hinfo = xtreeData(hitree[servicetype], handle); return hinfo->server; }
static char *locator_querycache(enum locator_servicetype_t svc, char *key) { xtreePos_t handle; cacheitm_t *itm; if (!havecache[svc]) return NULL; handle = xtreeFind(locatorcache[svc], key); if (handle == xtreeEnd(locatorcache[svc])) return NULL; itm = (cacheitm_t *)xtreeData(locatorcache[svc], handle); return (itm->tstamp + cachetimeout[svc]) > getcurrenttime(NULL) ? itm->resp : NULL; }
void locator_flushcache(enum locator_servicetype_t svc, char *key) { xtreePos_t handle; if (!havecache[svc]) return; if (key) { handle = xtreeFind(locatorcache[svc], key); if (handle != xtreeEnd(locatorcache[svc])) { cacheitm_t *itm = (cacheitm_t *)xtreeData(locatorcache[svc], handle); itm->tstamp = 0; } } else { for (handle = xtreeFirst(locatorcache[svc]); (handle != xtreeEnd(locatorcache[svc])); handle = xtreeNext(locatorcache[svc], handle)) { cacheitm_t *itm = (cacheitm_t *)xtreeData(locatorcache[svc], handle); itm->tstamp = 0; } } }
char *find_name(void * tree, char *name) { char *result; xtreePos_t handle; handle = xtreeFind(tree, name); if (handle == xtreeEnd(tree)) { result = strdup(name); if (tree == hostnames) { alertanchor_t *anchor = malloc(sizeof(alertanchor_t)); anchor->head = NULL; xtreeAdd(tree, result, anchor); } else { xtreeAdd(tree, result, result); } } else { result = (char *)xtreeKey(tree, handle); } return result; }
serverinfo_t *downup_server(char *servername, enum locator_servicetype_t servicetype, char action) { xtreePos_t handle; serverinfo_t *itm = NULL; handle = xtreeFind(sitree[servicetype], servername); if (handle == xtreeEnd(sitree[servicetype])) return NULL; /* Update existing item */ itm = xtreeData(sitree[servicetype], handle); switch (action) { case 'F': /* Flag the hosts that point to this server as un-assigned */ for (handle = xtreeFirst(hitree[servicetype]); (handle != xtreeEnd(hitree[servicetype])); handle = xtreeNext(hitree[servicetype], handle)) { hostinfo_t *hitm = (hostinfo_t *)xtreeData(hitree[servicetype], handle); if (hitm->server == itm) hitm->server = NULL; } /* Fall through */ case 'D': dbgprintf("Downing server '%s' type %s\n", servername, servicetype_names[servicetype]); itm->serveractualweight = 0; itm->serverweightleft = 0; if (itm->serverconfweight < 0) recalc_current(servicetype); break; case 'U': dbgprintf("Upping server '%s' type %s to weight %d\n", servername, servicetype_names[servicetype], itm->serverconfweight); itm->serveractualweight = itm->serverconfweight; /* Dont mess with serverweightleft - this may just be an "i'm alive" message */ if (itm->serverconfweight < 0) recalc_current(servicetype); break; } return itm; }
int do_la_rrd(char *hostname, char *testname, char *classname, char *pagepaths, char *msg, time_t tstamp) { static char *la_params[] = { "DS:la:GAUGE:600:U:U", NULL }; static void *la_tpl = NULL; static char *clock_params[] = { "DS:la:GAUGE:600:U:U", NULL }; /* "la" is a misnomer, but to stay compatiable with existing RRD files */ static void *clock_tpl = NULL; static pcre *as400_exp = NULL; static pcre *zVM_exp = NULL; static time_t starttime = 0; char *p, *eoln = NULL; int gotusers=0, gotprocs=0, gotload=0, gotclock=0; int users=0, procs=0, load=0, clockdiff=0; time_t now = getcurrenttime(NULL); if (la_tpl == NULL) la_tpl = setup_template(la_params); if (clock_tpl == NULL) clock_tpl = setup_template(clock_params); if (starttime == 0) starttime = now; if (strstr(msg, "bb-xsnmp")) { /* * bb-xsnmp.pl script output. * * green Tue Apr 5 12:57:37 2005 up: 254.58 days, CPU Usage= 9% * * &green CPU Time in Busy Mode: 9% * &green CPU Time in Idle Mode: 91% * * &yellow CPU Usage Threshold: 90% * &red CPU Usage Threshold: 95% * * <!-- Enterprise: netapp , Version: 6.42 --> * bb-xsnmp.pl Version: 1.78 */ p = strstr(msg, "CPU Usage="); if (p) { p += strlen("CPU Usage="); gotload = 1; load = atoi(p); } goto done_parsing; } else if (strstr(msg, "z/VM") || strstr(msg, "VSE/ESA") || strstr(msg, "z/VSE") || strstr(msg, "z/OS")) { /* z/VM cpu message. Looks like this, from Rich Smrcina (client config mode): * green 5 Apr 2005 20:07:34 CPU Utilization 7% z/VM Version 4 Release 4.0, service level 0402 (32-bit) AVGPROC-007% 01 * VSE/ESA or z/VSE cpu message. * VSE/ESA 2.7.2 cr IPLed on ... * or * z/VSE 3.1.1 cr IPLed on ... * In server (centralized) config mode or for z/OS (which is centralized config only) * the operating system name is part of the message (as in the tests above). */ int ovector[30]; char w[100]; int res; if (zVM_exp == NULL) { const char *errmsg = NULL; int errofs = 0; zVM_exp = pcre_compile(".* CPU Utilization *([0-9]+)%", PCRE_CASELESS, &errmsg, &errofs, NULL); } res = pcre_exec(zVM_exp, NULL, msg, strlen(msg), 0, 0, ovector, (sizeof(ovector)/sizeof(int))); if (res >= 0) { /* We have a match - pick up the data. */ *w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 1, w, sizeof(w)); if (strlen(w)) { load = atoi(w); gotload = 1; } } goto done_parsing; } eoln = strchr(msg, '\n'); if (eoln) *eoln = '\0'; p = strstr(msg, "up: "); if (!p) p = strstr(msg, "Uptime:"); /* Netapp filerstats2bb script */ if (!p) p = strstr(msg, "uptime:"); if (p) { /* First line of cpu report, contains "up: 159 days, 1 users, 169 procs, load=21" */ p = strchr(p, ','); if (p) { gotusers = (sscanf(p, ", %d users", &users) == 1); p = strchr(p+1, ','); } if (p) { gotprocs = (sscanf(p, ", %d procs", &procs) == 1); p = strchr(p+1, ','); } /* * Load can be either * - "load=xx%" (Windows) * - "load=xx.xx" (Unix, DISPREALLOADAVG=TRUE) * - "load=xx" (Unix, DISPREALLOADAVG=FALSE) * * We want the load in percent (Windows), or LA*100 (Unix). */ p = strstr(msg, "load="); if (p) { p += 5; if (strchr(p, '%')) { gotload = 1; load = atoi(p); } else if (strchr(p, '.')) { gotload = 1; load = 100*atoi(p); /* Find the decimal part, and cut off at 2 decimals */ p = strchr(p, '.'); if (strlen(p) > 3) *(p+3) = '\0'; load += atoi(p+1); } else { gotload = 1; load = atoi(p); } } } else { /* * No "uptime" in message - could be from an AS/400. They look like this: * green March 21, 2005 12:33:24 PM EST deltacdc 108 users 45525 jobs(126 batch,0 waiting for message), load=26% */ int ovector[30]; char w[100]; int res; if (as400_exp == NULL) { const char *errmsg = NULL; int errofs = 0; as400_exp = pcre_compile(".* ([0-9]+) users ([0-9]+) jobs.* load=([0-9]+)\\%", PCRE_CASELESS, &errmsg, &errofs, NULL); } res = pcre_exec(as400_exp, NULL, msg, strlen(msg), 0, 0, ovector, (sizeof(ovector)/sizeof(int))); if (res >= 0) { /* We have a match - pick up the AS/400 data. */ *w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 1, w, sizeof(w)); if (strlen(w)) { users = atoi(w); gotusers = 1; } *w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 3, w, sizeof(w)); if (strlen(w)) { load = atoi(w); gotload = 1; } } } done_parsing: if (eoln) *eoln = '\n'; p = strstr(msg, "System clock is "); if (p) { if (sscanf(p, "System clock is %d seconds off", &clockdiff) == 1) gotclock = 1; } if (!gotload) { /* See if it's a report from the ciscocpu.pl script. */ p = strstr(msg, "<br>CPU 5 min average:"); if (p) { /* It reports in % cpu utilization */ p = strchr(p, ':'); load = atoi(p+1); gotload = 1; } } if (gotload) { setupfn("%s.rrd", "la"); snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, load); create_and_update_rrd(hostname, testname, classname, pagepaths, la_params, la_tpl); } if (gotprocs) { setupfn("%s.rrd", "procs"); snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, procs); create_and_update_rrd(hostname, testname, classname, pagepaths, la_params, la_tpl); } if (gotusers) { setupfn("%s.rrd", "users"); snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, users); create_and_update_rrd(hostname, testname, classname, pagepaths, la_params, la_tpl); } if (gotclock) { setupfn("%s.rrd", "clock"); snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, clockdiff); create_and_update_rrd(hostname, testname, classname, pagepaths, clock_params, clock_tpl); } /* * If we have run for less than 6 minutes, drop the memory updates here. * We want to be sure not to use memory statistics from the CPU report * if there is a memory add-on sending a separate memory statistics */ if ((now - starttime) < 360) return 0; if (!memhosts_init || (xtreeFind(memhosts, hostname) == xtreeEnd(memhosts))) { /* Pick up memory statistics */ int found, overflow, realuse, swapuse; long long phystotal, physavail, pagetotal, pageavail; found = overflow = realuse = swapuse = 0; phystotal = physavail = pagetotal = pageavail = 0; p = strstr(msg, "Total Physical memory:"); if (p) { phystotal = str2ll(strchr(p, ':') + 1, NULL); if (phystotal != LONG_MAX) found++; else overflow++; } if (found == 1) { p = strstr(msg, "Available Physical memory:"); if (p) { physavail = str2ll(strchr(p, ':') + 1, NULL); if (physavail != LONG_MAX) found++; else overflow++; } } if (found == 2) { p = strstr(msg, "Total PageFile size:"); if (p) { pagetotal = str2ll(strchr(p, ':') + 1, NULL); if (pagetotal != LONG_MAX) found++; else overflow++; } } if (found == 3) { p = strstr(msg, "Available PageFile size:"); if (p) { pageavail = str2ll(strchr(p, ':') + 1, NULL); if (pageavail != LONG_MAX) found++; else overflow++; } } if (found == 4) { if (!phystotal || !pagetotal) { errprintf("Host %s cpu report had 0 total physical/pagefile memory listed\n", hostname); return 0; } phystotal = phystotal / 100; pagetotal = pagetotal / 100; realuse = 100 - (physavail / phystotal); swapuse = 100 - (pageavail / pagetotal); do_memory_rrd_update(tstamp, hostname, testname, classname, pagepaths, realuse, swapuse, -1); } else if (overflow) { errprintf("Host %s cpu report overflows in memory usage calculation\n", hostname); } } return 0; }
int load_hostnames(char *hostsfn, char *extrainclude, int fqdn) { /* Return value: 0 for load OK, 1 for "No files changed since last load", -1 for error (file not found) */ int prepresult; int ip1, ip2, ip3, ip4, groupid, pageidx; char hostname[4096], *dgname; pagelist_t *curtoppage, *curpage, *pgtail; namelist_t *nametail = NULL; void * htree; char *cfgdata, *inbol, *ineol, insavchar = '\0'; load_hostinfo(NULL); if (*hostsfn == '!') prepresult = prepare_fromfile(hostsfn+1, extrainclude); else if (extrainclude) prepresult = prepare_fromfile(hostsfn, extrainclude); else if ((*hostsfn == '@') || (strcmp(hostsfn, xgetenv("HOSTSCFG")) == 0)) { prepresult = prepare_fromnet(); if (prepresult == -1) { errprintf("Failed to load from xymond, reverting to file-load\n"); prepresult = prepare_fromfile(xgetenv("HOSTSCFG"), extrainclude); } } else prepresult = prepare_fromfile(hostsfn, extrainclude); /* Did we get the data ? */ if (prepresult == -1) { errprintf("Cannot load host data\n"); return -1; } /* Any modifications at all ? */ if (prepresult == 1) { dbgprintf("No files modified, skipping reload of %s\n", hostsfn); return 1; } MEMDEFINE(hostname); MEMDEFINE(l); configloaded = 1; initialize_hostlist(); curpage = curtoppage = pgtail = pghead; pageidx = groupid = 0; dgname = NULL; htree = xtreeNew(strcasecmp); 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'; } if (strncmp(inbol, "page", 4) == 0) { pagelist_t *newp; char *name, *title; pageidx = groupid = 0; if (dgname) xfree(dgname); dgname = NULL; if (get_page_name_title(inbol, "page", &name, &title) == 0) { newp = (pagelist_t *)malloc(sizeof(pagelist_t)); newp->pagepath = strdup(name); newp->pagetitle = (title ? strdup(title) : NULL); newp->next = NULL; pgtail->next = newp; pgtail = newp; curpage = curtoppage = newp; } } else if (strncmp(inbol, "subpage", 7) == 0) { pagelist_t *newp; char *name, *title; pageidx = groupid = 0; if (dgname) xfree(dgname); dgname = NULL; if (get_page_name_title(inbol, "subpage", &name, &title) == 0) { newp = (pagelist_t *)malloc(sizeof(pagelist_t)); newp->pagepath = malloc(strlen(curtoppage->pagepath) + strlen(name) + 2); sprintf(newp->pagepath, "%s/%s", curtoppage->pagepath, name); newp->pagetitle = malloc(strlen(curtoppage->pagetitle) + strlen(title) + 2); sprintf(newp->pagetitle, "%s/%s", curtoppage->pagetitle, title); newp->next = NULL; pgtail->next = newp; pgtail = newp; curpage = newp; } } else if (strncmp(inbol, "subparent", 9) == 0) { pagelist_t *newp, *parent; char *pname, *name, *title; pageidx = groupid = 0; if (dgname) xfree(dgname); dgname = NULL; parent = NULL; if (get_page_name_title(inbol, "subparent", &pname, &title) == 0) { for (parent = pghead; (parent && !pagematch(parent, pname)); parent = parent->next); } if (parent && (get_page_name_title(title, "", &name, &title) == 0)) { newp = (pagelist_t *)malloc(sizeof(pagelist_t)); newp->pagepath = malloc(strlen(parent->pagepath) + strlen(name) + 2); sprintf(newp->pagepath, "%s/%s", parent->pagepath, name); newp->pagetitle = malloc(strlen(parent->pagetitle) + strlen(title) + 2); sprintf(newp->pagetitle, "%s/%s", parent->pagetitle, title); newp->next = NULL; pgtail->next = newp; pgtail = newp; curpage = newp; } } else if (strncmp(inbol, "group", 5) == 0) { char *tok; groupid++; if (dgname) xfree(dgname); dgname = NULL; tok = strtok(inbol, " \t"); if ((strcmp(tok, "group-only") == 0) || (strcmp(tok, "group-except") == 0)) { tok = strtok(NULL, " \t"); } if (tok) tok = strtok(NULL, "\r\n"); if (tok) { char *inp; /* Strip HTML tags from the string */ dgname = (char *)malloc(strlen(tok) + 1); *dgname = '\0'; inp = tok; while (*inp) { char *tagstart, *tagend; tagstart = strchr(inp, '<'); if (tagstart) { tagend = strchr(tagstart, '>'); *tagstart = '\0'; if (*inp) strcat(dgname, inp); if (tagend) { inp = tagend+1; } else { /* Unmatched '<', keep all of the string */ *tagstart = '<'; strcat(dgname, tagstart); inp += strlen(inp); } } else { strcat(dgname, inp); inp += strlen(inp); } } } } else if (sscanf(inbol, "%d.%d.%d.%d %s", &ip1, &ip2, &ip3, &ip4, hostname) == 5) { char *startoftags, *tag, *delim; int elemidx, elemsize; char groupidstr[10]; xtreePos_t handle; namelist_t *newitem, *iwalk, *iprev; if ( (ip1 < 0) || (ip1 > 255) || (ip2 < 0) || (ip2 > 255) || (ip3 < 0) || (ip3 > 255) || (ip4 < 0) || (ip4 > 255)) { errprintf("Invalid IPv4-address for host %s (nibble outside 0-255 range): %d.%d.%d.%d\n", hostname, ip1, ip2, ip3, ip4); goto nextline; } newitem = calloc(1, sizeof(namelist_t)); /* Hostname beginning with '@' are "no-display" hosts. But we still want them. */ if (*hostname == '@') memmove(hostname, hostname+1, strlen(hostname)); if (!fqdn) { /* Strip any domain from the hostname */ char *p = strchr(hostname, '.'); if (p) *p = '\0'; } sprintf(newitem->ip, "%d.%d.%d.%d", ip1, ip2, ip3, ip4); sprintf(groupidstr, "%d", groupid); newitem->groupid = strdup(groupidstr); newitem->dgname = (dgname ? strdup(dgname) : strdup("NONE")); newitem->pageindex = pageidx++; newitem->hostname = strdup(hostname); if (ip1 || ip2 || ip3 || ip4) newitem->preference = 1; else newitem->preference = 0; newitem->logname = strdup(newitem->hostname); { char *p = newitem->logname; while ((p = strchr(p, '.')) != NULL) { *p = '_'; } } newitem->page = curpage; newitem->defaulthost = defaulthost; startoftags = strchr(inbol, '#'); if (startoftags == NULL) startoftags = ""; else startoftags++; startoftags += strspn(startoftags, " \t\r\n"); newitem->allelems = strdup(startoftags); elemsize = 5; newitem->elems = (char **)malloc((elemsize+1)*sizeof(char *)); tag = newitem->allelems; elemidx = 0; while (tag && *tag) { if (elemidx == elemsize) { elemsize += 5; newitem->elems = (char **)realloc(newitem->elems, (elemsize+1)*sizeof(char *)); } newitem->elems[elemidx] = tag; /* Skip until we hit a whitespace or a quote */ tag += strcspn(tag, " \t\r\n\""); if (*tag == '"') { delim = tag; /* Hit a quote - skip until the next matching quote */ tag = strchr(tag+1, '"'); if (tag != NULL) { /* Found end-quote, NULL the item here and move on */ *tag = '\0'; tag++; } /* Now move quoted data one byte down (including the NUL) to kill quotechar */ memmove(delim, delim+1, strlen(delim)); } else if (*tag) { /* Normal end of item, NULL it and move on */ *tag = '\0'; tag++; } else { /* End of line - no more to do. */ tag = NULL; } /* * If we find a "noconn", drop preference value to 0. * If we find a "prefer", up reference value to 2. */ if ((newitem->preference == 1) && (strcmp(newitem->elems[elemidx], "noconn") == 0)) newitem->preference = 0; else if (strcmp(newitem->elems[elemidx], "prefer") == 0) newitem->preference = 2; /* Skip whitespace until start of next tag */ if (tag) tag += strspn(tag, " \t\r\n"); elemidx++; } newitem->elems[elemidx] = NULL; /* See if this host is defined before */ handle = xtreeFind(htree, newitem->hostname); if (strcasecmp(newitem->hostname, ".default.") == 0) { /* The pseudo DEFAULT host */ newitem->next = NULL; defaulthost = newitem; } else if (handle == xtreeEnd(htree)) { /* New item, so add to end of list */ newitem->next = NULL; if (namehead == NULL) namehead = nametail = newitem; else { nametail->next = newitem; nametail = newitem; } xtreeAdd(htree, newitem->hostname, newitem); } else { /* Find the existing record - compare the record pointer instead of the name */ namelist_t *existingrec = (namelist_t *)xtreeData(htree, handle); for (iwalk = namehead, iprev = NULL; ((iwalk != existingrec) && iwalk); iprev = iwalk, iwalk = iwalk->next) ; if (newitem->preference <= iwalk->preference) { /* Add after the existing (more preferred) entry */ newitem->next = iwalk->next; iwalk->next = newitem; } else { /* New item has higher preference, so add before the iwalk item (i.e. after iprev) */ if (iprev == NULL) { newitem->next = namehead; namehead = newitem; } else { newitem->next = iprev->next; iprev->next = newitem; } } } newitem->clientname = xmh_find_item(newitem, XMH_CLIENTALIAS); if (newitem->clientname == NULL) newitem->clientname = newitem->hostname; newitem->downtime = xmh_find_item(newitem, XMH_DOWNTIME); } nextline: if (ineol) { *ineol = insavchar; if (*ineol != '\n') ineol = strchr(ineol, '\n'); inbol = (ineol ? ineol+1 : NULL); } else inbol = NULL; } xfree(cfgdata); if (dgname) xfree(dgname); xtreeDestroy(htree); MEMUNDEFINE(hostname); MEMUNDEFINE(l); build_hosttree(); return 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; }
int main(int argc, char *argv[]) { time_t starttime = gettimer(); char *histdir = NULL; char *histlogdir = NULL; char *msg; int argi, seq; int save_allevents = 1; int save_hostevents = 1; int save_statusevents = 1; int save_histlogs = 1, defaultsaveop = 1; FILE *alleventsfd = NULL; int running = 1; struct sigaction sa; char newcol2[3]; char oldcol2[3]; char alleventsfn[PATH_MAX]; char pidfn[PATH_MAX]; int logdirfull = 0; int minlogspace = 5; MEMDEFINE(pidfn); MEMDEFINE(alleventsfn); MEMDEFINE(newcol2); MEMDEFINE(oldcol2); /* Dont save the error buffer */ save_errbuf = 0; sprintf(pidfn, "%s/xymond_history.pid", xgetenv("XYMONSERVERLOGS")); if (xgetenv("XYMONALLHISTLOG")) save_allevents = (strcmp(xgetenv("XYMONALLHISTLOG"), "TRUE") == 0); if (xgetenv("XYMONHOSTHISTLOG")) save_hostevents = (strcmp(xgetenv("XYMONHOSTHISTLOG"), "TRUE") == 0); if (xgetenv("SAVESTATUSLOG")) save_histlogs = (strncmp(xgetenv("SAVESTATUSLOG"), "FALSE", 5) != 0); for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--histdir=")) { histdir = strchr(argv[argi], '=')+1; } else if (argnmatch(argv[argi], "--histlogdir=")) { histlogdir = strchr(argv[argi], '=')+1; } else if (argnmatch(argv[argi], "--pidfile=")) { strcpy(pidfn, strchr(argv[argi], '=')+1); } else if (argnmatch(argv[argi], "--minimum-free=")) { minlogspace = atoi(strchr(argv[argi], '=')+1); } else if (argnmatch(argv[argi], "--debug")) { debug = 1; } } if (xgetenv("XYMONHISTDIR") && (histdir == NULL)) { histdir = strdup(xgetenv("XYMONHISTDIR")); } if (histdir == NULL) { errprintf("No history directory given, aborting\n"); return 1; } if (save_histlogs && (histlogdir == NULL) && xgetenv("XYMONHISTLOGS")) { histlogdir = strdup(xgetenv("XYMONHISTLOGS")); } if (save_histlogs && (histlogdir == NULL)) { errprintf("No history-log directory given, aborting\n"); return 1; } columndefs = xtreeNew(strcmp); { char *defaultsave, *tok; char *savelist; columndef_t *newrec; savelist = strdup(xgetenv("SAVESTATUSLOG")); defaultsave = strtok(savelist, ","); /* * TRUE: Save everything by default; may list some that are not saved. * ONLY: Save nothing by default; may list some that are saved. * FALSE: Save nothing. */ defaultsaveop = (strcasecmp(defaultsave, "TRUE") == 0); tok = strtok(NULL, ","); while (tok) { newrec = (columndef_t *)malloc(sizeof(columndef_t)); if (*tok == '!') { newrec->saveit = 0; newrec->name = strdup(tok+1); } else { newrec->saveit = 1; newrec->name = strdup(tok); } xtreeAdd(columndefs, newrec->name, newrec); tok = strtok(NULL, ","); } xfree(savelist); } { FILE *pidfd = fopen(pidfn, "w"); if (pidfd) { fprintf(pidfd, "%lu\n", (unsigned long)getpid()); fclose(pidfd); } } sprintf(alleventsfn, "%s/allevents", histdir); if (save_allevents) { alleventsfd = fopen(alleventsfn, "a"); if (alleventsfd == NULL) { errprintf("Cannot open the all-events file '%s'\n", alleventsfn); } setvbuf(alleventsfd, (char *)NULL, _IOLBF, 0); } /* For picking up lost children */ setup_signalhandler("xymond_history"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; sigaction(SIGCHLD, &sa, NULL); sigaction(SIGHUP, &sa, NULL); signal(SIGPIPE, SIG_DFL); while (running) { char *metadata[20] = { NULL, }; int metacount; char *p; char *statusdata = ""; char *hostname, *hostnamecommas, *testname, *dismsg, *modifiers; time_t tstamp, lastchg, disabletime, clienttstamp; int tstamp_i, lastchg_i; int newcolor, oldcolor; int downtimeactive; struct tm tstamptm; int trend; int childstat; /* Pickup any finished child processes to avoid zombies */ while (wait3(&childstat, WNOHANG, NULL) > 0) ; if (rotatefiles && alleventsfd) { fclose(alleventsfd); alleventsfd = fopen(alleventsfn, "a"); if (alleventsfd == NULL) { errprintf("Cannot re-open the all-events file '%s'\n", alleventsfn); } else { setvbuf(alleventsfd, (char *)NULL, _IOLBF, 0); } } msg = get_xymond_message(C_STACHG, "xymond_history", &seq, NULL); if (msg == NULL) { running = 0; continue; } if (nextfscheck < gettimer()) { logdirfull = (chkfreespace(histlogdir, minlogspace, minlogspace) != 0); if (logdirfull) errprintf("Historylog directory %s has less than %d%% free space - disabling save of data for 5 minutes\n", histlogdir, minlogspace); nextfscheck = gettimer() + 300; } p = strchr(msg, '\n'); if (p) { *p = '\0'; statusdata = msg_data(p+1, 0); } metacount = 0; memset(&metadata, 0, sizeof(metadata)); p = gettok(msg, "|"); while (p && (metacount < 20)) { metadata[metacount++] = p; p = gettok(NULL, "|"); } if ((metacount > 9) && (strncmp(metadata[0], "@@stachg", 8) == 0)) { xtreePos_t handle; columndef_t *saveit = NULL; /* @@stachg#seq|timestamp|sender|origin|hostname|testname|expiretime|color|prevcolor|changetime|disabletime|disablemsg|downtimeactive|clienttstamp|modifiers */ sscanf(metadata[1], "%d.%*d", &tstamp_i); tstamp = tstamp_i; hostname = metadata[4]; testname = metadata[5]; newcolor = parse_color(metadata[7]); oldcolor = parse_color(metadata[8]); lastchg = atoi(metadata[9]); disabletime = atoi(metadata[10]); dismsg = metadata[11]; downtimeactive = (atoi(metadata[12]) > 0); clienttstamp = atoi(metadata[13]); modifiers = metadata[14]; if (newcolor == -1) { errprintf("Bad message: newcolor is unknown '%s'\n", metadata[7]); continue; } p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; handle = xtreeFind(columndefs, testname); if (handle == xtreeEnd(columndefs)) { saveit = (columndef_t *)malloc(sizeof(columndef_t)); saveit->name = strdup(testname); saveit->saveit = defaultsaveop; xtreeAdd(columndefs, saveit->name, saveit); } else { saveit = (columndef_t *) xtreeData(columndefs, handle); } if (save_statusevents) { char statuslogfn[PATH_MAX]; int logexists; FILE *statuslogfd; char oldcol[100]; char timestamp[40]; struct stat st; MEMDEFINE(statuslogfn); MEMDEFINE(oldcol); MEMDEFINE(timestamp); sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname); stat(statuslogfn, &st); statuslogfd = fopen(statuslogfn, "r+"); logexists = (statuslogfd != NULL); *oldcol = '\0'; if (logexists) { /* * There is a fair chance xymond has not been * running all the time while this system was monitored. * So get the time of the latest status change from the file, * instead of relying on the "lastchange" value we get * from xymond. This is also needed when migrating from * standard bbd to xymond. */ off_t pos = -1; char l[1024]; int gotit; MEMDEFINE(l); fseeko(statuslogfd, 0, SEEK_END); if (ftello(statuslogfd) > 512) { /* Go back 512 from EOF, and skip to start of a line */ fseeko(statuslogfd, -512, SEEK_END); gotit = (fgets(l, sizeof(l)-1, statuslogfd) == NULL); } else { /* Read from beginning of file */ fseeko(statuslogfd, 0, SEEK_SET); gotit = 0; } while (!gotit) { off_t tmppos = ftello(statuslogfd); int dur_i; if (fgets(l, sizeof(l)-1, statuslogfd)) { /* Sun Oct 10 06:49:42 2004 red 1097383782 602 */ if ((strlen(l) > 24) && (sscanf(l+24, " %s %d %d", oldcol, &lastchg_i, &dur_i) == 2) && (parse_color(oldcol) != -1)) { /* * Record the start location of the line */ pos = tmppos; lastchg = lastchg_i; } } else { gotit = 1; } } if (pos == -1) { /* * Couldnt find anything in the log. * Take lastchg from the timestamp of the logfile, * and just append the data. */ lastchg = st.st_mtime; fseeko(statuslogfd, 0, SEEK_END); } else { /* * lastchg was updated above. * Seek to where the last line starts. */ fseeko(statuslogfd, pos, SEEK_SET); } MEMUNDEFINE(l); } else { /* * Logfile does not exist. */ lastchg = tstamp; statuslogfd = fopen(statuslogfn, "a"); if (statuslogfd == NULL) { errprintf("Cannot open status historyfile '%s' : %s\n", statuslogfn, strerror(errno)); } } if (strcmp(oldcol, colorname(newcolor)) == 0) { /* We wont update history unless the color did change. */ if ((gettimer() - starttime) > 300) { errprintf("Will not update %s - color unchanged (%s)\n", statuslogfn, oldcol); } if (hostnamecommas) xfree(hostnamecommas); if (statuslogfd) fclose(statuslogfd); MEMUNDEFINE(statuslogfn); MEMUNDEFINE(oldcol); MEMUNDEFINE(timestamp); continue; } if (statuslogfd) { if (logexists) { struct tm oldtm; /* Re-print the old record, now with the final duration */ memcpy(&oldtm, localtime(&lastchg), sizeof(oldtm)); strftime(timestamp, sizeof(timestamp), "%a %b %e %H:%M:%S %Y", &oldtm); fprintf(statuslogfd, "%s %s %d %d\n", timestamp, oldcol, (int)lastchg, (int)(tstamp - lastchg)); } /* And the new record. */ memcpy(&tstamptm, localtime(&tstamp), sizeof(tstamptm)); strftime(timestamp, sizeof(timestamp), "%a %b %e %H:%M:%S %Y", &tstamptm); fprintf(statuslogfd, "%s %s %d", timestamp, colorname(newcolor), (int)tstamp); fclose(statuslogfd); } MEMUNDEFINE(statuslogfn); MEMUNDEFINE(oldcol); MEMUNDEFINE(timestamp); } if (save_histlogs && saveit->saveit && !logdirfull) { char *hostdash; char fname[PATH_MAX]; FILE *histlogfd; MEMDEFINE(fname); p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(fname, "%s/%s", histlogdir, hostdash); mkdir(fname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); p = fname + sprintf(fname, "%s/%s/%s", histlogdir, hostdash, testname); mkdir(fname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); p += sprintf(p, "/%s", histlogtime(tstamp)); histlogfd = fopen(fname, "w"); if (histlogfd) { /* * When a host gets disabled or goes purple, the status * message data is not changed - so it will include a * wrong color as the first word of the message. * Therefore we need to fixup this so it matches the * newcolor value. */ int txtcolor = parse_color(statusdata); char *origstatus = statusdata; char *eoln, *restofdata; int written, closestatus, ok = 1; if (txtcolor != -1) { fprintf(histlogfd, "%s", colorname(newcolor)); statusdata += strlen(colorname(txtcolor)); } if (dismsg && *dismsg) nldecode(dismsg); if (disabletime > 0) { fprintf(histlogfd, " Disabled until %s\n%s\n\n", ctime(&disabletime), (dismsg ? dismsg : "")); fprintf(histlogfd, "Status message when disabled follows:\n\n"); statusdata = origstatus; } else if (dismsg && *dismsg) { fprintf(histlogfd, " Planned downtime: %s\n\n", dismsg); fprintf(histlogfd, "Original status message follows:\n\n"); statusdata = origstatus; } restofdata = statusdata; if (modifiers && *modifiers) { char *modtxt; /* We must finish writing the first line before putting in the modifiers */ eoln = strchr(restofdata, '\n'); if (eoln) { restofdata = eoln+1; *eoln = '\0'; fprintf(histlogfd, "%s\n", statusdata); } nldecode(modifiers); modtxt = strtok(modifiers, "\n"); while (modtxt) { fprintf(histlogfd, "%s\n", modtxt); modtxt = strtok(NULL, "\n"); } } written = fwrite(restofdata, 1, strlen(restofdata), histlogfd); if (written != strlen(restofdata)) { ok = 0; errprintf("Error writing to file %s: %s\n", fname, strerror(errno)); closestatus = fclose(histlogfd); /* Ignore any errors on close */ } else { fprintf(histlogfd, "Status unchanged in 0.00 minutes\n"); fprintf(histlogfd, "Message received from %s\n", metadata[2]); if (clienttstamp) fprintf(histlogfd, "Client data ID %d\n", (int) clienttstamp); closestatus = fclose(histlogfd); if (closestatus != 0) { ok = 0; errprintf("Error writing to file %s: %s\n", fname, strerror(errno)); } } if (!ok) remove(fname); } else { errprintf("Cannot create histlog file '%s' : %s\n", fname, strerror(errno)); } xfree(hostdash); MEMUNDEFINE(fname); } strncpy(oldcol2, ((oldcolor >= 0) ? colorname(oldcolor) : "-"), 2); strncpy(newcol2, colorname(newcolor), 2); newcol2[2] = oldcol2[2] = '\0'; if (oldcolor == -1) trend = -1; /* we dont know how bad it was */ else if (newcolor > oldcolor) trend = 2; /* It's getting worse */ else if (newcolor < oldcolor) trend = 1; /* It's getting better */ else trend = 0; /* Shouldn't happen ... */ if (save_hostevents) { char hostlogfn[PATH_MAX]; FILE *hostlogfd; MEMDEFINE(hostlogfn); sprintf(hostlogfn, "%s/%s", histdir, hostname); hostlogfd = fopen(hostlogfn, "a"); if (hostlogfd) { fprintf(hostlogfd, "%s %d %d %d %s %s %d\n", testname, (int)tstamp, (int)lastchg, (int)(tstamp - lastchg), newcol2, oldcol2, trend); fclose(hostlogfd); } else { errprintf("Cannot open host logfile '%s' : %s\n", hostlogfn, strerror(errno)); } MEMUNDEFINE(hostlogfn); } if (save_allevents) { fprintf(alleventsfd, "%s %s %d %d %d %s %s %d\n", hostname, testname, (int)tstamp, (int)lastchg, (int)(tstamp - lastchg), newcol2, oldcol2, trend); fflush(alleventsfd); } xfree(hostnamecommas); } else if ((metacount > 3) && ((strncmp(metadata[0], "@@drophost", 10) == 0))) { /* @@drophost|timestamp|sender|hostname */ hostname = metadata[3]; if (save_histlogs) { char *hostdash; char testdir[PATH_MAX]; MEMDEFINE(testdir); /* Remove all directories below the host-specific histlog dir */ p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(testdir, "%s/%s", histlogdir, hostdash); dropdirectory(testdir, 1); xfree(hostdash); MEMUNDEFINE(testdir); } if (save_hostevents) { char hostlogfn[PATH_MAX]; struct stat st; MEMDEFINE(hostlogfn); sprintf(hostlogfn, "%s/%s", histdir, hostname); if ((stat(hostlogfn, &st) == 0) && S_ISREG(st.st_mode)) { unlink(hostlogfn); } MEMUNDEFINE(hostlogfn); } if (save_statusevents) { DIR *dirfd; struct dirent *de; char *hostlead; char statuslogfn[PATH_MAX]; struct stat st; MEMDEFINE(statuslogfn); /* Remove $XYMONVAR/hist/host,name.* */ p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; hostlead = malloc(strlen(hostname) + 2); strcpy(hostlead, hostnamecommas); strcat(hostlead, "."); dirfd = opendir(histdir); if (dirfd) { while ((de = readdir(dirfd)) != NULL) { if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) { sprintf(statuslogfn, "%s/%s", histdir, de->d_name); if ((stat(statuslogfn, &st) == 0) && S_ISREG(st.st_mode)) { unlink(statuslogfn); } } } closedir(dirfd); } xfree(hostlead); xfree(hostnamecommas); MEMUNDEFINE(statuslogfn); } } else if ((metacount > 4) && ((strncmp(metadata[0], "@@droptest", 10) == 0))) { /* @@droptest|timestamp|sender|hostname|testname */ hostname = metadata[3]; testname = metadata[4]; if (save_histlogs) { char *hostdash; char testdir[PATH_MAX]; MEMDEFINE(testdir); p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(testdir, "%s/%s/%s", histlogdir, hostdash, testname); dropdirectory(testdir, 1); xfree(hostdash); MEMUNDEFINE(testdir); } if (save_statusevents) { char *hostnamecommas; char statuslogfn[PATH_MAX]; struct stat st; MEMDEFINE(statuslogfn); p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname); if ((stat(statuslogfn, &st) == 0) && S_ISREG(st.st_mode)) unlink(statuslogfn); xfree(hostnamecommas); MEMUNDEFINE(statuslogfn); } } else if ((metacount > 4) && ((strncmp(metadata[0], "@@renamehost", 12) == 0))) { /* @@renamehost|timestamp|sender|hostname|newhostname */ char *newhostname; hostname = metadata[3]; newhostname = metadata[4]; if (save_histlogs) { char *hostdash; char *newhostdash; char olddir[PATH_MAX]; char newdir[PATH_MAX]; MEMDEFINE(olddir); MEMDEFINE(newdir); p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; p = newhostdash = strdup(newhostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(olddir, "%s/%s", histlogdir, hostdash); sprintf(newdir, "%s/%s", histlogdir, newhostdash); rename(olddir, newdir); xfree(newhostdash); xfree(hostdash); MEMUNDEFINE(newdir); MEMUNDEFINE(olddir); } if (save_hostevents) { char hostlogfn[PATH_MAX]; char newhostlogfn[PATH_MAX]; MEMDEFINE(hostlogfn); MEMDEFINE(newhostlogfn); sprintf(hostlogfn, "%s/%s", histdir, hostname); sprintf(newhostlogfn, "%s/%s", histdir, newhostname); rename(hostlogfn, newhostlogfn); MEMUNDEFINE(hostlogfn); MEMUNDEFINE(newhostlogfn); } if (save_statusevents) { DIR *dirfd; struct dirent *de; char *hostlead; char *newhostnamecommas; char statuslogfn[PATH_MAX]; char newlogfn[PATH_MAX]; MEMDEFINE(statuslogfn); MEMDEFINE(newlogfn); p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; hostlead = malloc(strlen(hostname) + 2); strcpy(hostlead, hostnamecommas); strcat(hostlead, "."); p = newhostnamecommas = strdup(newhostname); while ((p = strchr(p, '.')) != NULL) *p = ','; dirfd = opendir(histdir); if (dirfd) { while ((de = readdir(dirfd)) != NULL) { if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) { char *testname = strchr(de->d_name, '.'); sprintf(statuslogfn, "%s/%s", histdir, de->d_name); sprintf(newlogfn, "%s/%s%s", histdir, newhostnamecommas, testname); rename(statuslogfn, newlogfn); } } closedir(dirfd); } xfree(newhostnamecommas); xfree(hostlead); xfree(hostnamecommas); MEMUNDEFINE(statuslogfn); MEMUNDEFINE(newlogfn); } } else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) { /* @@renametest|timestamp|sender|hostname|oldtestname|newtestname */ char *newtestname; hostname = metadata[3]; testname = metadata[4]; newtestname = metadata[5]; if (save_histlogs) { char *hostdash; char olddir[PATH_MAX]; char newdir[PATH_MAX]; MEMDEFINE(olddir); MEMDEFINE(newdir); p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(olddir, "%s/%s/%s", histlogdir, hostdash, testname); sprintf(newdir, "%s/%s/%s", histlogdir, hostdash, newtestname); rename(olddir, newdir); xfree(hostdash); MEMUNDEFINE(newdir); MEMUNDEFINE(olddir); } if (save_statusevents) { char *hostnamecommas; char statuslogfn[PATH_MAX]; char newstatuslogfn[PATH_MAX]; MEMDEFINE(statuslogfn); MEMDEFINE(newstatuslogfn); p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname); sprintf(newstatuslogfn, "%s/%s.%s", histdir, hostnamecommas, newtestname); rename(statuslogfn, newstatuslogfn); xfree(hostnamecommas); MEMUNDEFINE(newstatuslogfn); MEMUNDEFINE(statuslogfn); } } else if (strncmp(metadata[0], "@@idle", 6) == 0) { /* Nothing */ } else if (strncmp(metadata[0], "@@shutdown", 10) == 0) { running = 0; } 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); } continue; } else if (strncmp(metadata[0], "@@reload", 8) == 0) { /* Do nothing */ } } MEMUNDEFINE(newcol2); MEMUNDEFINE(oldcol2); MEMUNDEFINE(alleventsfn); MEMUNDEFINE(pidfn); fclose(alleventsfd); unlink(pidfn); return 0; }
int main(int argc, char **argv) { char buf[1024], key[1024], data[1024]; void *th = NULL; xtreePos_t n; xtreeStatus_t stat; char *rec, *p; do { printf("New, Add, Find, Delete, dUmp, deStroy : "); fflush(stdout); if (fgets(buf, sizeof(buf), stdin) == NULL) return 0; switch (*buf) { case 'N': case 'n': th = xtreeNew(strcasecmp); break; case 'A': case 'a': printf("Key:");fflush(stdout); fgets(key, sizeof(key), stdin); p = strchr(key, '\n'); if (p) *p = '\0'; printf("Data:");fflush(stdout); fgets(data, sizeof(data), stdin); p = strchr(data, '\n'); if (p) *p = '\0'; stat = xtreeAdd(th, strdup(key), strdup(data)); printf("Result: %d\n", stat); break; case 'D': case 'd': printf("Key:");fflush(stdout); fgets(key, sizeof(key), stdin); p = strchr(key, '\n'); if (p) *p = '\0'; rec = xtreeDelete(th, key); if (rec) { printf("Existing record deleted: Data was '%s'\n", rec); } else { printf("No record\n"); } break; case 'F': case 'f': printf("Key:");fflush(stdout); fgets(key, sizeof(key), stdin); p = strchr(key, '\n'); if (p) *p = '\0'; n = xtreeFind(th, key); if (n != xtreeEnd(th)) { printf("Found record: Data was '%s'\n", (char *)xtreeData(th, n)); } else { printf("No record\n"); } break; case 'U': case 'u': n = xtreeFirst(th); while (n != xtreeEnd(th)) { printf("Key '%s', data '%s'\n", (char *)xtreeKey(th, n), (char *)xtreeData(th, n)); n = xtreeNext(th, n); } break; case 'S': case 's': xtreeDestroy(th); th = NULL; break; } } while (1); return 0; }
int main(int argc, char *argv[]) { char *msg; int running; int argi, seq; int recentperiod = 3600; int maxrecentcount = 5; int logdirfull = 0; int minlogspace = 5; struct sigaction sa; /* Handle program options. */ for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--logdir=")) { clientlogdir = strchr(argv[argi], '=')+1; } else if (argnmatch(argv[argi], "--recent-period=")) { char *p = strchr(argv[argi], '='); recentperiod = 60*atoi(p+1); } else if (argnmatch(argv[argi], "--recent-count=")) { char *p = strchr(argv[argi], '='); maxrecentcount = atoi(p+1); } else if (argnmatch(argv[argi], "--minimum-free=")) { minlogspace = atoi(strchr(argv[argi], '=')+1); } else if (strcmp(argv[argi], "--debug") == 0) { /* * A global "debug" variable is available. If * it is set, then "dbgprintf()" outputs debug messages. */ debug = 1; } else if (net_worker_option(argv[argi])) { /* Handled in the subroutine */ } } if (clientlogdir == NULL) clientlogdir = xgetenv("CLIENTLOGS"); if (clientlogdir == NULL) { clientlogdir = (char *)malloc(strlen(xgetenv("XYMONVAR")) + 10); sprintf(clientlogdir, "%s/hostdata", xgetenv("XYMONVAR")); } save_errbuf = 0; /* Do the network stuff if needed */ net_worker_run(ST_HOSTDATA, LOC_STICKY, update_locator_hostdata); setup_signalhandler("xymond_hostdata"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; signal(SIGCHLD, SIG_IGN); sigaction(SIGHUP, &sa, NULL); signal(SIGPIPE, SIG_DFL); savetimes = xtreeNew(strcasecmp); running = 1; while (running) { char *eoln, *restofmsg, *p; char *metadata[MAX_META+1]; int metacount; msg = get_xymond_message(C_CLICHG, "xymond_hostdata", &seq, NULL); if (msg == NULL) { /* * get_xymond_message will return NULL if xymond_channel closes * the input pipe. We should shutdown when that happens. */ running = 0; continue; } if (nextfscheck < gettimer()) { logdirfull = (chkfreespace(clientlogdir, minlogspace, minlogspace) != 0); if (logdirfull) errprintf("Hostdata directory %s has less than %d%% free space - disabling save of data for 5 minutes\n", clientlogdir, minlogspace); nextfscheck = gettimer() + 300; } /* 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 = ""; } metacount = 0; memset(&metadata, 0, sizeof(metadata)); p = gettok(msg, "|"); while (p && (metacount < MAX_META)) { metadata[metacount++] = p; p = gettok(NULL, "|"); } metadata[metacount] = NULL; if (strncmp(metadata[0], "@@clichg", 8) == 0) { xtreePos_t handle; savetimes_t *itm; int i, recentcount; time_t now = gettimer(); char hostdir[PATH_MAX]; char fn[PATH_MAX]; FILE *fd; /* metadata[3] is the hostname */ handle = xtreeFind(savetimes, metadata[3]); if (handle != xtreeEnd(savetimes)) { itm = (savetimes_t *)xtreeData(savetimes, handle); } else { itm = (savetimes_t *)calloc(1, sizeof(savetimes_t)); itm->hostname = strdup(metadata[3]); xtreeAdd(savetimes, itm->hostname, itm); } /* See how many times we've saved the hostdata recently (within the past 'recentperiod' seconds) */ for (i=0, recentcount=0; ((i < 12) && (itm->tstamp[i] > (now - recentperiod))); i++) recentcount++; /* If it's been saved less than 'maxrecentcount' times, then save it. Otherwise just drop it */ if (!logdirfull && (recentcount < maxrecentcount)) { int written, closestatus, ok = 1; for (i = 10; (i > 0); i--) itm->tstamp[i+1] = itm->tstamp[i]; itm->tstamp[0] = now; sprintf(hostdir, "%s/%s", clientlogdir, metadata[3]); mkdir(hostdir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); sprintf(fn, "%s/%s", hostdir, metadata[4]); fd = fopen(fn, "w"); if (fd == NULL) { errprintf("Cannot create file %s: %s\n", fn, strerror(errno)); continue; } written = fwrite(restofmsg, 1, strlen(restofmsg), fd); if (written != strlen(restofmsg)) { errprintf("Cannot write hostdata file %s: %s\n", fn, strerror(errno)); closestatus = fclose(fd); /* Ignore any close errors */ ok = 0; } else { closestatus = fclose(fd); if (closestatus != 0) { errprintf("Cannot write hostdata file %s: %s\n", fn, strerror(errno)); ok = 0; } } if (!ok) remove(fn); } } /* * A "shutdown" message is sent when the master daemon * terminates. The child workers should shutdown also. */ else if (strncmp(metadata[0], "@@shutdown", 10) == 0) { running = 0; continue; } else if (strncmp(metadata[0], "@@idle", 6) == 0) { /* Ignored */ continue; } /* * A "logrotate" message is sent when the Xymon logs are * rotated. The child workers must re-open their logfiles, * typically stdin and stderr - the filename is always * provided in the XYMONCHANNEL_LOGFILENAME environment. */ 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); } continue; } else if ((metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) { /* @@drophost|timestamp|sender|hostname */ char hostdir[PATH_MAX]; snprintf(hostdir, sizeof(hostdir), "%s/%s", clientlogdir, basename(metadata[3])); dropdirectory(hostdir, 1); } else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) { /* @@renamehost|timestamp|sender|hostname|newhostname */ char oldhostdir[PATH_MAX], newhostdir[PATH_MAX]; snprintf(oldhostdir, sizeof(oldhostdir), "%s/%s", clientlogdir, basename(metadata[3])); snprintf(newhostdir, sizeof(newhostdir), "%s/%s", clientlogdir, basename(metadata[4])); rename(oldhostdir, newhostdir); if (net_worker_locatorbased()) locator_rename_host(metadata[3], metadata[4], ST_HOSTDATA); } else if (strncmp(metadata[0], "@@reload", 8) == 0) { /* Do nothing */ } } return 0; }
static int ev_included(char *hostname) { /* Callback function for filtering eventlog-hosts */ return (xtreeFind(evhopfilter, hostname) == xtreeEnd(evhopfilter)) ? 0 : 1; }
static void load_rrddefs(void) { char fn[PATH_MAX]; FILE *fd; strbuffer_t *inbuf = newstrbuffer(0); char *key = NULL, *p; char **defs = NULL; int defcount = 0; rrddeftree_t *newrec; rrddeftree = xtreeNew(strcasecmp); sprintf(fn, "%s/etc/rrddefinitions.cfg", xgetenv("XYMONHOME")); fd = stackfopen(fn, "r", NULL); if (fd == NULL) goto loaddone; while (stackfgets(inbuf, NULL)) { sanitize_input(inbuf, 1, 0); if (STRBUFLEN(inbuf) == 0) continue; if (*(STRBUF(inbuf)) == '[') { if (key && (defcount > 0)) { /* Save the current record */ newrec = (rrddeftree_t *)malloc(sizeof(rrddeftree_t)); newrec->key = key; newrec->defs = defs; newrec->count = defcount; xtreeAdd(rrddeftree, newrec->key, newrec); key = NULL; defs = NULL; defcount = 0; } key = strdup(STRBUF(inbuf)+1); p = strchr(key, ']'); if (p) *p = '\0'; } else if (key) { if (!defs) { defcount = 1; defs = (char **)malloc(sizeof(char *)); } else { defcount++; defs = (char **)realloc(defs, defcount * sizeof(char *)); } p = STRBUF(inbuf); p += strspn(p, " \t"); defs[defcount-1] = strdup(p); } } if (key && (defcount > 0)) { /* Save the last record */ newrec = (rrddeftree_t *)malloc(sizeof(rrddeftree_t)); newrec->key = key; newrec->defs = defs; newrec->count = defcount; xtreeAdd(rrddeftree, newrec->key, newrec); } stackfclose(fd); loaddone: freestrbuffer(inbuf); /* Check if the default record exists */ if (xtreeFind(rrddeftree, "") == xtreeEnd(rrddeftree)) { /* Create the default record */ newrec = (rrddeftree_t *)malloc(sizeof(rrddeftree_t)); newrec->key = strdup(""); newrec->defs = (char **)malloc(4 * sizeof(char *));; newrec->defs[0] = strdup("RRA:AVERAGE:0.5:1:576"); newrec->defs[1] = strdup("RRA:AVERAGE:0.5:6:576"); newrec->defs[2] = strdup("RRA:AVERAGE:0.5:24:576"); newrec->defs[3] = strdup("RRA:AVERAGE:0.5:288:576"); newrec->count = 4; xtreeAdd(rrddeftree, newrec->key, newrec); } }
void print_hoststatus(FILE *output, hstatus_t *itm, void * statetree, void * columns, int prio, int firsthost, int firsthostever) { char *key; time_t now; xtreePos_t colhandle; now = getcurrenttime(NULL); 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, " "); else fprintf(output, "<FONT %s>No priority</FONT>", xgetenv("XYMONPAGEROWFONT")); } else { fprintf(output, "<FONT %s>PRIO %d</FONT>", xgetenv("XYMONPAGEROWFONT"), prio); } else fprintf(output, " "); 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&NKPRIO=%d&NKTTGROUP=%s&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"); }
static void add_holiday(char *key, int year, holiday_t *newhol) { int isOK = 0; struct tm *t; time_t day; holiday_t *newitem; xtreePos_t handle; holidayset_t *hset; switch (newhol->holtype) { case HOL_ABSOLUTE: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <=31) && (!newhol->year || (newhol->year == year)) ); if (!isOK) break; day = mkday(year, newhol->month, newhol->day); t = localtime(&day); newhol->yday = t->tm_yday; break; case HOL_EASTER: isOK = (newhol->month == 0); if (!isOK) break; day = getEasterDate(year); t = localtime(&day); newhol->yday = t->tm_yday + newhol->day; break; case HOL_ADVENT: isOK = (newhol->month == 0); if (!isOK) break; day = get4AdventDate(year); t = localtime(&day); newhol->yday = t->tm_yday + newhol->day; break; case HOL_MON: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) ); if (!isOK) break; newhol->yday = getnumberedweekday(1, newhol->day, newhol->month, year); break; case HOL_TUE: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) ); if (!isOK) break; newhol->yday = getnumberedweekday(2, newhol->day, newhol->month, year); break; case HOL_WED: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) ); if (!isOK) break; newhol->yday = getnumberedweekday(3, newhol->day, newhol->month, year); break; case HOL_THU: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) ); if (!isOK) break; newhol->yday = getnumberedweekday(4, newhol->day, newhol->month, year); break; case HOL_FRI: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) ); if (!isOK) break; newhol->yday = getnumberedweekday(5, newhol->day, newhol->month, year); break; case HOL_SAT: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) ); if (!isOK) break; newhol->yday = getnumberedweekday(6, newhol->day, newhol->month, year); break; case HOL_SUN: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) ); if (!isOK) break; newhol->yday = getnumberedweekday(0, newhol->day, newhol->month, year); break; case HOL_MON_AFTER: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) ); if (!isOK) break; newhol->yday = getweekdayafter(1, newhol->day, newhol->month, year); break; case HOL_TUE_AFTER: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) ); if (!isOK) break; newhol->yday = getweekdayafter(2, newhol->day, newhol->month, year); break; case HOL_WED_AFTER: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) ); if (!isOK) break; newhol->yday = getweekdayafter(3, newhol->day, newhol->month, year); break; case HOL_THU_AFTER: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) ); if (!isOK) break; newhol->yday = getweekdayafter(4, newhol->day, newhol->month, year); break; case HOL_FRI_AFTER: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) ); if (!isOK) break; newhol->yday = getweekdayafter(5, newhol->day, newhol->month, year); break; case HOL_SAT_AFTER: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) ); if (!isOK) break; newhol->yday = getweekdayafter(6, newhol->day, newhol->month, year); break; case HOL_SUN_AFTER: isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) ); if (!isOK) break; newhol->yday = getweekdayafter(0, newhol->day, newhol->month, year); break; } if (!isOK) { errprintf("Error in holiday definition %s\n", newhol->desc); return; } newitem = (holiday_t *)calloc(1, sizeof(holiday_t)); newitem->holtype = newhol->holtype; newitem->day = newhol->day; newitem->month = newhol->month; newitem->desc = strdup(newhol->desc); newitem->yday = newhol->yday; handle = xtreeFind(holidays, key); if (handle == xtreeEnd(holidays)) { hset = (holidayset_t *)calloc(1, sizeof(holidayset_t)); hset->key = strdup(key); xtreeAdd(holidays, hset->key, hset); } else { hset = (holidayset_t *)xtreeData(holidays, handle); } if (hset->head == NULL) { hset->head = hset->tail = newitem; } else { hset->tail->next = newitem; hset->tail = hset->tail->next; } }
int load_holidays(int year) { static void *configholidays = NULL; char fn[PATH_MAX]; FILE *fd; strbuffer_t *inbuf; holiday_t newholiday; xtreePos_t handle, commonhandle; char *setname = NULL; holidayset_t *commonhols; MEMDEFINE(fn); if (year == 0) { time_t tnow; struct tm *now; tnow = getcurrenttime(NULL); now = localtime(&tnow); year = now->tm_year; } else if (year > 1000) { year -= 1900; } sprintf(fn, "%s/etc/holidays.cfg", xgetenv("XYMONHOME")); /* First check if there were no modifications at all */ if (configholidays) { /* if the new year begins, the holidays have to be recalculated */ if (!stackfmodified(configholidays) && (year == current_year)){ dbgprintf("No files modified, skipping reload of %s\n", fn); MEMUNDEFINE(fn); return 0; } else { stackfclist(&configholidays); configholidays = NULL; } } reset_holidays(); fd = stackfopen(fn, "r", &configholidays); if (!fd) { errprintf("Cannot open configuration file %s\n", fn); MEMUNDEFINE(fn); return 0; } memset(&newholiday,0,sizeof(holiday_t)); inbuf = newstrbuffer(0); while (stackfgets(inbuf, NULL)) { char *p, *delim, *arg1, *arg2; sanitize_input(inbuf, 1, 0); if (STRBUFLEN(inbuf) == 0) continue; p = STRBUF(inbuf); if (strncasecmp(p, "HOLIDAYLIKEWEEKDAY=", 19) == 0) { p+=19; holidays_like_weekday = atoi(p); if (holidays_like_weekday < -1 || holidays_like_weekday > 6) { holidays_like_weekday = -1; errprintf("Invalid HOLIDAYLIKEWEEKDAY in %s\n", fn); } continue; } if (*p == '[') { /* New set of holidays */ if (setname) xfree(setname); delim = strchr(p, ']'); if (delim) *delim = '\0'; setname = strdup(p+1); continue; } delim = strchr(p, ':'); if (delim) { memset(&newholiday,0,sizeof(holiday_t)); if (delim == p) { newholiday.desc = "untitled"; } else { *delim = '\0'; newholiday.desc = p; p=delim+1; } } arg1 = strtok(p, "="); while (arg1) { arg2=strtok(NULL," ,;\t\n\r"); if (!arg2) break; if (strncasecmp(arg1, "TYPE", 4) == 0) { if (strncasecmp(arg2, "STATIC", 6) == 0) newholiday.holtype = HOL_ABSOLUTE; else if (strncasecmp(arg2, "EASTER", 6) == 0) newholiday.holtype = HOL_EASTER; else if (strncasecmp(arg2, "4ADVENT", 7) == 0) newholiday.holtype = HOL_ADVENT; else if (strncasecmp(arg2, "MON", 3) == 0) newholiday.holtype = HOL_MON; else if (strncasecmp(arg2, "TUE", 3) == 0) newholiday.holtype = HOL_TUE; else if (strncasecmp(arg2, "WED", 3) == 0) newholiday.holtype = HOL_WED; else if (strncasecmp(arg2, "THU", 3) == 0) newholiday.holtype = HOL_THU; else if (strncasecmp(arg2, "FRI", 3) == 0) newholiday.holtype = HOL_FRI; else if (strncasecmp(arg2, "SAT", 3) == 0) newholiday.holtype = HOL_SAT; else if (strncasecmp(arg2, "SUN", 3) == 0) newholiday.holtype = HOL_SUN; else if (strncasecmp(arg2, "+MON", 4) == 0) newholiday.holtype = HOL_MON_AFTER; else if (strncasecmp(arg2, "+TUE", 4) == 0) newholiday.holtype = HOL_TUE_AFTER; else if (strncasecmp(arg2, "+WED", 4) == 0) newholiday.holtype = HOL_WED_AFTER; else if (strncasecmp(arg2, "+THU", 4) == 0) newholiday.holtype = HOL_THU_AFTER; else if (strncasecmp(arg2, "+FRI", 4) == 0) newholiday.holtype = HOL_FRI_AFTER; else if (strncasecmp(arg2, "+SAT", 4) == 0) newholiday.holtype = HOL_SAT_AFTER; else if (strncasecmp(arg2, "+SUN", 4) == 0) newholiday.holtype = HOL_SUN_AFTER; } else if (strncasecmp(arg1, "MONTH", 5) == 0) { newholiday.month=atoi(arg2); } else if (strncasecmp(arg1, "DAY", 3) == 0) { newholiday.day=atoi(arg2); } else if (strncasecmp(arg1, "OFFSET", 6) == 0) { newholiday.day=atoi(arg2); } else if (strncasecmp(arg1, "YEAR", 4) == 0) { newholiday.year=atoi(arg2); if (newholiday.year > 1000) { newholiday.year -= 1900; } } arg1 = strtok(NULL,"="); } add_holiday((setname ? setname : ""), year, &newholiday); } stackfclose(fd); freestrbuffer(inbuf); commonhandle = xtreeFind(holidays, ""); commonhols = (commonhandle != xtreeEnd(holidays)) ? (holidayset_t *)xtreeData(holidays, commonhandle) : NULL; for (handle = xtreeFirst(holidays); (handle != xtreeEnd(holidays)); handle = xtreeNext(holidays, handle)) { holidayset_t *oneset = (holidayset_t *)xtreeData(holidays, handle); if (commonhols && (oneset != commonhols)) { /* Add the common holidays to this set */ holiday_t *walk; for (walk = commonhols->head; (walk); walk = walk->next) add_holiday(oneset->key, year, walk); } oneset->head = msort(oneset->head, record_compare, record_getnext, record_setnext); } MEMUNDEFINE(fn); current_year = year; return 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; }
void send_test_results(listhead_t *head, char *collector, int issubmodule, char *location, int usebackfeed) { char msgline[4096]; listitem_t *walk; xtreePos_t handle; void *hostresults = xtreeNew(strcasecmp); if (usebackfeed) combo_start_local(); else combo_start(); for (walk = head->head; (walk); walk = walk->next) { hostresult_t *hres; myconn_t *rec = (myconn_t *)walk->data; char *s; if (rec->ignoreresult) continue; switch (rec->talkprotocol) { case TALK_PROTO_PING: if (!issubmodule && (rec->talkresult == TALK_OK)) { add_to_sub_queue(rec, "ping", location, NULL); continue; } break; #ifdef HAVE_LDAP case TALK_PROTO_LDAP: if (!issubmodule && (rec->talkresult == TALK_OK)) { char *creds = xmh_item(rec->hostinfo, XMH_LDAPLOGIN); add_to_sub_queue(rec, "ldap", location, creds, NULL); continue; } break; #endif case TALK_PROTO_EXTERNAL: if (!issubmodule && (rec->talkresult == TALK_OK)) { if (strncmp(rec->testspec, "rpc=", 4) == 0) add_to_sub_queue(rec, "rpc", location, NULL); else add_to_sub_queue(rec, rec->testspec, location, NULL); continue; } break; default: break; } handle = xtreeFind(hostresults, xmh_item(rec->hostinfo, XMH_HOSTNAME)); if (handle == xtreeEnd(hostresults)) { hres = (hostresult_t *)calloc(1, sizeof(hostresult_t)); hres->hinfo = rec->hostinfo; hres->txt = newstrbuffer(0); xtreeAdd(hostresults, xmh_item(rec->hostinfo, XMH_HOSTNAME), hres); snprintf(msgline, sizeof(msgline), "client/%s %s.netcollect netcollect\n", collector, xmh_item(rec->hostinfo, XMH_HOSTNAME)); addtobuffer(hres->txt, msgline); } else { hres = xtreeData(hostresults, handle); } switch (rec->talkprotocol) { case TALK_PROTO_DNSQUERY: snprintf(msgline, sizeof(msgline), "\n[dns=%s]\n", rec->testspec); addtobuffer(hres->txt, msgline); break; case TALK_PROTO_PING: snprintf(msgline, sizeof(msgline), "\n[ping=%s]\n", rec->netparams.destinationip); addtobuffer(hres->txt, msgline); snprintf(msgline, sizeof(msgline), "SourceSpec: %s\n", rec->testspec); addtobuffer(hres->txt, msgline); break; default: snprintf(msgline, sizeof(msgline), "\n[%s]\n", rec->testspec); addtobuffer(hres->txt, msgline); break; } snprintf(msgline, sizeof(msgline), "Handler: %s\n", talkproto_names[rec->talkprotocol]); addtobuffer(hres->txt, msgline); snprintf(msgline, sizeof(msgline), "StartTime: %d\nEndTime: %d\n", (int)rec->teststarttime, (int)rec->testendtime); addtobuffer(hres->txt, msgline); if (rec->netparams.lookupstring) { snprintf(msgline, sizeof(msgline), "TargetHostname: %s\n", rec->netparams.lookupstring); addtobuffer(hres->txt, msgline); } snprintf(msgline, sizeof(msgline), "TargetIP: %s\n", rec->netparams.destinationip); addtobuffer(hres->txt, msgline); snprintf(msgline, sizeof(msgline), "TargetPort: %d\n", rec->netparams.destinationport); addtobuffer(hres->txt, msgline); if (rec->netparams.sourceip) { snprintf(msgline, sizeof(msgline), "SourceIP: %s\n", rec->netparams.sourceip); addtobuffer(hres->txt, msgline); } if (location) { snprintf(msgline, sizeof(msgline), "Location: %s\n", location); addtobuffer(hres->txt, msgline); } if (rec->talkprotocol == TALK_PROTO_PING) s = "ICMP"; else { switch (rec->netparams.socktype) { case CONN_SOCKTYPE_STREAM: s = "TCP"; break; case CONN_SOCKTYPE_DGRAM: s = "UDP"; break; default: s = "UNKNOWN"; break; } } snprintf(msgline, sizeof(msgline), "Protocol: %s\n", s); addtobuffer(hres->txt, msgline); switch (rec->netparams.sslhandling) { case CONN_SSL_NO: s = "NO"; break; case CONN_SSL_YES: s = "YES"; break; case CONN_SSL_STARTTLS_CLIENT: s = "STARTTLS_CLIENT"; break; case CONN_SSL_STARTTLS_SERVER: s = "STARTTLS_SERVER"; break; default: s = "UNKNOWN"; break; } snprintf(msgline, sizeof(msgline), "SSL: %s\n", s); addtobuffer(hres->txt, msgline); switch (rec->talkresult) { case TALK_CONN_FAILED: s = "CONN_FAILED"; break; case TALK_CONN_TIMEOUT: s = "CONN_TIMEOUT"; break; case TALK_OK: s = "OK"; break; case TALK_BADDATA: s = "BADDATA"; break; case TALK_BADSSLHANDSHAKE: s = "BADSSLHANDSHAKE"; break; case TALK_INTERRUPTED: s = "INTERRUPTED"; break; case TALK_CANNOT_RESOLVE: s = "CANNOT_RESOLVE"; break; case TALK_MODULE_FAILED: s = "MODULE_FAILED"; break; default: s = "UNKNOWN"; break; } snprintf(msgline, sizeof(msgline), "Status: %s\n", s); addtobuffer(hres->txt, msgline); snprintf(msgline, sizeof(msgline), "TestID: %lu\nElapsedMS: %d.%02d\nDNSMS: %d.%02d\nTimeoutMS: %d\nIntervalMS: %d\n", rec->testid, (rec->elapsedus / 1000), (rec->elapsedus % 1000), (rec->dnselapsedus / 1000), (rec->dnselapsedus % 1000), rec->timeout*1000, rec->interval*1000); addtobuffer(hres->txt, msgline); snprintf(msgline, sizeof(msgline), "BytesRead: %u\nBytesWritten: %u\n", rec->bytesread, rec->byteswritten); addtobuffer(hres->txt, msgline); if (rec->peercertificate) { char exps[50]; addtobuffer(hres->txt, "PeerCertificateSubject: "); addtobuffer(hres->txt, rec->peercertificate); addtobuffer(hres->txt, "\n"); addtobuffer(hres->txt, "PeerCertificateIssuer: "); addtobuffer(hres->txt, rec->peercertificateissuer); addtobuffer(hres->txt, "\n"); strftime(exps, sizeof(exps), "%Y-%m-%d %H:%M:%S UTC", gmtime(&rec->peercertificatestart)); snprintf(msgline, sizeof(msgline), "PeerCertificateStart: %d %s\n", (int)rec->peercertificatestart, exps); addtobuffer(hres->txt, msgline); strftime(exps, sizeof(exps), "%Y-%m-%d %H:%M:%S UTC", gmtime(&rec->peercertificateexpiry)); snprintf(msgline, sizeof(msgline), "PeerCertificateExpiry: %d %s\n", (int)rec->peercertificateexpiry, exps); addtobuffer(hres->txt, msgline); snprintf(msgline, sizeof(msgline), "PeerCertificateKeysize: %d\n", (int)rec->peercertificatekeysize); addtobuffer(hres->txt, msgline); snprintf(msgline, sizeof(msgline), "PeerCertificateDetails: %d\n", (int)strlen(rec->peercertificatedetails)+1); addtobuffer(hres->txt, msgline); addtobuffer(hres->txt, rec->peercertificatedetails); addtobuffer(hres->txt, "\n"); } switch (rec->talkprotocol) { case TALK_PROTO_PLAIN: result_plain(rec, hres->txt); break; case TALK_PROTO_NTP: result_ntp(rec, hres->txt); break; case TALK_PROTO_HTTP: result_http(rec, hres->txt); break; case TALK_PROTO_DNSQUERY: result_dns(rec, hres->txt); break; case TALK_PROTO_PING: result_subqueue("PING", rec, hres->txt); break; #ifdef HAVE_LDAP case TALK_PROTO_LDAP: result_subqueue("LDAP", rec, hres->txt); break; #endif case TALK_PROTO_EXTERNAL: result_subqueue(rec->testspec, rec, hres->txt); break; default: break; } } for (handle = xtreeFirst(hostresults); handle != xtreeEnd(hostresults); handle = xtreeNext(hostresults, handle)) { hostresult_t *hres = xtreeData(hostresults, handle); combo_add(hres->txt); freestrbuffer(hres->txt); xtreeDelete(hostresults, xmh_item(hres->hinfo, XMH_HOSTNAME)); xfree(hres); } xtreeDestroy(hostresults); combo_end(); }