예제 #1
0
noit_boolean
noit_apply_filterset(const char *filterset,
                     noit_check_t *check,
                     metric_t *metric) {
  /* We pass in filterset here just in case someone wants to apply
   * a filterset other than check->filterset.. You never know.
   */
  void *vfs;
  if(!filterset) return noit_true;   /* No filter */
  if(!filtersets) return noit_false; /* Couldn't possibly match */

  LOCKFS();
  if(noit_hash_retrieve(filtersets, filterset, strlen(filterset), &vfs)) {
    filterset_t *fs = (filterset_t *)vfs;
    filterrule_t *r;
    noit_atomic_inc32(&fs->ref_cnt);
    UNLOCKFS();
#define MATCHES(rname, value) noit_apply_filterrule(r->rname, r->rname##_e, value)
    for(r = fs->rules; r; r = r->next) {
      if(MATCHES(target, check->target) &&
         MATCHES(module, check->module) &&
         MATCHES(name, check->name) &&
         MATCHES(metric, metric->metric_name))
        return (r->type == NOIT_FILTER_ACCEPT) ? noit_true : noit_false;
    }
    filterset_free(fs);
    return noit_false;
  }
  UNLOCKFS();
  return noit_false;
}
예제 #2
0
int
noit_filter_exists(const char *name) {
  int exists;
  void *v;
  LOCKFS();
  exists = noit_hash_retrieve(filtersets, name, strlen(name), &v);
  UNLOCKFS();
  return exists;
}
예제 #3
0
int
noit_filter_remove(noit_conf_section_t vnode) {
  int removed;
  char *name = (char *)xmlGetProp(vnode, (xmlChar *)"name");
  if(!name) return 0;
  LOCKFS();
  removed = noit_hash_delete(filtersets, name, strlen(name),
                             NULL, filterset_free);
  UNLOCKFS();
  return removed;
}
예제 #4
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();
}
예제 #5
0
static int
noit_console_filter_configure(noit_console_closure_t ncct,
                              int argc, char **argv,
                              noit_console_state_t *state,
                              void *closure) {
  xmlNodePtr parent, fsnode = NULL;
  int rv = -1;
  noit_conf_t_userdata_t *info;
  char xpath[1024];

  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA);
  if(!info) {
    nc_printf(ncct, "internal error\n");
    goto cleanup;
  }
  if(strncmp(info->path, "/filtersets/", strlen("/filtersets/")) &&
     strcmp(info->path, "/filtersets")) {
    nc_printf(ncct, "filterset only allows inside /filtersets (not %s)\n",
              info->path);
    goto cleanup;
  }
  if(argc != 1) {
    nc_printf(ncct, "filterset requires one argument\n");
    goto cleanup;
  }
  snprintf(xpath, sizeof(xpath), "/%s", info->path);
  parent = noit_conf_get_section(NULL, xpath);
  if(!parent) {
    nc_printf(ncct, "internal error, can't final current working path\n");
    goto cleanup;
  }
  snprintf(xpath, sizeof(xpath), "filterset[@name=\"%s\"]", argv[0]);
  fsnode = noit_conf_get_section(parent, xpath);
  if(closure) {
    int removed;
    removed = noit_filter_remove(fsnode);
    nc_printf(ncct, "%sremoved filterset '%s'\n",
              removed ? "" : "failed to ", argv[0]);
    if(removed) {
      xmlUnlinkNode(fsnode);
      xmlFreeNode(fsnode);
    }
    rv = !removed;
    goto cleanup;
  }
  if(!fsnode) {
    void *vfs;
    nc_printf(ncct, "Cannot find filterset '%s'\n", argv[0]);
    LOCKFS();
    if(noit_hash_retrieve(filtersets, argv[0], strlen(argv[0]), &vfs)) {
      UNLOCKFS();
      nc_printf(ncct, "filter of the same name already exists\n");
      goto cleanup;
    }
    UNLOCKFS();
    /* Fine the parent path */
    fsnode = xmlNewNode(NULL, (xmlChar *)"filterset");
    xmlSetProp(fsnode, (xmlChar *)"name", (xmlChar *)argv[0]);
    xmlAddChild(parent, fsnode);
    nc_printf(ncct, "created new filterset\n");
  }

  if(info) {
    char *xmlpath = NULL;
    if(info->path) free(info->path);
    xmlpath = (char *)xmlGetNodePath(fsnode);
    info->path = strdup(xmlpath + strlen("/noit"));
    free(xmlpath);
    strlcpy(info->filter_name, argv[0], sizeof(info->filter_name));
    if(state) {
      noit_console_state_push_state(ncct, state);
      noit_console_state_init(ncct);
    }
  }
 cleanup:
  return rv;
}
예제 #6
0
mtev_boolean
noit_apply_filterset(const char *filterset,
                     noit_check_t *check,
                     metric_t *metric) {
  /* We pass in filterset here just in case someone wants to apply
   * a filterset other than check->filterset.. You never know.
   */
  void *vfs;
  if(!filterset) return mtev_true;   /* No filter */
  if(!filtersets) return mtev_false; /* Couldn't possibly match */

  LOCKFS();
  if(mtev_hash_retrieve(filtersets, filterset, strlen(filterset), &vfs)) {
    filterset_t *fs = (filterset_t *)vfs;
    filterrule_t *r, *skipto_rule = NULL;
    int idx = 0;
    mtev_atomic_inc32(&fs->ref_cnt);
    UNLOCKFS();
#define MATCHES(rname, value) noit_apply_filterrule(r->rname##_ht, r->rname ? r->rname : r->rname##_override, r->rname ? r->rname##_e : NULL, value)
    for(r = fs->rules; r; r = r->next) {
      int need_target, need_module, need_name, need_metric;
      /* If we're targeting a skipto rule, match or continue */
      idx++;
      if(skipto_rule && skipto_rule != r) continue;
      skipto_rule = NULL;

      need_target = !MATCHES(target, check->target);
      need_module = !MATCHES(module, check->module);
      need_name = !MATCHES(name, check->name);
      need_metric = !MATCHES(metric, metric->metric_name);
      if(!need_target && !need_module && !need_name && !need_metric) {
        if(r->type == NOIT_FILTER_SKIPTO) {
          skipto_rule = r->skipto_rule;
          continue;
        }
        return (r->type == NOIT_FILTER_ACCEPT) ? mtev_true : mtev_false;
      }
      /* If we need some of these and we have an auto setting that isn't fulfilled for each of them, we can add and succeed */
#define CHECK_ADD(rname) (!need_##rname || (r->rname##_auto_hash_max > 0 && r->rname##_ht && mtev_hash_size(r->rname##_ht) < r->rname##_auto_hash_max))
      if(CHECK_ADD(target) && CHECK_ADD(module) && CHECK_ADD(name) && CHECK_ADD(metric)) {
#define UPDATE_FILTER_RULE(rnum, rname, value) do { \
  mtev_hash_replace(r->rname##_ht, strdup(value), strlen(value), NULL, free, NULL); \
  if(noit_filter_update_conf_rule(fs->name, rnum, #rname, value) < 0) { \
    mtevL(noit_error, "Error updating configuration for new filter auto_add on %s=%s\n", #rname, value); \
  } \
} while(0)
        if(need_target) UPDATE_FILTER_RULE(idx, target, check->target);
        if(need_module) UPDATE_FILTER_RULE(idx, module, check->module);
        if(need_name) UPDATE_FILTER_RULE(idx, name, check->name);
        if(need_metric) UPDATE_FILTER_RULE(idx, metric, metric->metric_name);
        noit_filterset_log_auto_add(fs->name, check, metric, r->type == NOIT_FILTER_ACCEPT);
        if(r->type == NOIT_FILTER_SKIPTO) {
          skipto_rule = r->skipto_rule;
          continue;
        }
        return (r->type == NOIT_FILTER_ACCEPT) ? mtev_true : mtev_false;
      }
    }
    filterset_free(fs);
    return mtev_false;
  }
  UNLOCKFS();
  return mtev_false;
}
예제 #7
0
void
noit_filter_compile_add(mtev_conf_section_t setinfo) {
  mtev_conf_section_t *rules;
  int j, fcnt;
  char filterset_name[256];
  filterset_t *set;
  if(!mtev_conf_get_stringbuf(setinfo, "@name",
                              filterset_name, sizeof(filterset_name))) {
    mtevL(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 = mtev_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.
   */
  mtevL(noit_debug, "Compiling filterset '%s'\n", set->name);
  for(j=fcnt-1; j>=0; j--) {
    filterrule_t *rule;
    char buffer[256];
    if(!mtev_conf_get_stringbuf(rules[j], "@type", buffer, sizeof(buffer)) ||
       (strcmp(buffer, "accept") && strcmp(buffer, "allow") && strcmp(buffer, "deny") &&
        strncmp(buffer, "skipto:", strlen("skipto:")))) {
      mtevL(noit_error, "rule must have type 'accept' or 'allow' or 'deny' or 'skipto:'\n");
      continue;
    }
    mtevL(noit_debug, "Prepending %s into %s\n", buffer, set->name);
    rule = calloc(1, sizeof(*rule));
    if(!strncasecmp(buffer, "skipto:", strlen("skipto:"))) {
      rule->type = NOIT_FILTER_SKIPTO;
      rule->skipto = strdup(buffer+strlen("skipto:"));
    }
    else {
      rule->type = (!strcmp(buffer, "accept") || !strcmp(buffer, "allow")) ?
                     NOIT_FILTER_ACCEPT : NOIT_FILTER_DENY;
    }

    if(mtev_conf_get_stringbuf(rules[j], "@id", buffer, sizeof(buffer))) {
      rule->ruleid = strdup(buffer);
    }
    /* Compile any hash tables, should they exist */
#define HT_COMPILE(rname) do { \
    mtev_conf_section_t *htentries; \
    int hte_cnt, hti, tablesize = 2, auto_max = 0; \
    char *htstr; \
    htentries = mtev_conf_get_sections(rules[j], #rname, &hte_cnt); \
    mtev_conf_get_int(rules[j], "@" #rname "_auto_add", &auto_max); \
    if(hte_cnt || auto_max > 0) { \
      rule->rname##_auto_hash_max = auto_max; \
      rule->rname##_ht = calloc(1, sizeof(*(rule->rname##_ht))); \
      while(tablesize < hte_cnt) tablesize <<= 1; \
      mtev_hash_init_size(rule->rname##_ht, tablesize); \
      for(hti=0; hti<hte_cnt; hti++) { \
        if(!mtev_conf_get_string(htentries[hti], "self::node()", &htstr)) \
          mtevL(noit_error, "Error fetching text content from filter match.\n"); \
        else \
          mtev_hash_replace(rule->rname##_ht, htstr, strlen(htstr), NULL, free, NULL); \
      } \
    } \
    free(htentries); \
} while(0);
    HT_COMPILE(target);
    HT_COMPILE(module);
    HT_COMPILE(name);
    HT_COMPILE(metric);
    
    /* Compile our rules */
#define RULE_COMPILE(rname) do { \
  char *longre = NULL; \
  if(mtev_conf_get_string(rules[j], "@" #rname, &longre)) { \
    const char *error; \
    int erroffset; \
    rule->rname = pcre_compile(longre, 0, &error, &erroffset, NULL); \
    if(!rule->rname) { \
      mtevL(noit_debug, "set '%s' rule '%s: %s' compile failed: %s\n", \
            set->name, #rname, longre, error ? error : "???"); \
      rule->rname##_override = fallback_no_match; \
    } \
    else { \
      rule->rname##_e = pcre_study(rule->rname, 0, &error); \
    } \
    free(longre); \
  } \
} while(0)

    if(rule->target_ht == NULL)
      RULE_COMPILE(target);
    if(rule->module_ht == NULL)
      RULE_COMPILE(module);
    if(rule->name_ht == NULL)
      RULE_COMPILE(name);
    if(rule->metric_ht == NULL)
      RULE_COMPILE(metric);
    rule->next = set->rules;
    set->rules = rule;
  }

  filterrule_t *cursor;
  for(cursor = set->rules; cursor->next; cursor = cursor->next) {
    if(cursor->skipto) {
      filterrule_t *target;
      for(target = cursor->next; target; target = target->next) {
        if(target->ruleid && !strcmp(cursor->skipto, target->ruleid)) {
          cursor->skipto_rule = target;
          break;
        }
      }
      if(!cursor->skipto_rule)
        mtevL(noit_error, "filterset %s skipto:%s not found\n",
              set->name, cursor->skipto);
    }
  }
  free(rules);
  LOCKFS();
  mtev_hash_replace(filtersets, set->name, strlen(set->name), (void *)set,
                    NULL, filterset_free);
  UNLOCKFS();
}