| 204 | | |
|---|
| | 221 | static char * |
|---|
| | 222 | conf_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 | |
|---|
| | 243 | static int |
|---|
| | 244 | noit_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 | } |
|---|
| | 281 | static int |
|---|
| | 282 | noit_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 | } |
|---|
| | 362 | static int |
|---|
| | 363 | noit_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 | |
|---|
| | 437 | static void |
|---|
| | 438 | register_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 | |
|---|
| | 476 | void |
|---|
| | 477 | noit_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 | } |
|---|