Changeset 37daa37bbc546da8db4d76945b9c4b523e02d77b

Show
Ignore:
Timestamp:
09/21/09 00:10:13 (5 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1253491813 +0000
git-parent:

[d9fd356e6dcff42e03b313c5d8753a6dff82f36d]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1253491813 +0000
Message:

online configuration filters, refs #182

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/noit_conf.h

    r25fec2c r37daa37  
    4747  char *path; 
    4848  uuid_t current_check; 
     49  char filter_name[50]; 
    4950  char prompt[50]; 
    5051} noit_conf_t_userdata_t; 
  • src/noit_conf_checks.c

    r25fec2c r37daa37  
    1  
    21/* 
    32 * Copyright (c) 2007, OmniTI Computer Consulting, Inc. 
     
    4544#include "noit_conf.h" 
    4645#include "noit_conf_private.h" 
     46#include "noit_conf_checks.h" 
    4747#include "noit_check.h" 
    4848#include "noit_check_tools.h" 
     
    5353 
    5454static void register_console_config_commands(); 
    55 static int noit_console_config_cd(noit_console_closure_t ncct, 
    56                                   int argc, char **argv, 
    57                                   noit_console_state_t *state, void *closure); 
    5855 
    5956static struct _valid_attr_t { 
     
    7168  { "/checks", "filterset", "@filterset", 0 }, 
    7269  { "/checks", "module", "@module", 1 }, 
    73   { "/filtersets/filterset", "target", "@target", 1 }, 
    74   { "/filtersets/filterset", "module", "@module", 1 }, 
    75   { "/filtersets/filterset", "name", "@name", 1 }, 
    76   { "/filtersets/filterset", "metric", "@metric", 1 }, 
     70  { "/filtersets", "target", "@target", 0 }, 
     71  { "/filtersets", "module", "@module", 0 }, 
     72  { "/filtersets", "name", "@name", 0 }, 
     73  { "/filtersets", "metric", "@metric", 0 }, 
    7774}; 
    7875 
    7976void 
    8077noit_console_state_add_check_attrs(noit_console_state_t *state, 
    81                                    console_cmd_func_t f) { 
     78                                   console_cmd_func_t f, 
     79                                   const char *scope) { 
    8280  int i; 
    8381  for(i = 0; 
    8482      i < sizeof(valid_attrs)/sizeof(valid_attrs[0]); 
    8583      i++) { 
     84    if(strcmp(valid_attrs[i].scope, scope)) continue; 
    8685    noit_console_state_add_cmd(state, 
    8786      NCSCMD(valid_attrs[i].name, f, NULL, 
     
    9089} 
    9190static noit_hash_table check_attrs = NOIT_HASH_EMPTY; 
     91 
    9292void noit_conf_checks_init(const char *toplevel) { 
    9393  int i; 
     
    265265    uuid_t out; 
    266266    creating_new = noit_true; 
     267    if(strncmp(info->path, "/checks/", strlen("/checks/")) && 
     268       strcmp(info->path, "/checks")) { 
     269      nc_printf(ncct, "New checks must be under /checks/\n"); 
     270      return -1; 
     271    } 
    267272    if(noit_conf_mkcheck_under(info->path, argc - 1, argv + 1, out)) { 
    268273      nc_printf(ncct, "Error creating new check\n"); 
     
    621626    return -1; 
    622627  } 
     628  if(!strcmp(argv[0], "filterset")) { 
     629    nc_printf(ncct, "use 'filterset' to create checks\n"); 
     630    return -1; 
     631  } 
    623632  if(!strcmp(argv[0], "config")) { 
    624633    nc_printf(ncct, "use 'config' to set check config options\n"); 
     
    698707} 
    699708 
    700 static int 
     709int 
    701710noit_console_config_cd(noit_console_closure_t ncct, 
    702711                       int argc, char **argv, 
     
    875884    node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); 
    876885    if(!strcmp((char *)node->name, "check")) continue; 
     886    if(!strcmp((char *)node->name, "filterset")) continue; 
    877887    if(!strcmp((char *)xmlGetNodePath(node) + cliplen, "config")) continue; 
    878888    if(!(node->children && node->children == xmlGetLastChild(node) && 
     
    886896  for(i=0; i<cnt; i++) { 
    887897    node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); 
    888     if(!strcmp((char *)node->name, "check")) { 
     898    if(!strcmp((char *)node->name, "filterset")) { 
     899      xmlAttr *attr; 
     900      char *filter_name = NULL; 
     901      for(attr=node->properties; attr; attr = attr->next) { 
     902        if(!strcmp((char *)attr->name, "name")) 
     903          filter_name = (char *)xmlXPathCastNodeToString(attr->children); 
     904      } 
     905      if(filter_name) { 
     906        nc_printf(ncct, "filterset[@name=\"%s\"]\n", filter_name); 
     907        xmlFree(filter_name); 
     908      } 
     909      else nc_printf(ncct, "fitlerset\n"); 
     910    } 
     911    else if(!strcmp((char *)node->name, "check")) { 
    889912      int busted = 1; 
    890913      xmlAttr *attr; 
     
    13201343  /* attribute <attrname> <value> */ 
    13211344  NEW_STATE(_attr_state); 
    1322   noit_console_state_add_check_attrs(_attr_state, noit_conf_check_set_attr); 
     1345  noit_console_state_add_check_attrs(_attr_state, noit_conf_check_set_attr, 
     1346                                     "/checks"); 
    13231347  
    13241348  /* no attribute <attrname> <value> */ 
    13251349  NEW_STATE(_uattr_state); 
    1326   noit_console_state_add_check_attrs(_uattr_state, noit_conf_check_unset_attr); 
     1350  noit_console_state_add_check_attrs(_uattr_state, noit_conf_check_unset_attr, 
     1351                                     "/checks"); 
    13271352 
    13281353  NEW_STATE(_unset_state); 
  • src/noit_conf_checks.h

    r88a7178 r37daa37  
    3838#include "noit_console.h" 
    3939 
    40 API_EXPORT(int) noit_conf_checks_init(const char *toplevel); 
     40API_EXPORT(void) noit_conf_checks_init(const char *toplevel); 
     41API_EXPORT(int) 
     42  noit_console_config_cd(noit_console_closure_t ncct, 
     43                         int argc, char **argv, 
     44                         noit_console_state_t *state, void *closure); 
     45API_EXPORT(int) 
     46  noit_conf_check_set_attr(noit_console_closure_t ncct, 
     47                           int argc, char **argv, 
     48                           noit_console_state_t *state, void *closure); 
     49API_EXPORT(void) 
     50  noit_console_state_add_check_attrs(noit_console_state_t *state, 
     51                                     console_cmd_func_t f, 
     52                                     const char *scope); 
    4153 
    4254#endif 
  • src/noit_filters.c

    r88a7178 r37daa37  
    3434 
    3535#include "utils/noit_hash.h" 
     36#include "utils/noit_atomic.h" 
    3637#include "noit_conf.h" 
    3738#include "noit_check.h" 
     39#include "noit_conf_checks.h" 
    3840#include "noit_filters.h" 
    3941 
    4042#include <pcre.h> 
     43#include <assert.h> 
     44#include <libxml/tree.h> 
    4145 
    4246static noit_hash_table *filtersets = NULL; 
     47static pthread_mutex_t filterset_lock; 
     48#define LOCKFS() pthread_mutex_lock(&filterset_lock) 
     49#define UNLOCKFS() pthread_mutex_unlock(&filterset_lock) 
    4350 
    4451typedef enum { NOIT_FILTER_ACCEPT, NOIT_FILTER_DENY } noit_ruletype_t; 
     
    5764 
    5865typedef struct { 
     66  noit_atomic32_t ref_cnt; 
    5967  char *name; 
    6068  filterrule_t *rules; 
    6169} filterset_t; 
    62  
    63 void 
    64 noit_refresh_filtersets(noit_console_closure_t ncct, 
    65                         noit_conf_t_userdata_t *info) { 
    66   noit_filters_init(); 
    67   nc_printf(ncct, "Reloaded %d filtersets.\n", 
    68             filtersets ? filtersets->size : 0); 
    69 } 
    7070 
    7171#define FRF(r,a) do { \ 
     
    8787  filterset_t *fs = vp; 
    8888  filterrule_t *r; 
     89  if(noit_atomic_dec32(&fs->ref_cnt) != 0) return; 
     90  noitL(noit_error, "Freeing filterset [%d]: %s\n", fs->ref_cnt, fs->name); 
    8991  while(fs->rules) { 
    9092    r = fs->rules->next; 
     
    9698} 
    9799void 
    98 noit_filters_init() { 
    99   noit_hash_table *newsets = NULL, *cleanup; 
    100   noit_conf_section_t *sets; 
    101   int i, cnt; 
    102  
    103   sets = noit_conf_get_sections(NULL, "/noit/filtersets//filterset", &cnt); 
    104   newsets = calloc(1, sizeof(noit_hash_table)); 
    105   for(i=0; i<cnt; i++) { 
    106     noit_conf_section_t *rules; 
    107     int j, fcnt; 
    108     char filterset_name[256]; 
    109     filterset_t *set; 
    110     if(!noit_conf_get_stringbuf(sets[i], "@name", 
    111                                 filterset_name, sizeof(filterset_name))) { 
    112       noitL(noit_error, 
    113             "filterset with no name, skipping as it cannot be referenced.\n"); 
     100noit_filter_compile_add(noit_conf_section_t setinfo) { 
     101  noit_conf_section_t *rules; 
     102  int j, fcnt; 
     103  char filterset_name[256]; 
     104  filterset_t *set; 
     105  if(!noit_conf_get_stringbuf(setinfo, "@name", 
     106                              filterset_name, sizeof(filterset_name))) { 
     107    noitL(noit_error, 
     108          "filterset with no name, skipping as it cannot be referenced.\n"); 
     109    return; 
     110  } 
     111  set = calloc(1, sizeof(*set)); 
     112  set->ref_cnt = 1; 
     113  set->name = strdup(filterset_name); 
     114 
     115  rules = noit_conf_get_sections(setinfo, "rule", &fcnt); 
     116  /* Here we will work through the list backwards pushing the rules on 
     117   * the front of the list.  That way we can simply walk them in order 
     118   * for the application process. 
     119   */ 
     120  noitL(noit_debug, "Compiling filterset '%s'\n", set->name); 
     121  for(j=fcnt-1; j>=0; j--) { 
     122    filterrule_t *rule; 
     123    char buffer[256]; 
     124    if(!noit_conf_get_stringbuf(rules[j], "@type", buffer, sizeof(buffer)) || 
     125       (strcmp(buffer, "accept") && strcmp(buffer, "deny"))) { 
     126      noitL(noit_error, "rule must have type 'accept' or 'deny'\n"); 
    114127      continue; 
    115128    } 
    116     set = calloc(1, sizeof(*set)); 
    117     set->name = strdup(filterset_name); 
    118  
    119     rules = noit_conf_get_sections(sets[i], "rule", &fcnt); 
    120     /* Here we will work through the list backwards pushing the rules on 
    121      * the front of the list.  That way we can simply walk them in order 
    122      * for the application process. 
    123      */ 
    124     noitL(noit_debug, "Compiling filterset '%s'\n", set->name); 
    125     for(j=fcnt-1; j>=0; j--) { 
    126       filterrule_t *rule; 
    127       char buffer[256]; 
    128       if(!noit_conf_get_stringbuf(rules[j], "@type", buffer, sizeof(buffer)) || 
    129          (strcmp(buffer, "accept") && strcmp(buffer, "deny"))) { 
    130         noitL(noit_error, "rule must have type 'accept' or 'deny'\n"); 
    131         continue; 
    132       } 
    133       noitL(noit_debug, "Prepending %s into %s\n", buffer, set->name); 
    134       rule = calloc(1, sizeof(*rule)); 
    135       rule->type = (!strcmp(buffer, "accept")) ? 
    136                      NOIT_FILTER_ACCEPT : NOIT_FILTER_DENY; 
    137  
    138       /* Compile our rules */ 
     129    noitL(noit_debug, "Prepending %s into %s\n", buffer, set->name); 
     130    rule = calloc(1, sizeof(*rule)); 
     131    rule->type = (!strcmp(buffer, "accept")) ? 
     132                   NOIT_FILTER_ACCEPT : NOIT_FILTER_DENY; 
     133 
     134    /* Compile our rules */ 
    139135#define RULE_COMPILE(rname) do { \ 
    140136  if(noit_conf_get_stringbuf(rules[j], "@" #rname, buffer, sizeof(buffer))) { \ 
     
    152148} while(0) 
    153149 
    154       RULE_COMPILE(target); 
    155       RULE_COMPILE(module); 
    156       RULE_COMPILE(name); 
    157       RULE_COMPILE(metric); 
    158       rule->next = set->rules; 
    159       set->rules = rule; 
    160     } 
    161     free(rules); 
    162     noit_hash_replace(newsets, set->name, strlen(set->name), (void *)set, 
    163                       NULL, filterset_free); 
     150    RULE_COMPILE(target); 
     151    RULE_COMPILE(module); 
     152    RULE_COMPILE(name); 
     153    RULE_COMPILE(metric); 
     154    rule->next = set->rules; 
     155    set->rules = rule; 
     156  } 
     157  free(rules); 
     158  LOCKFS(); 
     159  noit_hash_replace(filtersets, set->name, strlen(set->name), (void *)set, 
     160                    NULL, filterset_free); 
     161  UNLOCKFS(); 
     162
     163void 
     164noit_filters_from_conf() { 
     165  noit_conf_section_t *sets; 
     166  int i, cnt; 
     167 
     168  sets = noit_conf_get_sections(NULL, "/noit/filtersets//filterset", &cnt); 
     169  for(i=0; i<cnt; i++) { 
     170    noit_filter_compile_add(sets[i]); 
    164171  } 
    165172  free(sets); 
    166   cleanup = filtersets; 
    167   filtersets = newsets; 
    168   if(cleanup) noit_hash_destroy(cleanup, NULL, filterset_free); 
     173
     174 
     175void 
     176noit_refresh_filtersets(noit_console_closure_t ncct, 
     177                        noit_conf_t_userdata_t *info) { 
     178  noit_filters_from_conf(); 
     179  nc_printf(ncct, "Reloaded %d filtersets.\n", 
     180            filtersets ? filtersets->size : 0); 
    169181} 
    170182 
     
    187199  if(!filtersets || !filterset) return noit_true; 
    188200 
     201  LOCKFS(); 
    189202  if(noit_hash_retrieve(filtersets, filterset, strlen(filterset), &vfs)) { 
    190203    filterset_t *fs = (filterset_t *)vfs; 
    191204    filterrule_t *r; 
     205    noit_atomic_inc32(&fs->ref_cnt); 
     206    UNLOCKFS(); 
    192207#define MATCHES(rname, value) noit_apply_filterrule(r->rname, r->rname##_e, value) 
    193208    for(r = fs->rules; r; r = r->next) { 
     
    198213        return (r->type == NOIT_FILTER_ACCEPT) ? noit_true : noit_false; 
    199214    } 
    200   } 
     215    filterset_free(fs); 
     216  } 
     217  UNLOCKFS(); 
    201218  return noit_true; 
    202219} 
    203220 
    204  
     221static char * 
     222conf_t_filterset_prompt(EditLine *el) { 
     223  noit_console_closure_t ncct; 
     224  noit_conf_t_userdata_t *info; 
     225  static char *tl = "noit(conf)# "; 
     226  static char *pfmt = "noit(conf:filterset:%.*s%s)# "; 
     227  int max_space, namelen; 
     228  el_get(el, EL_USERDATA, (void *)&ncct); 
     229  if(!ncct) return tl; 
     230  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     231  if(!info) return tl; 
     232  max_space = sizeof(info->prompt) - strlen(pfmt) + 6 - 1; 
     233  namelen = strlen(info->filter_name); 
     234  if(namelen > max_space) 
     235    snprintf(info->prompt, sizeof(info->prompt), pfmt, 
     236             max_space - 3, info->filter_name, "..."); 
     237  else 
     238    snprintf(info->prompt, sizeof(info->prompt), pfmt, 
     239             namelen, info->filter_name, ""); 
     240  return info->prompt; 
     241
     242 
     243static int 
     244noit_console_filter_show(noit_console_closure_t ncct, 
     245                         int argc, char **argv, 
     246                         noit_console_state_t *state, 
     247                         void *closure) { 
     248  noit_conf_t_userdata_t *info; 
     249  char xpath[1024]; 
     250  xmlNodePtr fsnode; 
     251  noit_conf_section_t *rules; 
     252  int i, rulecnt; 
     253 
     254  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     255  snprintf(xpath, sizeof(xpath), "/%s", 
     256           info->path); 
     257  fsnode = noit_conf_get_section(NULL, xpath); 
     258  if(!fsnode) { 
     259    nc_printf(ncct, "internal error\n"); 
     260    return -1; 
     261  } 
     262  rules = noit_conf_get_sections(fsnode, "rule", &rulecnt); 
     263  for(i=0; i<rulecnt; i++) { 
     264    char val[256]; 
     265    val[0] = '\0'; 
     266    noit_conf_get_stringbuf(rules[i], "@type", val, sizeof(val)); 
     267    nc_printf(ncct, "Rule %d [%s]:\n", i+1, val); 
     268#define DUMP_ATTR(a) do { \ 
     269  if(noit_conf_get_stringbuf(rules[i], "@" #a, val, sizeof(val))) { \ 
     270    nc_printf(ncct, "\t%s: /%s/\n", #a, val); \ 
     271  } \ 
     272} while(0) 
     273    DUMP_ATTR(target); 
     274    DUMP_ATTR(module); 
     275    DUMP_ATTR(name); 
     276    DUMP_ATTR(metric); 
     277  } 
     278  if(rules) free(rules); 
     279  return 0; 
     280
     281static int 
     282noit_console_rule_configure(noit_console_closure_t ncct, 
     283                            int argc, char **argv, 
     284                            noit_console_state_t *state, 
     285                            void *closure) { 
     286  xmlNodePtr fsnode = NULL; 
     287  noit_conf_t_userdata_t *info; 
     288  char xpath[1024]; 
     289 
     290  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     291  snprintf(xpath, sizeof(xpath), "/%s", 
     292           info->path); 
     293  fsnode = noit_conf_get_section(NULL, xpath); 
     294  if(!fsnode) { 
     295    nc_printf(ncct, "internal error"); 
     296    return -1; 
     297  } 
     298  if(closure) { 
     299    int rulenum; 
     300    xmlNodePtr byebye; 
     301    /* removing a rule */ 
     302    if(argc != 1) { 
     303      nc_printf(ncct, "requires one argument\n"); 
     304      return -1; 
     305    } 
     306    rulenum = atoi(argv[0]); 
     307    snprintf(xpath, sizeof(xpath), "rule[%d]", rulenum); 
     308    byebye = noit_conf_get_section(fsnode, xpath); 
     309    if(!byebye) { 
     310      nc_printf(ncct, "cannot find rule\n"); 
     311      return -1; 
     312    } 
     313    xmlUnlinkNode(byebye); 
     314    xmlFreeNode(byebye); 
     315    nc_printf(ncct, "removed\n"); 
     316  } 
     317  else { 
     318    xmlNodePtr (*add_func)(xmlNodePtr, xmlNodePtr); 
     319    xmlNodePtr add_arg, new_rule; 
     320    int i, needs_type = 1; 
     321    if(argc < 1 || argc % 2) { 
     322      nc_printf(ncct, "even number of arguments required\n"); 
     323      return -1; 
     324    } 
     325    if(!strcmp(argv[0], "before") || !strcmp(argv[0], "after")) { 
     326      int rulenum = atoi(argv[1]); 
     327      snprintf(xpath, sizeof(xpath), "rule[%d]", rulenum); 
     328      add_arg = noit_conf_get_section(fsnode, xpath); 
     329      if(!add_arg) { 
     330        nc_printf(ncct, "%s rule not found\n", xpath); 
     331        return -1; 
     332      } 
     333      if(*argv[0] == 'b') add_func = xmlAddPrevSibling; 
     334      else add_func = xmlAddNextSibling; 
     335      argc -= 2; 
     336      argv += 2; 
     337    } 
     338    else { 
     339      add_func = xmlAddChild; 
     340      add_arg = fsnode; 
     341    } 
     342    for(i=0;i<argc;i+=2) { 
     343      if(!strcmp(argv[i], "type")) needs_type = 0; 
     344      else if(strcmp(argv[i], "target") && strcmp(argv[i], "module") && 
     345              strcmp(argv[i], "name") && strcmp(argv[i], "metric")) { 
     346        nc_printf(ncct, "unknown attribute '%s'\n", argv[i]); 
     347        return -1; 
     348      } 
     349    } 
     350    if(needs_type) { 
     351      nc_printf(ncct, "type <allow|deny> is required\n"); 
     352      return -1; 
     353    } 
     354    new_rule = xmlNewNode(NULL, (xmlChar *)"rule"); 
     355    for(i=0;i<argc;i+=2) 
     356      xmlSetProp(new_rule, (xmlChar *)argv[i], (xmlChar *)argv[i+1]); 
     357    add_func(add_arg, new_rule); 
     358    noit_filter_compile_add((noit_conf_section_t *)fsnode); 
     359  } 
     360  return 0; 
     361
     362static int 
     363noit_console_filter_configure(noit_console_closure_t ncct, 
     364                              int argc, char **argv, 
     365                              noit_console_state_t *state, 
     366                              void *closure) { 
     367  xmlNodePtr parent, fsnode = NULL; 
     368  int rv = -1; 
     369  noit_conf_t_userdata_t *info; 
     370  char xpath[1024]; 
     371 
     372  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     373  if(!info || 
     374     (strncmp(info->path, "/filtersets/", strlen("/filtersets/")) && 
     375      strcmp(info->path, "/filtersets"))) { 
     376    nc_printf(ncct, "filterset only allows inside /filtersets (not %s)\n", 
     377              info->path); 
     378    goto cleanup; 
     379  } 
     380  if(argc != 1) { 
     381    nc_printf(ncct, "filterset requires one argument\n"); 
     382    goto cleanup; 
     383  } 
     384  snprintf(xpath, sizeof(xpath), "/%s", info->path); 
     385  parent = noit_conf_get_section(NULL, xpath); 
     386  if(!parent) { 
     387    nc_printf(ncct, "internal error, can't final current working path\n"); 
     388    goto cleanup; 
     389  } 
     390  snprintf(xpath, sizeof(xpath), "filterset[@name=\"%s\"]", argv[0]); 
     391  fsnode = noit_conf_get_section(parent, xpath); 
     392  if(closure) { 
     393    int removed; 
     394    LOCKFS(); 
     395    removed = noit_hash_delete(filtersets, argv[0], strlen(argv[0]), 
     396                               NULL, filterset_free); 
     397    UNLOCKFS(); 
     398    nc_printf(ncct, "%sremoved filterset '%s'\n", 
     399              removed ? "" : "failed to ", argv[0]); 
     400    if(removed) { 
     401      xmlUnlinkNode(fsnode); 
     402      xmlFreeNode(fsnode); 
     403    } 
     404    rv = !removed; 
     405    goto cleanup; 
     406  } 
     407  if(!fsnode) { 
     408    void *vfs; 
     409    nc_printf(ncct, "Cannot find filterset '%s'\n", argv[0]); 
     410    LOCKFS(); 
     411    if(noit_hash_retrieve(filtersets, argv[0], strlen(argv[0]), &vfs)) { 
     412      UNLOCKFS(); 
     413      nc_printf(ncct, "filter of the same name already exists\n"); 
     414      goto cleanup; 
     415    } 
     416    UNLOCKFS(); 
     417    /* Fine the parent path */ 
     418    fsnode = xmlNewNode(NULL, (xmlChar *)"filterset"); 
     419    xmlSetProp(fsnode, (xmlChar *)"name", (xmlChar *)argv[0]); 
     420    xmlAddChild(parent, fsnode); 
     421    nc_printf(ncct, "created new filterset\n"); 
     422  } 
     423 
     424  if(info) { 
     425    if(info->path) free(info->path); 
     426    info->path = strdup((char *)xmlGetNodePath(fsnode) + strlen("/noit")); 
     427    strlcpy(info->filter_name, argv[0], sizeof(info->filter_name)); 
     428    if(state) { 
     429      noit_console_state_push_state(ncct, state); 
     430      noit_console_state_init(ncct); 
     431    } 
     432  } 
     433 cleanup: 
     434  return rv; 
     435
     436 
     437static void 
     438register_console_filter_commands() { 
     439  noit_console_state_t *tl, *filterset_state, *nostate; 
     440  cmd_info_t *confcmd, *conf_t_cmd, *no_cmd; 
     441 
     442  tl = noit_console_state_initial(); 
     443  confcmd = noit_console_state_get_cmd(tl, "configure"); 
     444  assert(confcmd && confcmd->dstate); 
     445 
     446  conf_t_cmd = noit_console_state_get_cmd(confcmd->dstate, "terminal"); 
     447  assert(conf_t_cmd && conf_t_cmd->dstate); 
     448 
     449  nostate = noit_console_state_alloc(); 
     450  noit_console_state_add_cmd(nostate, 
     451    NCSCMD("rule", noit_console_rule_configure, NULL, NULL, (void *)1)); 
     452 
     453  filterset_state = noit_console_state_alloc(); 
     454  noit_console_state_add_cmd(filterset_state, 
     455    NCSCMD("exit", noit_console_config_cd, NULL, NULL, "..")); 
     456  noit_console_state_add_cmd(filterset_state, 
     457    NCSCMD("status", noit_console_filter_show, NULL, NULL, NULL)); 
     458  noit_console_state_add_cmd(filterset_state, 
     459    NCSCMD("rule", noit_console_rule_configure, NULL, NULL, NULL)); 
     460  noit_console_state_add_cmd(filterset_state, 
     461    NCSCMD("no", noit_console_state_delegate, noit_console_opt_delegate, 
     462           nostate, NULL)); 
     463 
     464  filterset_state->console_prompt_function = conf_t_filterset_prompt; 
     465 
     466  noit_console_state_add_cmd(conf_t_cmd->dstate, 
     467    NCSCMD("filterset", noit_console_filter_configure, 
     468           NULL, filterset_state, NULL)); 
     469 
     470  no_cmd = noit_console_state_get_cmd(conf_t_cmd->dstate, "no"); 
     471  assert(no_cmd && no_cmd->dstate); 
     472  noit_console_state_add_cmd(no_cmd->dstate, 
     473    NCSCMD("filterset", noit_console_filter_configure, NULL, NULL, (void *)1)); 
     474
     475 
     476void 
     477noit_filters_init() { 
     478  pthread_mutex_init(&filterset_lock, NULL); 
     479  filtersets = calloc(1, sizeof(noit_hash_table)); 
     480  register_console_filter_commands(); 
     481  noit_filters_from_conf(); 
     482