static int ip_acl_onload(noit_image_t *self) { int i, cnt; noit_conf_section_t *acl_c; ip_acl_module_id = noit_check_register_module("ip_acl"); if(ip_acl_module_id < 0) return -1; acl_c = noit_conf_get_sections(NULL, "/noit/acls//acl", &cnt); if(acl_c) { for(i=0; i<cnt; i++) { char *name; int j, rcnt, arcnt = 0; noit_conf_section_t *rule_c; if(noit_conf_get_string(acl_c[i], "@name", &name)) { rule_c = noit_conf_get_sections(acl_c[i], "rule", &rcnt); if(rule_c) { btrie *acl = calloc(1, sizeof(*acl)); for(j=0; j<rcnt; j++) { int mask = -1, rv; char dirstr[16] = "unspecified"; char *cp, target[256] = ""; union { struct in_addr addr4; struct in6_addr addr6; } a; noit_conf_get_stringbuf(rule_c[j], "self::node()", target, sizeof(target)); if(NULL != (cp = strchr(target, '/'))) { *cp++ = '\0'; mask = atoi(cp); } if(!noit_conf_get_stringbuf(rule_c[j], "@type", dirstr, sizeof(dirstr)) || (strcmp(dirstr, "deny") && strcmp(dirstr, "allow"))) { noitL(noit_error, "Unknown acl rule type \"%s\" in acl \"%s\"\n", dirstr, name); } else if(inet_pton(AF_INET, target, &a) == 1) { if(mask == -1) mask = 32; noit_add_route_ipv4(acl, &a.addr4, mask, strcmp(dirstr, "allow") ? DENY_PTR : ALLOW_PTR); arcnt++; } else if(inet_pton(AF_INET6, target, &a) == 1) { if(mask == -1) mask = 128; noit_add_route_ipv6(acl, &a.addr6, mask, strcmp(dirstr, "allow") ? DENY_PTR : ALLOW_PTR); arcnt++; } } noitL(noit_error, "ACL %s/%p -> %d/%d rules\n", name, acl, arcnt, rcnt); noit_hash_replace(&acls, name, strlen(name), acl, free, free_btrie); free(rule_c); } } } free(acl_c); } return 0; }
void noit_filters_from_conf() { noit_conf_section_t *sets; int i, cnt; sets = noit_conf_get_sections(NULL, "/noit/filtersets//filterset", &cnt); for(i=0; i<cnt; i++) { noit_filter_compile_add(sets[i]); } free(sets); }
static int noit_console_filter_show(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *state, void *closure) { noit_conf_t_userdata_t *info; char xpath[1024]; xmlNodePtr fsnode; noit_conf_section_t *rules; int i, rulecnt; info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); snprintf(xpath, sizeof(xpath), "/%s", info->path); fsnode = noit_conf_get_section(NULL, xpath); if(!fsnode) { nc_printf(ncct, "internal error\n"); return -1; } rules = noit_conf_get_sections(fsnode, "rule", &rulecnt); for(i=0; i<rulecnt; i++) { char val[256]; val[0] = '\0'; noit_conf_get_stringbuf(rules[i], "@type", val, sizeof(val)); nc_printf(ncct, "Rule %d [%s]:\n", i+1, val); #define DUMP_ATTR(a) do { \ char *vstr; \ noit_conf_section_t ht; \ int cnt; \ ht = noit_conf_get_sections(rules[i], #a, &cnt); \ if(ht && cnt) { \ nc_printf(ncct, "\t%s: hash match of %d items\n", #a, cnt); \ } \ else if(noit_conf_get_string(rules[i], "@" #a, &vstr)) { \ nc_printf(ncct, "\t%s: /%s/\n", #a, val); \ free(vstr); \ } \ free(ht); \ } while(0) DUMP_ATTR(target); DUMP_ATTR(module); DUMP_ATTR(name); DUMP_ATTR(metric); } if(rules) free(rules); return 0; }
void noit_filter_compile_add(noit_conf_section_t setinfo) { noit_conf_section_t *rules; int j, fcnt; char filterset_name[256]; filterset_t *set; if(!noit_conf_get_stringbuf(setinfo, "@name", filterset_name, sizeof(filterset_name))) { noitL(noit_error, "filterset with no name, skipping as it cannot be referenced.\n"); return; } set = calloc(1, sizeof(*set)); set->ref_cnt = 1; set->name = strdup(filterset_name); rules = noit_conf_get_sections(setinfo, "rule", &fcnt); /* Here we will work through the list backwards pushing the rules on * the front of the list. That way we can simply walk them in order * for the application process. */ noitL(noit_debug, "Compiling filterset '%s'\n", set->name); for(j=fcnt-1; j>=0; j--) { filterrule_t *rule; char buffer[256]; if(!noit_conf_get_stringbuf(rules[j], "@type", buffer, sizeof(buffer)) || (strcmp(buffer, "accept") && strcmp(buffer, "allow") && strcmp(buffer, "deny"))) { noitL(noit_error, "rule must have type 'accept' or 'allow' or 'deny'\n"); continue; } noitL(noit_debug, "Prepending %s into %s\n", buffer, set->name); rule = calloc(1, sizeof(*rule)); rule->type = (!strcmp(buffer, "accept") || !strcmp(buffer, "allow")) ? NOIT_FILTER_ACCEPT : NOIT_FILTER_DENY; /* Compile our rules */ #define RULE_COMPILE(rname) do { \ char *longre = NULL; \ if(noit_conf_get_string(rules[j], "@" #rname, &longre)) { \ const char *error; \ int erroffset; \ rule->rname = pcre_compile(longre, 0, &error, &erroffset, NULL); \ if(!rule->rname) { \ noitL(noit_error, "set '%s' rule '%s: %s' compile failed: %s\n", \ set->name, #rname, longre, error ? error : "???"); \ } \ else { \ rule->rname##_e = pcre_study(rule->rname, 0, &error); \ } \ free(longre); \ } \ } while(0) RULE_COMPILE(target); RULE_COMPILE(module); RULE_COMPILE(name); RULE_COMPILE(metric); rule->next = set->rules; set->rules = rule; } free(rules); LOCKFS(); noit_hash_replace(filtersets, set->name, strlen(set->name), (void *)set, NULL, filterset_free); UNLOCKFS(); }
void noit_poller_process_checks(const char *xpath) { int i, flags, cnt = 0; noit_conf_section_t *sec; __config_load_generation++; sec = noit_conf_get_sections(NULL, xpath, &cnt); for(i=0; i<cnt; i++) { void *vcheck; char uuid_str[37]; char target[256] = ""; char module[256] = ""; char name[256] = ""; char filterset[256] = ""; char oncheck[1024] = ""; int no_period = 0; int no_oncheck = 0; int period = 0, timeout = 0; noit_boolean disabled = noit_false, busted = noit_false; uuid_t uuid, out_uuid; noit_hash_table *options; #define NEXT(...) noitL(noit_stderr, __VA_ARGS__); continue #define MYATTR(type,a,...) noit_conf_get_##type(sec[i], "@" #a, __VA_ARGS__) #define INHERIT(type,a,...) \ noit_conf_get_##type(sec[i], "ancestor-or-self::node()/@" #a, __VA_ARGS__) if(!MYATTR(stringbuf, uuid, uuid_str, sizeof(uuid_str))) { noitL(noit_stderr, "check %d has no uuid\n", i+1); continue; } if(uuid_parse(uuid_str, uuid)) { noitL(noit_stderr, "check uuid: '%s' is invalid\n", uuid_str); continue; } if(!INHERIT(stringbuf, target, target, sizeof(target))) { noitL(noit_stderr, "check uuid: '%s' has no target\n", uuid_str); busted = noit_true; } if(!INHERIT(stringbuf, module, module, sizeof(module))) { noitL(noit_stderr, "check uuid: '%s' has no module\n", uuid_str); busted = noit_true; } if(!INHERIT(stringbuf, filterset, filterset, sizeof(filterset))) filterset[0] = '\0'; if(!MYATTR(stringbuf, name, name, sizeof(name))) strlcpy(name, module, sizeof(name)); if(!INHERIT(int, period, &period) || period == 0) no_period = 1; if(!INHERIT(stringbuf, oncheck, oncheck, sizeof(oncheck)) || !oncheck[0]) no_oncheck = 1; if(no_period && no_oncheck) { noitL(noit_stderr, "check uuid: '%s' has neither period nor oncheck\n", uuid_str); busted = noit_true; } if(!(no_period || no_oncheck)) { noitL(noit_stderr, "check uuid: '%s' has oncheck and period.\n", uuid_str); busted = noit_true; } if(!INHERIT(int, timeout, &timeout)) { noitL(noit_stderr, "check uuid: '%s' has no timeout\n", uuid_str); busted = noit_true; } if(!no_period && timeout >= period) { noitL(noit_stderr, "check uuid: '%s' timeout > period\n", uuid_str); timeout = period/2; } options = noit_conf_get_hash(sec[i], "config"); INHERIT(boolean, disable, &disabled); flags = 0; if(busted) flags |= (NP_UNCONFIG|NP_DISABLED); else if(disabled) flags |= NP_DISABLED; if(noit_hash_retrieve(&polls, (char *)uuid, UUID_SIZE, &vcheck)) { noit_check_t *existing_check = (noit_check_t *)vcheck; /* Once set, we can never change it. */ assert(!existing_check->module || !existing_check->module[0] || !strcmp(existing_check->module, module)); /* Only set it if it is not yet set */ if(!existing_check->module || !existing_check->module[0]) { if(existing_check->module) free(existing_check->module); existing_check->module = strdup(module); } noit_check_update(existing_check, target, name, filterset, options, period, timeout, oncheck[0] ? oncheck : NULL, flags); noitL(noit_debug, "reloaded uuid: %s\n", uuid_str); } else { noit_poller_schedule(target, module, name, filterset, options, period, timeout, oncheck[0] ? oncheck : NULL, flags, uuid, out_uuid); noitL(noit_debug, "loaded uuid: %s\n", uuid_str); } noit_hash_destroy(options, free, free); free(options); } if(sec) free(sec); }
void noit_http_rest_load_rules() { int ai, cnt = 0; noit_conf_section_t *acls; char path[256]; struct noit_rest_acl *newhead = NULL, *oldacls, *remove_acl; struct noit_rest_acl_rule *remove_rule; snprintf(path, sizeof(path), "//rest//acl"); acls = noit_conf_get_sections(NULL, path, &cnt); noitL(noit_debug, "Found %d acl stanzas\n", cnt); for(ai = cnt-1; ai>=0; ai--) { char tbuff[32]; struct noit_rest_acl *newacl; int ri, rcnt = 0; noit_boolean default_allow = noit_false; noit_conf_section_t *rules; newacl = calloc(1, sizeof(*newacl)); newacl->next = newhead; newhead = newacl; if(noit_conf_get_stringbuf(acls[ai], "@type", tbuff, sizeof(tbuff)) && !strcmp(tbuff, "allow")) newacl->allow = noit_true; #define compile_re(node, cont, name) do { \ char buff[256]; \ if(noit_conf_get_stringbuf(node, "@" #name, buff, sizeof(buff))) { \ const char *error; \ int erroffset; \ cont->name = pcre_compile(buff, 0, &error, &erroffset, NULL); \ } \ } while(0) newacl->allow = default_allow; compile_re(acls[ai], newacl, cn); compile_re(acls[ai], newacl, url); rules = noit_conf_get_sections(acls[ai], "rule", &rcnt); for(ri = rcnt - 1; ri >= 0; ri--) { struct noit_rest_acl_rule *newacl_rule; newacl_rule = calloc(1, sizeof(*newacl_rule)); newacl_rule->next = newacl->rules; newacl->rules = newacl_rule; if(noit_conf_get_stringbuf(rules[ri], "@type", tbuff, sizeof(tbuff)) && !strcmp(tbuff, "allow")) newacl_rule->allow = noit_true; compile_re(rules[ri], newacl_rule, cn); compile_re(rules[ri], newacl_rule, url); } free(rules); } free(acls); oldacls = global_rest_acls; global_rest_acls = newhead; while(oldacls) { remove_acl = oldacls->next; while(oldacls->rules) { remove_rule = oldacls->rules->next; if(oldacls->rules->cn) pcre_free(oldacls->rules->cn); if(oldacls->rules->url) pcre_free(oldacls->rules->url); free(oldacls->rules); oldacls->rules = remove_rule; } if(oldacls->cn) pcre_free(oldacls->cn); if(oldacls->url) pcre_free(oldacls->url); free(oldacls); oldacls = remove_acl; } }
void noit_listener_reconfig(const char *toplevel) { int i, cnt = 0; noit_conf_section_t *listener_configs; char path[256]; snprintf(path, sizeof(path), "/%s/listeners//listener", toplevel ? toplevel : "*"); listener_configs = noit_conf_get_sections(NULL, path, &cnt); noitL(noit_debug, "Found %d %s stanzas\n", cnt, path); for(i=0; i<cnt; i++) { char address[256]; char type[256]; unsigned short port; int portint; int backlog; eventer_func_t f; noit_boolean ssl; noit_hash_table *sslconfig, *config; if(!noit_conf_get_stringbuf(listener_configs[i], "ancestor-or-self::node()/@type", type, sizeof(type))) { noitL(noit_error, "No type specified in listener stanza %d\n", i+1); continue; } f = eventer_callback_for_name(type); if(!f) { noitL(noit_error, "Cannot find handler for listener type: '%s'\n", type); continue; } if(!noit_conf_get_stringbuf(listener_configs[i], "ancestor-or-self::node()/@address", address, sizeof(address))) { address[0] = '*'; address[1] = '\0'; } if(!noit_conf_get_int(listener_configs[i], "ancestor-or-self::node()/@port", &portint)) portint = 0; port = (unsigned short) portint; if(address[0] != '/' && (portint == 0 || (port != portint))) { /* UNIX sockets don't require a port (they'll ignore it if specified */ noitL(noit_error, "Invalid port [%d] specified in stanza %d\n", port, i+1); continue; } if(noit_listener_should_skip(address, port)) { if(port) noitL(noit_error, "Operator forced skipping listener %s:%d\n", address, port); else noitL(noit_error, "Operator forced skipping listener %s\n", address); continue; } if(!noit_conf_get_int(listener_configs[i], "ancestor-or-self::node()/@backlog", &backlog)) backlog = 5; if(!noit_conf_get_boolean(listener_configs[i], "ancestor-or-self::node()/@ssl", &ssl)) ssl = noit_false; sslconfig = ssl ? noit_conf_get_hash(listener_configs[i], "sslconfig") : NULL; config = noit_conf_get_hash(listener_configs[i], "config"); if(noit_listener(address, port, SOCK_STREAM, backlog, sslconfig, config, f, NULL) != 0) { noit_hash_destroy(config,free,free); free(config); } if(sslconfig) { /* A copy of this is made within noit_listener */ noit_hash_destroy(sslconfig,free,free); free(sslconfig); } } free(listener_configs); }