2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2005 Philip Paeps <philip@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #define PFIOC_USE_LATEST
33 #include <sys/queue.h>
34 #include <bsnmp/snmpmod.h>
36 #include <net/pfvar.h>
37 #include <sys/ioctl.h>
49 #define SNMPTREE_TYPES
53 struct lmodule *module;
57 static uint64_t pf_tick;
59 static struct pf_status pfs;
65 #define PFI_IFTYPE_GROUP 0
66 #define PFI_IFTYPE_INSTANCE 1
67 #define PFI_IFTYPE_DETACHED 2
72 TAILQ_ENTRY(pfi_entry) link;
74 TAILQ_HEAD(pfi_table, pfi_entry);
76 static struct pfi_table pfi_table;
77 static time_t pfi_table_age;
78 static int pfi_table_count;
80 #define PFI_TABLE_MAXAGE 5
83 struct pfr_tstats pft;
85 TAILQ_ENTRY(pft_entry) link;
87 TAILQ_HEAD(pft_table, pft_entry);
89 static struct pft_table pft_table;
90 static time_t pft_table_age;
91 static int pft_table_count;
93 #define PFT_TABLE_MAXAGE 5
96 struct pfr_astats pfas;
98 TAILQ_ENTRY(pfa_entry) link;
100 TAILQ_HEAD(pfa_table, pfa_entry);
102 static struct pfa_table pfa_table;
103 static time_t pfa_table_age;
104 static int pfa_table_count;
106 #define PFA_TABLE_MAXAGE 5
111 TAILQ_ENTRY(pfq_entry) link;
113 TAILQ_HEAD(pfq_table, pfq_entry);
115 static struct pfq_table pfq_table;
116 static time_t pfq_table_age;
117 static int pfq_table_count;
119 static int altq_enabled = 0;
121 #define PFQ_TABLE_MAXAGE 5
124 char name[MAXPATHLEN + PF_RULE_LABEL_SIZE];
129 TAILQ_ENTRY(pfl_entry) link;
131 TAILQ_HEAD(pfl_table, pfl_entry);
133 static struct pfl_table pfl_table;
134 static time_t pfl_table_age;
135 static int pfl_table_count;
137 #define PFL_TABLE_MAXAGE 5
139 /* Forward declarations */
140 static int pfi_refresh(void);
141 static int pfq_refresh(void);
142 static int pfs_refresh(void);
143 static int pft_refresh(void);
144 static int pfa_refresh(void);
145 static int pfl_refresh(void);
146 static struct pfi_entry * pfi_table_find(u_int idx);
147 static struct pfq_entry * pfq_table_find(u_int idx);
148 static struct pft_entry * pft_table_find(u_int idx);
149 static struct pfa_entry * pfa_table_find(u_int idx);
150 static struct pfl_entry * pfl_table_find(u_int idx);
152 static int altq_is_enabled(int pfdevice);
155 pf_status(struct snmp_context __unused *ctx, struct snmp_value *val,
156 u_int sub, u_int __unused vindex, enum snmp_op op)
158 asn_subid_t which = val->var.subs[sub - 1];
160 unsigned char str[128];
162 if (op == SNMP_OP_SET)
163 return (SNMP_ERR_NOT_WRITEABLE);
165 if (op == SNMP_OP_GET) {
166 if (pfs_refresh() == -1)
167 return (SNMP_ERR_GENERR);
170 case LEAF_pfStatusRunning:
171 val->v.uint32 = pfs.running;
173 case LEAF_pfStatusRuntime:
174 runtime = (pfs.since > 0) ?
175 time(NULL) - pfs.since : 0;
176 val->v.uint32 = runtime * 100;
178 case LEAF_pfStatusDebug:
179 val->v.uint32 = pfs.debug;
181 case LEAF_pfStatusHostId:
182 sprintf(str, "0x%08x", ntohl(pfs.hostid));
183 return (string_get(val, str, strlen(str)));
186 return (SNMP_ERR_NOSUCHNAME);
189 return (SNMP_ERR_NOERROR);
196 pf_counter(struct snmp_context __unused *ctx, struct snmp_value *val,
197 u_int sub, u_int __unused vindex, enum snmp_op op)
199 asn_subid_t which = val->var.subs[sub - 1];
201 if (op == SNMP_OP_SET)
202 return (SNMP_ERR_NOT_WRITEABLE);
204 if (op == SNMP_OP_GET) {
205 if (pfs_refresh() == -1)
206 return (SNMP_ERR_GENERR);
209 case LEAF_pfCounterMatch:
210 val->v.counter64 = pfs.counters[PFRES_MATCH];
212 case LEAF_pfCounterBadOffset:
213 val->v.counter64 = pfs.counters[PFRES_BADOFF];
215 case LEAF_pfCounterFragment:
216 val->v.counter64 = pfs.counters[PFRES_FRAG];
218 case LEAF_pfCounterShort:
219 val->v.counter64 = pfs.counters[PFRES_SHORT];
221 case LEAF_pfCounterNormalize:
222 val->v.counter64 = pfs.counters[PFRES_NORM];
224 case LEAF_pfCounterMemDrop:
225 val->v.counter64 = pfs.counters[PFRES_MEMORY];
229 return (SNMP_ERR_NOSUCHNAME);
232 return (SNMP_ERR_NOERROR);
239 pf_statetable(struct snmp_context __unused *ctx, struct snmp_value *val,
240 u_int sub, u_int __unused vindex, enum snmp_op op)
242 asn_subid_t which = val->var.subs[sub - 1];
244 if (op == SNMP_OP_SET)
245 return (SNMP_ERR_NOT_WRITEABLE);
247 if (op == SNMP_OP_GET) {
248 if (pfs_refresh() == -1)
249 return (SNMP_ERR_GENERR);
252 case LEAF_pfStateTableCount:
253 val->v.uint32 = pfs.states;
255 case LEAF_pfStateTableSearches:
257 pfs.fcounters[FCNT_STATE_SEARCH];
259 case LEAF_pfStateTableInserts:
261 pfs.fcounters[FCNT_STATE_INSERT];
263 case LEAF_pfStateTableRemovals:
265 pfs.fcounters[FCNT_STATE_REMOVALS];
269 return (SNMP_ERR_NOSUCHNAME);
272 return (SNMP_ERR_NOERROR);
279 pf_srcnodes(struct snmp_context __unused *ctx, struct snmp_value *val,
280 u_int sub, u_int __unused vindex, enum snmp_op op)
282 asn_subid_t which = val->var.subs[sub - 1];
284 if (op == SNMP_OP_SET)
285 return (SNMP_ERR_NOT_WRITEABLE);
287 if (op == SNMP_OP_GET) {
288 if (pfs_refresh() == -1)
289 return (SNMP_ERR_GENERR);
292 case LEAF_pfSrcNodesCount:
293 val->v.uint32 = pfs.src_nodes;
295 case LEAF_pfSrcNodesSearches:
297 pfs.scounters[SCNT_SRC_NODE_SEARCH];
299 case LEAF_pfSrcNodesInserts:
301 pfs.scounters[SCNT_SRC_NODE_INSERT];
303 case LEAF_pfSrcNodesRemovals:
305 pfs.scounters[SCNT_SRC_NODE_REMOVALS];
309 return (SNMP_ERR_NOSUCHNAME);
312 return (SNMP_ERR_NOERROR);
319 pf_limits(struct snmp_context __unused *ctx, struct snmp_value *val,
320 u_int sub, u_int __unused vindex, enum snmp_op op)
322 asn_subid_t which = val->var.subs[sub - 1];
323 struct pfioc_limit pl;
325 if (op == SNMP_OP_SET)
326 return (SNMP_ERR_NOT_WRITEABLE);
328 if (op == SNMP_OP_GET) {
329 bzero(&pl, sizeof(struct pfioc_limit));
332 case LEAF_pfLimitsStates:
333 pl.index = PF_LIMIT_STATES;
335 case LEAF_pfLimitsSrcNodes:
336 pl.index = PF_LIMIT_SRC_NODES;
338 case LEAF_pfLimitsFrags:
339 pl.index = PF_LIMIT_FRAGS;
343 return (SNMP_ERR_NOSUCHNAME);
346 if (ioctl(dev, DIOCGETLIMIT, &pl)) {
347 syslog(LOG_ERR, "pf_limits(): ioctl(): %s",
349 return (SNMP_ERR_GENERR);
352 val->v.uint32 = pl.limit;
354 return (SNMP_ERR_NOERROR);
361 pf_timeouts(struct snmp_context __unused *ctx, struct snmp_value *val,
362 u_int sub, u_int __unused vindex, enum snmp_op op)
364 asn_subid_t which = val->var.subs[sub - 1];
367 if (op == SNMP_OP_SET)
368 return (SNMP_ERR_NOT_WRITEABLE);
370 if (op == SNMP_OP_GET) {
371 bzero(&pt, sizeof(struct pfioc_tm));
374 case LEAF_pfTimeoutsTcpFirst:
375 pt.timeout = PFTM_TCP_FIRST_PACKET;
377 case LEAF_pfTimeoutsTcpOpening:
378 pt.timeout = PFTM_TCP_OPENING;
380 case LEAF_pfTimeoutsTcpEstablished:
381 pt.timeout = PFTM_TCP_ESTABLISHED;
383 case LEAF_pfTimeoutsTcpClosing:
384 pt.timeout = PFTM_TCP_CLOSING;
386 case LEAF_pfTimeoutsTcpFinWait:
387 pt.timeout = PFTM_TCP_FIN_WAIT;
389 case LEAF_pfTimeoutsTcpClosed:
390 pt.timeout = PFTM_TCP_CLOSED;
392 case LEAF_pfTimeoutsUdpFirst:
393 pt.timeout = PFTM_UDP_FIRST_PACKET;
395 case LEAF_pfTimeoutsUdpSingle:
396 pt.timeout = PFTM_UDP_SINGLE;
398 case LEAF_pfTimeoutsUdpMultiple:
399 pt.timeout = PFTM_UDP_MULTIPLE;
401 case LEAF_pfTimeoutsIcmpFirst:
402 pt.timeout = PFTM_ICMP_FIRST_PACKET;
404 case LEAF_pfTimeoutsIcmpError:
405 pt.timeout = PFTM_ICMP_ERROR_REPLY;
407 case LEAF_pfTimeoutsOtherFirst:
408 pt.timeout = PFTM_OTHER_FIRST_PACKET;
410 case LEAF_pfTimeoutsOtherSingle:
411 pt.timeout = PFTM_OTHER_SINGLE;
413 case LEAF_pfTimeoutsOtherMultiple:
414 pt.timeout = PFTM_OTHER_MULTIPLE;
416 case LEAF_pfTimeoutsFragment:
417 pt.timeout = PFTM_FRAG;
419 case LEAF_pfTimeoutsInterval:
420 pt.timeout = PFTM_INTERVAL;
422 case LEAF_pfTimeoutsAdaptiveStart:
423 pt.timeout = PFTM_ADAPTIVE_START;
425 case LEAF_pfTimeoutsAdaptiveEnd:
426 pt.timeout = PFTM_ADAPTIVE_END;
428 case LEAF_pfTimeoutsSrcNode:
429 pt.timeout = PFTM_SRC_NODE;
433 return (SNMP_ERR_NOSUCHNAME);
436 if (ioctl(dev, DIOCGETTIMEOUT, &pt)) {
437 syslog(LOG_ERR, "pf_timeouts(): ioctl(): %s",
439 return (SNMP_ERR_GENERR);
442 val->v.integer = pt.seconds;
444 return (SNMP_ERR_NOERROR);
451 pf_logif(struct snmp_context __unused *ctx, struct snmp_value *val,
452 u_int sub, u_int __unused vindex, enum snmp_op op)
454 asn_subid_t which = val->var.subs[sub - 1];
455 unsigned char str[IFNAMSIZ];
457 if (op == SNMP_OP_SET)
458 return (SNMP_ERR_NOT_WRITEABLE);
460 if (op == SNMP_OP_GET) {
461 if (pfs_refresh() == -1)
462 return (SNMP_ERR_GENERR);
465 case LEAF_pfLogInterfaceName:
466 strlcpy(str, pfs.ifname, sizeof str);
467 return (string_get(val, str, strlen(str)));
468 case LEAF_pfLogInterfaceIp4BytesIn:
469 val->v.counter64 = pfs.bcounters[IPV4][IN];
471 case LEAF_pfLogInterfaceIp4BytesOut:
472 val->v.counter64 = pfs.bcounters[IPV4][OUT];
474 case LEAF_pfLogInterfaceIp4PktsInPass:
476 pfs.pcounters[IPV4][IN][PF_PASS];
478 case LEAF_pfLogInterfaceIp4PktsInDrop:
480 pfs.pcounters[IPV4][IN][PF_DROP];
482 case LEAF_pfLogInterfaceIp4PktsOutPass:
484 pfs.pcounters[IPV4][OUT][PF_PASS];
486 case LEAF_pfLogInterfaceIp4PktsOutDrop:
488 pfs.pcounters[IPV4][OUT][PF_DROP];
490 case LEAF_pfLogInterfaceIp6BytesIn:
491 val->v.counter64 = pfs.bcounters[IPV6][IN];
493 case LEAF_pfLogInterfaceIp6BytesOut:
494 val->v.counter64 = pfs.bcounters[IPV6][OUT];
496 case LEAF_pfLogInterfaceIp6PktsInPass:
498 pfs.pcounters[IPV6][IN][PF_PASS];
500 case LEAF_pfLogInterfaceIp6PktsInDrop:
502 pfs.pcounters[IPV6][IN][PF_DROP];
504 case LEAF_pfLogInterfaceIp6PktsOutPass:
506 pfs.pcounters[IPV6][OUT][PF_PASS];
508 case LEAF_pfLogInterfaceIp6PktsOutDrop:
510 pfs.pcounters[IPV6][OUT][PF_DROP];
514 return (SNMP_ERR_NOSUCHNAME);
517 return (SNMP_ERR_NOERROR);
524 pf_interfaces(struct snmp_context __unused *ctx, struct snmp_value *val,
525 u_int sub, u_int __unused vindex, enum snmp_op op)
527 asn_subid_t which = val->var.subs[sub - 1];
529 if (op == SNMP_OP_SET)
530 return (SNMP_ERR_NOT_WRITEABLE);
532 if (op == SNMP_OP_GET) {
533 if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE)
534 if (pfi_refresh() == -1)
535 return (SNMP_ERR_GENERR);
538 case LEAF_pfInterfacesIfNumber:
539 val->v.uint32 = pfi_table_count;
543 return (SNMP_ERR_NOSUCHNAME);
546 return (SNMP_ERR_NOERROR);
553 pf_iftable(struct snmp_context __unused *ctx, struct snmp_value *val,
554 u_int sub, u_int __unused vindex, enum snmp_op op)
556 asn_subid_t which = val->var.subs[sub - 1];
557 struct pfi_entry *e = NULL;
559 if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE)
564 return (SNMP_ERR_NOT_WRITEABLE);
565 case SNMP_OP_GETNEXT:
566 if ((e = NEXT_OBJECT_INT(&pfi_table,
567 &val->var, sub)) == NULL)
568 return (SNMP_ERR_NOSUCHNAME);
569 val->var.len = sub + 1;
570 val->var.subs[sub] = e->index;
573 if (val->var.len - sub != 1)
574 return (SNMP_ERR_NOSUCHNAME);
575 if ((e = pfi_table_find(val->var.subs[sub])) == NULL)
576 return (SNMP_ERR_NOSUCHNAME);
580 case SNMP_OP_ROLLBACK:
586 case LEAF_pfInterfacesIfDescr:
587 return (string_get(val, e->pfi.pfik_name, -1));
588 case LEAF_pfInterfacesIfType:
589 val->v.integer = PFI_IFTYPE_INSTANCE;
591 case LEAF_pfInterfacesIfTZero:
593 (time(NULL) - e->pfi.pfik_tzero) * 100;
595 case LEAF_pfInterfacesIfRefsRule:
596 val->v.uint32 = e->pfi.pfik_rulerefs;
598 case LEAF_pfInterfacesIf4BytesInPass:
600 e->pfi.pfik_bytes[IPV4][IN][PASS];
602 case LEAF_pfInterfacesIf4BytesInBlock:
604 e->pfi.pfik_bytes[IPV4][IN][BLOCK];
606 case LEAF_pfInterfacesIf4BytesOutPass:
608 e->pfi.pfik_bytes[IPV4][OUT][PASS];
610 case LEAF_pfInterfacesIf4BytesOutBlock:
612 e->pfi.pfik_bytes[IPV4][OUT][BLOCK];
614 case LEAF_pfInterfacesIf4PktsInPass:
616 e->pfi.pfik_packets[IPV4][IN][PASS];
618 case LEAF_pfInterfacesIf4PktsInBlock:
620 e->pfi.pfik_packets[IPV4][IN][BLOCK];
622 case LEAF_pfInterfacesIf4PktsOutPass:
624 e->pfi.pfik_packets[IPV4][OUT][PASS];
626 case LEAF_pfInterfacesIf4PktsOutBlock:
628 e->pfi.pfik_packets[IPV4][OUT][BLOCK];
630 case LEAF_pfInterfacesIf6BytesInPass:
632 e->pfi.pfik_bytes[IPV6][IN][PASS];
634 case LEAF_pfInterfacesIf6BytesInBlock:
636 e->pfi.pfik_bytes[IPV6][IN][BLOCK];
638 case LEAF_pfInterfacesIf6BytesOutPass:
640 e->pfi.pfik_bytes[IPV6][OUT][PASS];
642 case LEAF_pfInterfacesIf6BytesOutBlock:
644 e->pfi.pfik_bytes[IPV6][OUT][BLOCK];
646 case LEAF_pfInterfacesIf6PktsInPass:
648 e->pfi.pfik_packets[IPV6][IN][PASS];
650 case LEAF_pfInterfacesIf6PktsInBlock:
652 e->pfi.pfik_packets[IPV6][IN][BLOCK];
654 case LEAF_pfInterfacesIf6PktsOutPass:
656 e->pfi.pfik_packets[IPV6][OUT][PASS];
658 case LEAF_pfInterfacesIf6PktsOutBlock:
660 e->pfi.pfik_packets[IPV6][OUT][BLOCK];
664 return (SNMP_ERR_NOSUCHNAME);
667 return (SNMP_ERR_NOERROR);
671 pf_tables(struct snmp_context __unused *ctx, struct snmp_value *val,
672 u_int sub, u_int __unused vindex, enum snmp_op op)
674 asn_subid_t which = val->var.subs[sub - 1];
676 if (op == SNMP_OP_SET)
677 return (SNMP_ERR_NOT_WRITEABLE);
679 if (op == SNMP_OP_GET) {
680 if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
681 if (pft_refresh() == -1)
682 return (SNMP_ERR_GENERR);
685 case LEAF_pfTablesTblNumber:
686 val->v.uint32 = pft_table_count;
690 return (SNMP_ERR_NOSUCHNAME);
693 return (SNMP_ERR_NOERROR);
700 pf_tbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
701 u_int sub, u_int __unused vindex, enum snmp_op op)
703 asn_subid_t which = val->var.subs[sub - 1];
704 struct pft_entry *e = NULL;
706 if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
711 return (SNMP_ERR_NOT_WRITEABLE);
712 case SNMP_OP_GETNEXT:
713 if ((e = NEXT_OBJECT_INT(&pft_table,
714 &val->var, sub)) == NULL)
715 return (SNMP_ERR_NOSUCHNAME);
716 val->var.len = sub + 1;
717 val->var.subs[sub] = e->index;
720 if (val->var.len - sub != 1)
721 return (SNMP_ERR_NOSUCHNAME);
722 if ((e = pft_table_find(val->var.subs[sub])) == NULL)
723 return (SNMP_ERR_NOSUCHNAME);
727 case SNMP_OP_ROLLBACK:
733 case LEAF_pfTablesTblDescr:
734 return (string_get(val, e->pft.pfrts_name, -1));
735 case LEAF_pfTablesTblCount:
736 val->v.integer = e->pft.pfrts_cnt;
738 case LEAF_pfTablesTblTZero:
740 (time(NULL) - e->pft.pfrts_tzero) * 100;
742 case LEAF_pfTablesTblRefsAnchor:
744 e->pft.pfrts_refcnt[PFR_REFCNT_ANCHOR];
746 case LEAF_pfTablesTblRefsRule:
748 e->pft.pfrts_refcnt[PFR_REFCNT_RULE];
750 case LEAF_pfTablesTblEvalMatch:
751 val->v.counter64 = e->pft.pfrts_match;
753 case LEAF_pfTablesTblEvalNoMatch:
754 val->v.counter64 = e->pft.pfrts_nomatch;
756 case LEAF_pfTablesTblBytesInPass:
758 e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_PASS];
760 case LEAF_pfTablesTblBytesInBlock:
762 e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_BLOCK];
764 case LEAF_pfTablesTblBytesInXPass:
766 e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_XPASS];
768 case LEAF_pfTablesTblBytesOutPass:
770 e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_PASS];
772 case LEAF_pfTablesTblBytesOutBlock:
774 e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_BLOCK];
776 case LEAF_pfTablesTblBytesOutXPass:
778 e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_XPASS];
780 case LEAF_pfTablesTblPktsInPass:
782 e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_PASS];
784 case LEAF_pfTablesTblPktsInBlock:
786 e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_BLOCK];
788 case LEAF_pfTablesTblPktsInXPass:
790 e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_XPASS];
792 case LEAF_pfTablesTblPktsOutPass:
794 e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_PASS];
796 case LEAF_pfTablesTblPktsOutBlock:
798 e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_BLOCK];
800 case LEAF_pfTablesTblPktsOutXPass:
802 e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_XPASS];
806 return (SNMP_ERR_NOSUCHNAME);
809 return (SNMP_ERR_NOERROR);
813 pf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val,
814 u_int __unused sub, u_int __unused vindex, enum snmp_op __unused op)
816 asn_subid_t which = val->var.subs[sub - 1];
817 struct pfa_entry *e = NULL;
819 if ((time(NULL) - pfa_table_age) > PFA_TABLE_MAXAGE)
824 return (SNMP_ERR_NOT_WRITEABLE);
825 case SNMP_OP_GETNEXT:
826 if ((e = NEXT_OBJECT_INT(&pfa_table,
827 &val->var, sub)) == NULL)
828 return (SNMP_ERR_NOSUCHNAME);
829 val->var.len = sub + 1;
830 val->var.subs[sub] = e->index;
833 if (val->var.len - sub != 1)
834 return (SNMP_ERR_NOSUCHNAME);
835 if ((e = pfa_table_find(val->var.subs[sub])) == NULL)
836 return (SNMP_ERR_NOSUCHNAME);
840 case SNMP_OP_ROLLBACK:
846 case LEAF_pfTablesAddrNetType:
847 if (e->pfas.pfras_a.pfra_af == AF_INET)
848 val->v.integer = pfTablesAddrNetType_ipv4;
849 else if (e->pfas.pfras_a.pfra_af == AF_INET6)
850 val->v.integer = pfTablesAddrNetType_ipv6;
852 return (SNMP_ERR_GENERR);
854 case LEAF_pfTablesAddrNet:
855 if (e->pfas.pfras_a.pfra_af == AF_INET) {
856 return (string_get(val,
857 (u_char *)&e->pfas.pfras_a.pfra_ip4addr, 4));
858 } else if (e->pfas.pfras_a.pfra_af == AF_INET6)
859 return (string_get(val,
860 (u_char *)&e->pfas.pfras_a.pfra_ip6addr, 16));
862 return (SNMP_ERR_GENERR);
864 case LEAF_pfTablesAddrPrefix:
865 val->v.integer = (int32_t) e->pfas.pfras_a.pfra_net;
867 case LEAF_pfTablesAddrTZero:
869 (time(NULL) - e->pfas.pfras_tzero) * 100;
871 case LEAF_pfTablesAddrBytesInPass:
873 e->pfas.pfras_bytes[PFR_DIR_IN][PFR_OP_PASS];
875 case LEAF_pfTablesAddrBytesInBlock:
877 e->pfas.pfras_bytes[PFR_DIR_IN][PFR_OP_BLOCK];
879 case LEAF_pfTablesAddrBytesOutPass:
881 e->pfas.pfras_bytes[PFR_DIR_OUT][PFR_OP_PASS];
883 case LEAF_pfTablesAddrBytesOutBlock:
885 e->pfas.pfras_bytes[PFR_DIR_OUT][PFR_OP_BLOCK];
887 case LEAF_pfTablesAddrPktsInPass:
889 e->pfas.pfras_packets[PFR_DIR_IN][PFR_OP_PASS];
891 case LEAF_pfTablesAddrPktsInBlock:
893 e->pfas.pfras_packets[PFR_DIR_IN][PFR_OP_BLOCK];
895 case LEAF_pfTablesAddrPktsOutPass:
897 e->pfas.pfras_packets[PFR_DIR_OUT][PFR_OP_PASS];
899 case LEAF_pfTablesAddrPktsOutBlock:
901 e->pfas.pfras_packets[PFR_DIR_OUT][PFR_OP_BLOCK];
904 return (SNMP_ERR_NOSUCHNAME);
907 return (SNMP_ERR_NOERROR);
911 pf_altq_num(struct snmp_context __unused *ctx, struct snmp_value *val,
912 u_int sub, u_int __unused vindex, enum snmp_op op)
914 asn_subid_t which = val->var.subs[sub - 1];
917 return (SNMP_ERR_NOSUCHNAME);
919 if (op == SNMP_OP_SET)
920 return (SNMP_ERR_NOT_WRITEABLE);
922 if (op == SNMP_OP_GET) {
923 if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
924 if (pfq_refresh() == -1)
925 return (SNMP_ERR_GENERR);
928 case LEAF_pfAltqQueueNumber:
929 val->v.uint32 = pfq_table_count;
933 return (SNMP_ERR_NOSUCHNAME);
936 return (SNMP_ERR_NOERROR);
940 return (SNMP_ERR_GENERR);
944 pf_altqq(struct snmp_context __unused *ctx, struct snmp_value *val,
945 u_int sub, u_int __unused vindex, enum snmp_op op)
947 asn_subid_t which = val->var.subs[sub - 1];
948 struct pfq_entry *e = NULL;
951 return (SNMP_ERR_NOSUCHNAME);
953 if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
958 return (SNMP_ERR_NOT_WRITEABLE);
959 case SNMP_OP_GETNEXT:
960 if ((e = NEXT_OBJECT_INT(&pfq_table,
961 &val->var, sub)) == NULL)
962 return (SNMP_ERR_NOSUCHNAME);
963 val->var.len = sub + 1;
964 val->var.subs[sub] = e->index;
967 if (val->var.len - sub != 1)
968 return (SNMP_ERR_NOSUCHNAME);
969 if ((e = pfq_table_find(val->var.subs[sub])) == NULL)
970 return (SNMP_ERR_NOSUCHNAME);
974 case SNMP_OP_ROLLBACK:
980 case LEAF_pfAltqQueueDescr:
981 return (string_get(val, e->altq.qname, -1));
982 case LEAF_pfAltqQueueParent:
983 return (string_get(val, e->altq.parent, -1));
984 case LEAF_pfAltqQueueScheduler:
985 val->v.integer = e->altq.scheduler;
987 case LEAF_pfAltqQueueBandwidth:
988 val->v.uint32 = (e->altq.bandwidth > UINT_MAX) ?
989 UINT_MAX : (u_int32_t)e->altq.bandwidth;
991 case LEAF_pfAltqQueuePriority:
992 val->v.integer = e->altq.priority;
994 case LEAF_pfAltqQueueLimit:
995 val->v.integer = e->altq.qlimit;
999 return (SNMP_ERR_NOSUCHNAME);
1002 return (SNMP_ERR_NOERROR);
1006 pf_labels(struct snmp_context __unused *ctx, struct snmp_value *val,
1007 u_int sub, u_int __unused vindex, enum snmp_op op)
1009 asn_subid_t which = val->var.subs[sub - 1];
1011 if (op == SNMP_OP_SET)
1012 return (SNMP_ERR_NOT_WRITEABLE);
1014 if (op == SNMP_OP_GET) {
1015 if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
1016 if (pfl_refresh() == -1)
1017 return (SNMP_ERR_GENERR);
1020 case LEAF_pfLabelsLblNumber:
1021 val->v.uint32 = pfl_table_count;
1025 return (SNMP_ERR_NOSUCHNAME);
1028 return (SNMP_ERR_NOERROR);
1032 return (SNMP_ERR_GENERR);
1036 pf_lbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
1037 u_int sub, u_int __unused vindex, enum snmp_op op)
1039 asn_subid_t which = val->var.subs[sub - 1];
1040 struct pfl_entry *e = NULL;
1042 if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
1047 return (SNMP_ERR_NOT_WRITEABLE);
1048 case SNMP_OP_GETNEXT:
1049 if ((e = NEXT_OBJECT_INT(&pfl_table,
1050 &val->var, sub)) == NULL)
1051 return (SNMP_ERR_NOSUCHNAME);
1052 val->var.len = sub + 1;
1053 val->var.subs[sub] = e->index;
1056 if (val->var.len - sub != 1)
1057 return (SNMP_ERR_NOSUCHNAME);
1058 if ((e = pfl_table_find(val->var.subs[sub])) == NULL)
1059 return (SNMP_ERR_NOSUCHNAME);
1062 case SNMP_OP_COMMIT:
1063 case SNMP_OP_ROLLBACK:
1069 case LEAF_pfLabelsLblName:
1070 return (string_get(val, e->name, -1));
1071 case LEAF_pfLabelsLblEvals:
1072 val->v.counter64 = e->evals;
1074 case LEAF_pfLabelsLblBytesIn:
1075 val->v.counter64 = e->bytes[IN];
1077 case LEAF_pfLabelsLblBytesOut:
1078 val->v.counter64 = e->bytes[OUT];
1080 case LEAF_pfLabelsLblPktsIn:
1081 val->v.counter64 = e->pkts[IN];
1083 case LEAF_pfLabelsLblPktsOut:
1084 val->v.counter64 = e->pkts[OUT];
1087 return (SNMP_ERR_NOSUCHNAME);
1090 return (SNMP_ERR_NOERROR);
1093 static struct pfi_entry *
1094 pfi_table_find(u_int idx)
1096 struct pfi_entry *e;
1098 TAILQ_FOREACH(e, &pfi_table, link)
1099 if (e->index == idx)
1104 static struct pfq_entry *
1105 pfq_table_find(u_int idx)
1107 struct pfq_entry *e;
1109 TAILQ_FOREACH(e, &pfq_table, link)
1110 if (e->index == idx)
1115 static struct pft_entry *
1116 pft_table_find(u_int idx)
1118 struct pft_entry *e;
1120 TAILQ_FOREACH(e, &pft_table, link)
1121 if (e->index == idx)
1126 static struct pfa_entry *
1127 pfa_table_find(u_int idx)
1129 struct pfa_entry *e;
1131 TAILQ_FOREACH(e, &pfa_table, link)
1132 if (e->index == idx)
1137 static struct pfl_entry *
1138 pfl_table_find(u_int idx)
1140 struct pfl_entry *e;
1142 TAILQ_FOREACH(e, &pfl_table, link)
1143 if (e->index == idx)
1152 struct pfioc_iface io;
1153 struct pfi_kif *p = NULL;
1154 struct pfi_entry *e;
1157 if (started && this_tick <= pf_tick)
1160 while (!TAILQ_EMPTY(&pfi_table)) {
1161 e = TAILQ_FIRST(&pfi_table);
1162 TAILQ_REMOVE(&pfi_table, e, link);
1166 bzero(&io, sizeof(io));
1167 io.pfiio_esize = sizeof(struct pfi_kif);
1170 p = reallocf(p, numifs * sizeof(struct pfi_kif));
1172 syslog(LOG_ERR, "pfi_refresh(): reallocf() numifs=%d: %s",
1173 numifs, strerror(errno));
1176 io.pfiio_size = numifs;
1177 io.pfiio_buffer = p;
1179 if (ioctl(dev, DIOCIGETIFACES, &io)) {
1180 syslog(LOG_ERR, "pfi_refresh(): ioctl(): %s",
1185 if (numifs >= io.pfiio_size)
1188 numifs = io.pfiio_size;
1191 for (i = 0; i < numifs; i++) {
1192 e = malloc(sizeof(struct pfi_entry));
1196 memcpy(&e->pfi, p+i, sizeof(struct pfi_kif));
1197 TAILQ_INSERT_TAIL(&pfi_table, e, link);
1200 pfi_table_age = time(NULL);
1201 pfi_table_count = numifs;
1202 pf_tick = this_tick;
1208 while (!TAILQ_EMPTY(&pfi_table)) {
1209 e = TAILQ_FIRST(&pfi_table);
1210 TAILQ_REMOVE(&pfi_table, e, link);
1221 struct pfioc_altq pa;
1222 struct pfq_entry *e;
1223 int i, numqs, ticket;
1225 if (started && this_tick <= pf_tick)
1228 while (!TAILQ_EMPTY(&pfq_table)) {
1229 e = TAILQ_FIRST(&pfq_table);
1230 TAILQ_REMOVE(&pfq_table, e, link);
1234 bzero(&pa, sizeof(pa));
1235 pa.version = PFIOC_ALTQ_VERSION;
1236 if (ioctl(dev, DIOCGETALTQS, &pa)) {
1237 syslog(LOG_ERR, "pfq_refresh: ioctl(DIOCGETALTQS): %s",
1245 for (i = 0; i < numqs; i++) {
1246 e = malloc(sizeof(struct pfq_entry));
1248 syslog(LOG_ERR, "pfq_refresh(): "
1256 if (ioctl(dev, DIOCGETALTQ, &pa)) {
1257 syslog(LOG_ERR, "pfq_refresh(): "
1258 "ioctl(DIOCGETALTQ): %s",
1263 if (pa.altq.qid > 0) {
1264 memcpy(&e->altq, &pa.altq, sizeof(struct pf_altq));
1265 e->index = pa.altq.qid;
1266 pfq_table_count = i;
1267 INSERT_OBJECT_INT_LINK_INDEX(e, &pfq_table, link, index);
1271 pfq_table_age = time(NULL);
1272 pf_tick = this_tick;
1277 while (!TAILQ_EMPTY(&pfq_table)) {
1278 e = TAILQ_FIRST(&pfq_table);
1279 TAILQ_REMOVE(&pfq_table, e, link);
1288 if (started && this_tick <= pf_tick)
1291 bzero(&pfs, sizeof(struct pf_status));
1293 if (ioctl(dev, DIOCGETSTATUS, &pfs)) {
1294 syslog(LOG_ERR, "pfs_refresh(): ioctl(): %s",
1299 pf_tick = this_tick;
1306 struct pfioc_table io;
1307 struct pfr_tstats *t = NULL;
1308 struct pft_entry *e;
1311 if (started && this_tick <= pf_tick)
1314 while (!TAILQ_EMPTY(&pft_table)) {
1315 e = TAILQ_FIRST(&pft_table);
1316 TAILQ_REMOVE(&pft_table, e, link);
1320 bzero(&io, sizeof(io));
1321 io.pfrio_esize = sizeof(struct pfr_tstats);
1324 t = reallocf(t, numtbls * sizeof(struct pfr_tstats));
1326 syslog(LOG_ERR, "pft_refresh(): reallocf() numtbls=%d: %s",
1327 numtbls, strerror(errno));
1330 io.pfrio_size = numtbls;
1331 io.pfrio_buffer = t;
1333 if (ioctl(dev, DIOCRGETTSTATS, &io)) {
1334 syslog(LOG_ERR, "pft_refresh(): ioctl(): %s",
1339 if (numtbls >= io.pfrio_size)
1342 numtbls = io.pfrio_size;
1345 for (i = 0; i < numtbls; i++) {
1346 e = malloc(sizeof(struct pft_entry));
1350 memcpy(&e->pft, t+i, sizeof(struct pfr_tstats));
1351 TAILQ_INSERT_TAIL(&pft_table, e, link);
1354 pft_table_age = time(NULL);
1355 pft_table_count = numtbls;
1356 pf_tick = this_tick;
1361 while (!TAILQ_EMPTY(&pft_table)) {
1362 e = TAILQ_FIRST(&pft_table);
1363 TAILQ_REMOVE(&pft_table, e, link);
1372 pfa_table_addrs(u_int sidx, struct pfr_table *pt)
1374 struct pfioc_table io;
1375 struct pfr_astats *t = NULL;
1376 struct pfa_entry *e;
1377 int i, numaddrs = 1;
1382 memset(&io, 0, sizeof(io));
1383 strlcpy(io.pfrio_table.pfrt_name, pt->pfrt_name,
1384 sizeof(io.pfrio_table.pfrt_name));
1387 t = reallocf(t, numaddrs * sizeof(struct pfr_astats));
1389 syslog(LOG_ERR, "pfa_table_addrs(): reallocf(): %s",
1395 memset(t, 0, sizeof(*t));
1396 io.pfrio_size = numaddrs;
1397 io.pfrio_buffer = t;
1398 io.pfrio_esize = sizeof(struct pfr_astats);
1400 if (ioctl(dev, DIOCRGETASTATS, &io)) {
1401 syslog(LOG_ERR, "pfa_table_addrs(): ioctl() on %s: %s",
1402 pt->pfrt_name, strerror(errno));
1407 if (numaddrs >= io.pfrio_size)
1410 numaddrs = io.pfrio_size;
1413 for (i = 0; i < numaddrs; i++) {
1414 if ((t + i)->pfras_a.pfra_af != AF_INET &&
1415 (t + i)->pfras_a.pfra_af != AF_INET6) {
1420 e = (struct pfa_entry *)malloc(sizeof(struct pfa_entry));
1422 syslog(LOG_ERR, "pfa_table_addrs(): malloc(): %s",
1427 e->index = sidx + i;
1428 memcpy(&e->pfas, t + i, sizeof(struct pfr_astats));
1429 TAILQ_INSERT_TAIL(&pfa_table, e, link);
1440 struct pfioc_table io;
1441 struct pfr_table *pt = NULL, *it = NULL;
1442 struct pfa_entry *e;
1443 int i, numtbls = 1, cidx, naddrs;
1445 if (started && this_tick <= pf_tick)
1448 while (!TAILQ_EMPTY(&pfa_table)) {
1449 e = TAILQ_FIRST(&pfa_table);
1450 TAILQ_REMOVE(&pfa_table, e, link);
1454 memset(&io, 0, sizeof(io));
1455 io.pfrio_esize = sizeof(struct pfr_table);
1458 pt = reallocf(pt, numtbls * sizeof(struct pfr_table));
1460 syslog(LOG_ERR, "pfa_refresh(): reallocf() %s",
1464 memset(pt, 0, sizeof(*pt));
1465 io.pfrio_size = numtbls;
1466 io.pfrio_buffer = pt;
1468 if (ioctl(dev, DIOCRGETTABLES, &io)) {
1469 syslog(LOG_ERR, "pfa_refresh(): ioctl(): %s",
1474 if (numtbls >= io.pfrio_size)
1477 numtbls = io.pfrio_size;
1482 for (it = pt, i = 0; i < numtbls; it++, i++) {
1484 * Skip the table if not active - ioctl(DIOCRGETASTATS) will
1485 * return ESRCH for this entry anyway.
1487 if (!(it->pfrt_flags & PFR_TFLAG_ACTIVE))
1490 if ((naddrs = pfa_table_addrs(cidx, it)) < 0)
1496 pfa_table_age = time(NULL);
1497 pfa_table_count = cidx;
1498 pf_tick = this_tick;
1503 while (!TAILQ_EMPTY(&pfa_table)) {
1504 e = TAILQ_FIRST(&pfa_table);
1505 TAILQ_REMOVE(&pfa_table, e, link);
1515 pfl_scan_ruleset(const char *path)
1517 struct pfioc_rule pr;
1518 struct pfctl_rule rule;
1519 struct pfl_entry *e;
1522 bzero(&pr, sizeof(pr));
1523 strlcpy(pr.anchor, path, sizeof(pr.anchor));
1524 pr.rule.action = PF_PASS;
1525 if (ioctl(dev, DIOCGETRULES, &pr)) {
1526 syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULES): %s",
1531 for (nr = pr.nr, i = 0; i < nr; i++) {
1533 if (pfctl_add_rule(dev, &rule, pr.anchor, pr.anchor_call,
1534 pr.ticket, pr.pool_ticket)) {
1535 syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULE):"
1536 " %s", strerror(errno));
1540 if (rule.label[0]) {
1541 e = (struct pfl_entry *)malloc(sizeof(*e));
1545 strlcpy(e->name, path, sizeof(e->name));
1547 strlcat(e->name, "/", sizeof(e->name));
1548 strlcat(e->name, rule.label, sizeof(e->name));
1550 e->evals = rule.evaluations;
1551 e->bytes[IN] = rule.bytes[IN];
1552 e->bytes[OUT] = rule.bytes[OUT];
1553 e->pkts[IN] = rule.packets[IN];
1554 e->pkts[OUT] = rule.packets[OUT];
1555 e->index = ++pfl_table_count;
1557 TAILQ_INSERT_TAIL(&pfl_table, e, link);
1568 pfl_walk_rulesets(const char *path)
1570 struct pfioc_ruleset prs;
1571 char newpath[MAXPATHLEN];
1574 if (pfl_scan_ruleset(path))
1577 bzero(&prs, sizeof(prs));
1578 strlcpy(prs.path, path, sizeof(prs.path));
1579 if (ioctl(dev, DIOCGETRULESETS, &prs)) {
1580 syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESETS): %s",
1585 for (nr = prs.nr, i = 0; i < nr; i++) {
1587 if (ioctl(dev, DIOCGETRULESET, &prs)) {
1588 syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESET):"
1589 " %s", strerror(errno));
1593 if (strcmp(prs.name, PF_RESERVED_ANCHOR) == 0)
1596 strlcpy(newpath, path, sizeof(newpath));
1598 strlcat(newpath, "/", sizeof(newpath));
1600 strlcat(newpath, prs.name, sizeof(newpath));
1601 if (pfl_walk_rulesets(newpath))
1614 struct pfl_entry *e;
1616 if (started && this_tick <= pf_tick)
1619 while (!TAILQ_EMPTY(&pfl_table)) {
1620 e = TAILQ_FIRST(&pfl_table);
1621 TAILQ_REMOVE(&pfl_table, e, link);
1624 pfl_table_count = 0;
1626 if (pfl_walk_rulesets(""))
1629 pfl_table_age = time(NULL);
1630 pf_tick = this_tick;
1635 while (!TAILQ_EMPTY(&pfl_table)) {
1636 e = TAILQ_FIRST(&pfl_table);
1637 TAILQ_REMOVE(&pfl_table, e, link);
1640 pfl_table_count = 0;
1646 * check whether altq support is enabled in kernel
1650 altq_is_enabled(int pfdev)
1652 struct pfioc_altq pa;
1655 pa.version = PFIOC_ALTQ_VERSION;
1656 if (ioctl(pfdev, DIOCGETALTQS, &pa)) {
1657 if (errno == ENODEV) {
1658 syslog(LOG_INFO, "No ALTQ support in kernel\n"
1659 "ALTQ related functions disabled\n");
1662 syslog(LOG_ERR, "DIOCGETALTQS returned an error: %s",
1671 * Implement the bsnmpd module interface
1674 pf_init(struct lmodule *mod, int __unused argc, char __unused *argv[])
1678 if ((dev = open("/dev/pf", O_RDONLY)) == -1) {
1679 syslog(LOG_ERR, "pf_init(): open(): %s\n",
1684 if ((altq_enabled = altq_is_enabled(dev)) == -1) {
1685 syslog(LOG_ERR, "pf_init(): altq test failed");
1689 /* Prepare internal state */
1690 TAILQ_INIT(&pfi_table);
1691 TAILQ_INIT(&pfq_table);
1692 TAILQ_INIT(&pft_table);
1693 TAILQ_INIT(&pfa_table);
1694 TAILQ_INIT(&pfl_table);
1714 struct pfi_entry *i1, *i2;
1715 struct pfq_entry *q1, *q2;
1716 struct pft_entry *t1, *t2;
1717 struct pfa_entry *a1, *a2;
1718 struct pfl_entry *l1, *l2;
1720 /* Empty the list of interfaces */
1721 i1 = TAILQ_FIRST(&pfi_table);
1722 while (i1 != NULL) {
1723 i2 = TAILQ_NEXT(i1, link);
1728 /* List of queues */
1729 q1 = TAILQ_FIRST(&pfq_table);
1730 while (q1 != NULL) {
1731 q2 = TAILQ_NEXT(q1, link);
1736 /* List of tables */
1737 t1 = TAILQ_FIRST(&pft_table);
1738 while (t1 != NULL) {
1739 t2 = TAILQ_NEXT(t1, link);
1744 /* List of table addresses */
1745 a1 = TAILQ_FIRST(&pfa_table);
1746 while (a1 != NULL) {
1747 a2 = TAILQ_NEXT(a1, link);
1752 /* And the list of labeled filter rules */
1753 l1 = TAILQ_FIRST(&pfl_table);
1754 while (l1 != NULL) {
1755 l2 = TAILQ_NEXT(l1, link);
1775 syslog(LOG_ERR, "Dump: pfi_table_age = %jd",
1776 (intmax_t)pfi_table_age);
1777 syslog(LOG_ERR, "Dump: pfi_table_count = %d",
1780 syslog(LOG_ERR, "Dump: pfq_table_age = %jd",
1781 (intmax_t)pfq_table_age);
1782 syslog(LOG_ERR, "Dump: pfq_table_count = %d",
1785 syslog(LOG_ERR, "Dump: pft_table_age = %jd",
1786 (intmax_t)pft_table_age);
1787 syslog(LOG_ERR, "Dump: pft_table_count = %d",
1790 syslog(LOG_ERR, "Dump: pfa_table_age = %jd",
1791 (intmax_t)pfa_table_age);
1792 syslog(LOG_ERR, "Dump: pfa_table_count = %d",
1795 syslog(LOG_ERR, "Dump: pfl_table_age = %jd",
1796 (intmax_t)pfl_table_age);
1797 syslog(LOG_ERR, "Dump: pfl_table_count = %d",
1801 const struct snmp_module config = {
1802 .comment = "This module implements a MIB for the pf packet filter.",
1807 .tree_size = pf_CTREE_SIZE,