| 587 | } |
| 588 | |
| 589 | int |
| 590 | pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, |
| 591 | int flags) |
| 592 | { |
| 593 | struct pfr_ktable *kt; |
| 594 | struct pfr_walktree w; |
| 595 | struct pfr_kentryworkq workq; |
| 596 | int rv; |
| 597 | long tzero = time_second; |
| 598 | |
| 599 | PF_RULES_RASSERT(); |
| 600 | |
| 601 | /* XXX PFR_FLAG_CLSTATS disabled */ |
| 602 | ACCEPT_FLAGS(flags, 0); |
| 603 | if (pfr_validate_table(tbl, 0, 0)) |
| 604 | return (EINVAL); |
| 605 | kt = pfr_lookup_table(tbl); |
| 606 | if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) |
| 607 | return (ESRCH); |
| 608 | if (kt->pfrkt_cnt > *size) { |
| 609 | *size = kt->pfrkt_cnt; |
| 610 | return (0); |
| 611 | } |
| 612 | |
| 613 | bzero(&w, sizeof(w)); |
| 614 | w.pfrw_op = PFRW_GET_ASTATS; |
| 615 | w.pfrw_astats = addr; |
| 616 | w.pfrw_free = kt->pfrkt_cnt; |
| 617 | /* |
| 618 | * Flags below are for backward compatibility. It was possible to have |
| 619 | * a table without per-entry counters. Now they are always allocated, |
| 620 | * we just discard data when reading it if table is not configured to |
| 621 | * have counters. |
| 622 | */ |
| 623 | w.pfrw_flags = kt->pfrkt_flags; |
| 624 | rv = kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w); |
| 625 | if (!rv) |
| 626 | rv = kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, |
| 627 | pfr_walktree, &w); |
| 628 | if (!rv && (flags & PFR_FLAG_CLSTATS)) { |
| 629 | pfr_enqueue_addrs(kt, &workq, NULL, 0); |
| 630 | pfr_clstats_kentries(kt, &workq, tzero, 0); |
| 631 | } |
| 632 | if (rv) |
| 633 | return (rv); |
| 634 | |
| 635 | if (w.pfrw_free) { |
| 636 | printf("pfr_get_astats: corruption detected (%d).\n", |
| 637 | w.pfrw_free); |
| 638 | return (ENOTTY); |
| 639 | } |
| 640 | *size = kt->pfrkt_cnt; |
| 641 | return (0); |
| 642 | } |
| 643 | |
| 644 | int |
| 645 | pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, |
no test coverage detected