1143611Sphilip/*-
2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3330449Seadler *
4143611Sphilip * Copyright (c) 2005 Philip Paeps <philip@FreeBSD.org>
5143611Sphilip * All rights reserved.
6143611Sphilip *
7143611Sphilip * Redistribution and use in source and binary forms, with or without
8143611Sphilip * modification, are permitted provided that the following conditions
9143611Sphilip * are met:
10143611Sphilip * 1. Redistributions of source code must retain the above copyright
11143611Sphilip *    notice, this list of conditions and the following disclaimer.
12143611Sphilip * 2. Redistributions in binary form must reproduce the above copyright
13143611Sphilip *    notice, this list of conditions and the following disclaimer in the
14143611Sphilip *    documentation and/or other materials provided with the distribution.
15143611Sphilip *
16143611Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17143611Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18143611Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19143611Sphilip * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20143611Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21143611Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22143611Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23143611Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24143611Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25143611Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26143611Sphilip * SUCH DAMAGE.
27143611Sphilip *
28143611Sphilip * $FreeBSD: stable/11/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c 357523 2020-02-04 19:46:29Z dim $
29143611Sphilip */
30143611Sphilip
31216294Ssyrinx#include <sys/queue.h>
32143611Sphilip#include <bsnmp/snmpmod.h>
33143611Sphilip
34143611Sphilip#include <net/pfvar.h>
35143611Sphilip#include <sys/ioctl.h>
36143611Sphilip
37143611Sphilip#include <errno.h>
38143611Sphilip#include <fcntl.h>
39143626Sphilip#include <stdint.h>
40143611Sphilip#include <stdio.h>
41143611Sphilip#include <stdlib.h>
42143611Sphilip#include <string.h>
43143611Sphilip#include <syslog.h>
44143611Sphilip#include <unistd.h>
45143611Sphilip
46143611Sphilip#include "pf_oid.h"
47143611Sphilip#include "pf_tree.h"
48143611Sphilip
49143611Sphilipstruct lmodule *module;
50143611Sphilip
51143611Sphilipstatic int dev = -1;
52143611Sphilipstatic int started;
53146531Sphilipstatic uint64_t pf_tick;
54143611Sphilip
55143611Sphilipstatic struct pf_status pfs;
56143611Sphilip
57143611Sphilipenum { IN, OUT };
58143611Sphilipenum { IPV4, IPV6 };
59143611Sphilipenum { PASS, BLOCK };
60143611Sphilip
61143611Sphilip#define PFI_IFTYPE_GROUP	0
62143611Sphilip#define PFI_IFTYPE_INSTANCE	1
63143611Sphilip#define PFI_IFTYPE_DETACHED	2
64143611Sphilip
65143611Sphilipstruct pfi_entry {
66171173Smlaier	struct pfi_kif	pfi;
67143611Sphilip	u_int		index;
68143611Sphilip	TAILQ_ENTRY(pfi_entry) link;
69143611Sphilip};
70143611SphilipTAILQ_HEAD(pfi_table, pfi_entry);
71143611Sphilip
72143611Sphilipstatic struct pfi_table pfi_table;
73143611Sphilipstatic time_t pfi_table_age;
74143611Sphilipstatic int pfi_table_count;
75143611Sphilip
76143611Sphilip#define PFI_TABLE_MAXAGE	5
77143611Sphilip
78143611Sphilipstruct pft_entry {
79143611Sphilip	struct pfr_tstats pft;
80143611Sphilip	u_int		index;
81143611Sphilip	TAILQ_ENTRY(pft_entry) link;
82143611Sphilip};
83143611SphilipTAILQ_HEAD(pft_table, pft_entry);
84143611Sphilip
85143611Sphilipstatic struct pft_table pft_table;
86143611Sphilipstatic time_t pft_table_age;
87143611Sphilipstatic int pft_table_count;
88143611Sphilip
89143611Sphilip#define PFT_TABLE_MAXAGE	5
90143611Sphilip
91205607Ssyrinxstruct pfa_entry {
92205607Ssyrinx	struct pfr_astats pfas;
93205607Ssyrinx	u_int		index;
94205607Ssyrinx	TAILQ_ENTRY(pfa_entry) link;
95205607Ssyrinx};
96205607SsyrinxTAILQ_HEAD(pfa_table, pfa_entry);
97205607Ssyrinx
98205607Ssyrinxstatic struct pfa_table pfa_table;
99205607Ssyrinxstatic time_t pfa_table_age;
100205607Ssyrinxstatic int pfa_table_count;
101205607Ssyrinx
102205607Ssyrinx#define	PFA_TABLE_MAXAGE	5
103205607Ssyrinx
104143611Sphilipstruct pfq_entry {
105143611Sphilip	struct pf_altq	altq;
106143611Sphilip	u_int		index;
107143611Sphilip	TAILQ_ENTRY(pfq_entry) link;
108143611Sphilip};
109143611SphilipTAILQ_HEAD(pfq_table, pfq_entry);
110143611Sphilip
111143611Sphilipstatic struct pfq_table pfq_table;
112143611Sphilipstatic time_t pfq_table_age;
113143611Sphilipstatic int pfq_table_count;
114143611Sphilip
115152970Sphilipstatic int altq_enabled = 0;
116152970Sphilip
117143611Sphilip#define PFQ_TABLE_MAXAGE	5
118143611Sphilip
119205280Ssyrinxstruct pfl_entry {
120205280Ssyrinx	char		name[MAXPATHLEN + PF_RULE_LABEL_SIZE];
121205280Ssyrinx	u_int64_t	evals;
122205280Ssyrinx	u_int64_t	bytes[2];
123205280Ssyrinx	u_int64_t	pkts[2];
124205280Ssyrinx	u_int		index;
125205280Ssyrinx	TAILQ_ENTRY(pfl_entry) link;
126205280Ssyrinx};
127205280SsyrinxTAILQ_HEAD(pfl_table, pfl_entry);
128205280Ssyrinx
129205280Ssyrinxstatic struct pfl_table pfl_table;
130205280Ssyrinxstatic time_t pfl_table_age;
131205280Ssyrinxstatic int pfl_table_count;
132205280Ssyrinx
133205280Ssyrinx#define	PFL_TABLE_MAXAGE	5
134205280Ssyrinx
135143611Sphilip/* Forward declarations */
136143611Sphilipstatic int pfi_refresh(void);
137143611Sphilipstatic int pfq_refresh(void);
138143611Sphilipstatic int pfs_refresh(void);
139143611Sphilipstatic int pft_refresh(void);
140205607Ssyrinxstatic int pfa_refresh(void);
141205280Ssyrinxstatic int pfl_refresh(void);
142143611Sphilipstatic struct pfi_entry * pfi_table_find(u_int idx);
143143611Sphilipstatic struct pfq_entry * pfq_table_find(u_int idx);
144143611Sphilipstatic struct pft_entry * pft_table_find(u_int idx);
145205607Ssyrinxstatic struct pfa_entry * pfa_table_find(u_int idx);
146205280Ssyrinxstatic struct pfl_entry * pfl_table_find(u_int idx);
147143611Sphilip
148152970Sphilipstatic int altq_is_enabled(int pfdevice);
149152970Sphilip
150143611Sphilipint
151143611Sphilippf_status(struct snmp_context __unused *ctx, struct snmp_value *val,
152143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
153143611Sphilip{
154143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
155143611Sphilip	time_t		runtime;
156143611Sphilip	unsigned char	str[128];
157143611Sphilip
158143611Sphilip	if (op == SNMP_OP_SET)
159143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
160143611Sphilip
161143611Sphilip	if (op == SNMP_OP_GET) {
162143611Sphilip		if (pfs_refresh() == -1)
163143611Sphilip			return (SNMP_ERR_GENERR);
164143611Sphilip
165143611Sphilip		switch (which) {
166143611Sphilip			case LEAF_pfStatusRunning:
167143611Sphilip			    val->v.uint32 = pfs.running;
168143611Sphilip			    break;
169143611Sphilip			case LEAF_pfStatusRuntime:
170143611Sphilip			    runtime = (pfs.since > 0) ?
171143611Sphilip				time(NULL) - pfs.since : 0;
172143611Sphilip			    val->v.uint32 = runtime * 100;
173143611Sphilip			    break;
174143611Sphilip			case LEAF_pfStatusDebug:
175143611Sphilip			    val->v.uint32 = pfs.debug;
176143611Sphilip			    break;
177143611Sphilip			case LEAF_pfStatusHostId:
178143611Sphilip			    sprintf(str, "0x%08x", ntohl(pfs.hostid));
179143611Sphilip			    return (string_get(val, str, strlen(str)));
180143611Sphilip
181143611Sphilip			default:
182143611Sphilip			    return (SNMP_ERR_NOSUCHNAME);
183143611Sphilip		}
184143611Sphilip
185143611Sphilip		return (SNMP_ERR_NOERROR);
186143611Sphilip	}
187143611Sphilip
188143611Sphilip	abort();
189143611Sphilip}
190143611Sphilip
191143611Sphilipint
192143611Sphilippf_counter(struct snmp_context __unused *ctx, struct snmp_value *val,
193143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
194143611Sphilip{
195143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
196143611Sphilip
197143611Sphilip	if (op == SNMP_OP_SET)
198143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
199143611Sphilip
200143611Sphilip	if (op == SNMP_OP_GET) {
201143611Sphilip		if (pfs_refresh() == -1)
202143611Sphilip			return (SNMP_ERR_GENERR);
203143611Sphilip
204143611Sphilip		switch (which) {
205143611Sphilip			case LEAF_pfCounterMatch:
206143611Sphilip				val->v.counter64 = pfs.counters[PFRES_MATCH];
207143611Sphilip				break;
208143611Sphilip			case LEAF_pfCounterBadOffset:
209143611Sphilip				val->v.counter64 = pfs.counters[PFRES_BADOFF];
210143611Sphilip				break;
211143611Sphilip			case LEAF_pfCounterFragment:
212143611Sphilip				val->v.counter64 = pfs.counters[PFRES_FRAG];
213143611Sphilip				break;
214143611Sphilip			case LEAF_pfCounterShort:
215143611Sphilip				val->v.counter64 = pfs.counters[PFRES_SHORT];
216143611Sphilip				break;
217143611Sphilip			case LEAF_pfCounterNormalize:
218143611Sphilip				val->v.counter64 = pfs.counters[PFRES_NORM];
219143611Sphilip				break;
220143611Sphilip			case LEAF_pfCounterMemDrop:
221143611Sphilip				val->v.counter64 = pfs.counters[PFRES_MEMORY];
222143611Sphilip				break;
223143611Sphilip
224143611Sphilip			default:
225143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
226143611Sphilip		}
227143611Sphilip
228143611Sphilip		return (SNMP_ERR_NOERROR);
229143611Sphilip	}
230143611Sphilip
231143611Sphilip	abort();
232143611Sphilip}
233143611Sphilip
234143611Sphilipint
235143611Sphilippf_statetable(struct snmp_context __unused *ctx, struct snmp_value *val,
236143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
237143611Sphilip{
238143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
239143611Sphilip
240143611Sphilip	if (op == SNMP_OP_SET)
241143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
242143611Sphilip
243143611Sphilip	if (op == SNMP_OP_GET) {
244143611Sphilip		if (pfs_refresh() == -1)
245143611Sphilip			return (SNMP_ERR_GENERR);
246143611Sphilip
247143611Sphilip		switch (which) {
248143611Sphilip			case LEAF_pfStateTableCount:
249143611Sphilip				val->v.uint32 = pfs.states;
250143611Sphilip				break;
251143611Sphilip			case LEAF_pfStateTableSearches:
252143611Sphilip				val->v.counter64 =
253143611Sphilip				    pfs.fcounters[FCNT_STATE_SEARCH];
254143611Sphilip				break;
255143611Sphilip			case LEAF_pfStateTableInserts:
256143611Sphilip				val->v.counter64 =
257143611Sphilip				    pfs.fcounters[FCNT_STATE_INSERT];
258143611Sphilip				break;
259143611Sphilip			case LEAF_pfStateTableRemovals:
260143611Sphilip				val->v.counter64 =
261143611Sphilip				    pfs.fcounters[FCNT_STATE_REMOVALS];
262143611Sphilip				break;
263143611Sphilip
264143611Sphilip			default:
265143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
266143611Sphilip		}
267143611Sphilip
268143611Sphilip		return (SNMP_ERR_NOERROR);
269143611Sphilip	}
270143611Sphilip
271143611Sphilip	abort();
272143611Sphilip}
273143611Sphilip
274143611Sphilipint
275143611Sphilippf_srcnodes(struct snmp_context __unused *ctx, struct snmp_value *val,
276143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
277143611Sphilip{
278143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
279143611Sphilip
280143611Sphilip	if (op == SNMP_OP_SET)
281143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
282143611Sphilip
283143611Sphilip	if (op == SNMP_OP_GET) {
284143611Sphilip		if (pfs_refresh() == -1)
285143611Sphilip			return (SNMP_ERR_GENERR);
286143611Sphilip
287143611Sphilip		switch (which) {
288143611Sphilip			case LEAF_pfSrcNodesCount:
289143611Sphilip				val->v.uint32 = pfs.src_nodes;
290143611Sphilip				break;
291143611Sphilip			case LEAF_pfSrcNodesSearches:
292143611Sphilip				val->v.counter64 =
293143611Sphilip				    pfs.scounters[SCNT_SRC_NODE_SEARCH];
294143611Sphilip				break;
295143611Sphilip			case LEAF_pfSrcNodesInserts:
296143611Sphilip				val->v.counter64 =
297143611Sphilip				    pfs.scounters[SCNT_SRC_NODE_INSERT];
298143611Sphilip				break;
299143611Sphilip			case LEAF_pfSrcNodesRemovals:
300143611Sphilip				val->v.counter64 =
301143611Sphilip				    pfs.scounters[SCNT_SRC_NODE_REMOVALS];
302143611Sphilip				break;
303143611Sphilip
304143611Sphilip			default:
305143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
306143611Sphilip		}
307143611Sphilip
308143611Sphilip		return (SNMP_ERR_NOERROR);
309143611Sphilip	}
310143611Sphilip
311143611Sphilip	abort();
312143611Sphilip}
313143611Sphilip
314143611Sphilipint
315143611Sphilippf_limits(struct snmp_context __unused *ctx, struct snmp_value *val,
316143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
317143611Sphilip{
318143611Sphilip	asn_subid_t		which = val->var.subs[sub - 1];
319143611Sphilip	struct pfioc_limit	pl;
320143611Sphilip
321143611Sphilip	if (op == SNMP_OP_SET)
322143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
323143611Sphilip
324143611Sphilip	if (op == SNMP_OP_GET) {
325143611Sphilip		bzero(&pl, sizeof(struct pfioc_limit));
326143611Sphilip
327143611Sphilip		switch (which) {
328143611Sphilip			case LEAF_pfLimitsStates:
329143611Sphilip				pl.index = PF_LIMIT_STATES;
330143611Sphilip				break;
331143611Sphilip			case LEAF_pfLimitsSrcNodes:
332143611Sphilip				pl.index = PF_LIMIT_SRC_NODES;
333143611Sphilip				break;
334143611Sphilip			case LEAF_pfLimitsFrags:
335143611Sphilip				pl.index = PF_LIMIT_FRAGS;
336143611Sphilip				break;
337143611Sphilip
338143611Sphilip			default:
339143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
340143611Sphilip		}
341143611Sphilip
342143611Sphilip		if (ioctl(dev, DIOCGETLIMIT, &pl)) {
343143611Sphilip			syslog(LOG_ERR, "pf_limits(): ioctl(): %s",
344143611Sphilip			    strerror(errno));
345143611Sphilip			return (SNMP_ERR_GENERR);
346143611Sphilip		}
347143611Sphilip
348143611Sphilip		val->v.uint32 = pl.limit;
349143611Sphilip
350143611Sphilip		return (SNMP_ERR_NOERROR);
351143611Sphilip	}
352143611Sphilip
353143611Sphilip	abort();
354143611Sphilip}
355143611Sphilip
356143611Sphilipint
357143611Sphilippf_timeouts(struct snmp_context __unused *ctx, struct snmp_value *val,
358143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
359143611Sphilip{
360143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
361143611Sphilip	struct pfioc_tm	pt;
362143611Sphilip
363143611Sphilip	if (op == SNMP_OP_SET)
364143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
365143611Sphilip
366143611Sphilip	if (op == SNMP_OP_GET) {
367143611Sphilip		bzero(&pt, sizeof(struct pfioc_tm));
368143611Sphilip
369143611Sphilip		switch (which) {
370143611Sphilip			case LEAF_pfTimeoutsTcpFirst:
371143611Sphilip				pt.timeout = PFTM_TCP_FIRST_PACKET;
372143611Sphilip				break;
373143611Sphilip			case LEAF_pfTimeoutsTcpOpening:
374143611Sphilip				pt.timeout = PFTM_TCP_OPENING;
375143611Sphilip				break;
376143611Sphilip			case LEAF_pfTimeoutsTcpEstablished:
377143611Sphilip				pt.timeout = PFTM_TCP_ESTABLISHED;
378143611Sphilip				break;
379143611Sphilip			case LEAF_pfTimeoutsTcpClosing:
380143611Sphilip				pt.timeout = PFTM_TCP_CLOSING;
381143611Sphilip				break;
382143611Sphilip			case LEAF_pfTimeoutsTcpFinWait:
383143611Sphilip				pt.timeout = PFTM_TCP_FIN_WAIT;
384143611Sphilip				break;
385143611Sphilip			case LEAF_pfTimeoutsTcpClosed:
386143611Sphilip				pt.timeout = PFTM_TCP_CLOSED;
387143611Sphilip				break;
388143611Sphilip			case LEAF_pfTimeoutsUdpFirst:
389143611Sphilip				pt.timeout = PFTM_UDP_FIRST_PACKET;
390143611Sphilip				break;
391143611Sphilip			case LEAF_pfTimeoutsUdpSingle:
392143611Sphilip				pt.timeout = PFTM_UDP_SINGLE;
393143611Sphilip				break;
394143611Sphilip			case LEAF_pfTimeoutsUdpMultiple:
395143611Sphilip				pt.timeout = PFTM_UDP_MULTIPLE;
396143611Sphilip				break;
397143611Sphilip			case LEAF_pfTimeoutsIcmpFirst:
398143611Sphilip				pt.timeout = PFTM_ICMP_FIRST_PACKET;
399143611Sphilip				break;
400143611Sphilip			case LEAF_pfTimeoutsIcmpError:
401143611Sphilip				pt.timeout = PFTM_ICMP_ERROR_REPLY;
402143611Sphilip				break;
403143611Sphilip			case LEAF_pfTimeoutsOtherFirst:
404143611Sphilip				pt.timeout = PFTM_OTHER_FIRST_PACKET;
405143611Sphilip				break;
406143611Sphilip			case LEAF_pfTimeoutsOtherSingle:
407143611Sphilip				pt.timeout = PFTM_OTHER_SINGLE;
408143611Sphilip				break;
409143611Sphilip			case LEAF_pfTimeoutsOtherMultiple:
410143611Sphilip				pt.timeout = PFTM_OTHER_MULTIPLE;
411143611Sphilip				break;
412143611Sphilip			case LEAF_pfTimeoutsFragment:
413143611Sphilip				pt.timeout = PFTM_FRAG;
414143611Sphilip				break;
415143611Sphilip			case LEAF_pfTimeoutsInterval:
416143611Sphilip				pt.timeout = PFTM_INTERVAL;
417143611Sphilip				break;
418143611Sphilip			case LEAF_pfTimeoutsAdaptiveStart:
419143611Sphilip				pt.timeout = PFTM_ADAPTIVE_START;
420143611Sphilip				break;
421143611Sphilip			case LEAF_pfTimeoutsAdaptiveEnd:
422143611Sphilip				pt.timeout = PFTM_ADAPTIVE_END;
423143611Sphilip				break;
424143611Sphilip			case LEAF_pfTimeoutsSrcNode:
425143611Sphilip				pt.timeout = PFTM_SRC_NODE;
426143611Sphilip				break;
427143611Sphilip
428143611Sphilip			default:
429143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
430143611Sphilip		}
431143611Sphilip
432143611Sphilip		if (ioctl(dev, DIOCGETTIMEOUT, &pt)) {
433143611Sphilip			syslog(LOG_ERR, "pf_timeouts(): ioctl(): %s",
434143611Sphilip			    strerror(errno));
435143611Sphilip			return (SNMP_ERR_GENERR);
436143611Sphilip		}
437143611Sphilip
438143611Sphilip		val->v.integer = pt.seconds;
439143611Sphilip
440143611Sphilip		return (SNMP_ERR_NOERROR);
441143611Sphilip	}
442143611Sphilip
443143611Sphilip	abort();
444143611Sphilip}
445143611Sphilip
446143611Sphilipint
447143611Sphilippf_logif(struct snmp_context __unused *ctx, struct snmp_value *val,
448143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
449143611Sphilip{
450143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
451143611Sphilip	unsigned char	str[IFNAMSIZ];
452143611Sphilip
453143611Sphilip	if (op == SNMP_OP_SET)
454143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
455143611Sphilip
456143611Sphilip	if (op == SNMP_OP_GET) {
457143611Sphilip		if (pfs_refresh() == -1)
458143611Sphilip			return (SNMP_ERR_GENERR);
459143611Sphilip
460143611Sphilip		switch (which) {
461143611Sphilip	 		case LEAF_pfLogInterfaceName:
462143611Sphilip				strlcpy(str, pfs.ifname, sizeof str);
463143611Sphilip				return (string_get(val, str, strlen(str)));
464143611Sphilip			case LEAF_pfLogInterfaceIp4BytesIn:
465143611Sphilip				val->v.counter64 = pfs.bcounters[IPV4][IN];
466143611Sphilip				break;
467143611Sphilip			case LEAF_pfLogInterfaceIp4BytesOut:
468143611Sphilip				val->v.counter64 = pfs.bcounters[IPV4][OUT];
469143611Sphilip				break;
470143611Sphilip			case LEAF_pfLogInterfaceIp4PktsInPass:
471143611Sphilip				val->v.counter64 =
472143611Sphilip				    pfs.pcounters[IPV4][IN][PF_PASS];
473143611Sphilip				break;
474143611Sphilip			case LEAF_pfLogInterfaceIp4PktsInDrop:
475143611Sphilip				val->v.counter64 =
476143611Sphilip				    pfs.pcounters[IPV4][IN][PF_DROP];
477143611Sphilip				break;
478143611Sphilip			case LEAF_pfLogInterfaceIp4PktsOutPass:
479143611Sphilip				val->v.counter64 =
480143611Sphilip				    pfs.pcounters[IPV4][OUT][PF_PASS];
481143611Sphilip				break;
482143611Sphilip			case LEAF_pfLogInterfaceIp4PktsOutDrop:
483143611Sphilip				val->v.counter64 =
484143611Sphilip				    pfs.pcounters[IPV4][OUT][PF_DROP];
485143611Sphilip				break;
486143611Sphilip			case LEAF_pfLogInterfaceIp6BytesIn:
487143611Sphilip				val->v.counter64 = pfs.bcounters[IPV6][IN];
488143611Sphilip				break;
489143611Sphilip			case LEAF_pfLogInterfaceIp6BytesOut:
490143611Sphilip				val->v.counter64 = pfs.bcounters[IPV6][OUT];
491143611Sphilip				break;
492143611Sphilip			case LEAF_pfLogInterfaceIp6PktsInPass:
493143611Sphilip				val->v.counter64 =
494143611Sphilip				    pfs.pcounters[IPV6][IN][PF_PASS];
495143611Sphilip				break;
496143611Sphilip			case LEAF_pfLogInterfaceIp6PktsInDrop:
497143611Sphilip				val->v.counter64 =
498143611Sphilip				    pfs.pcounters[IPV6][IN][PF_DROP];
499143611Sphilip				break;
500143611Sphilip			case LEAF_pfLogInterfaceIp6PktsOutPass:
501143611Sphilip				val->v.counter64 =
502143611Sphilip				    pfs.pcounters[IPV6][OUT][PF_PASS];
503143611Sphilip				break;
504143611Sphilip			case LEAF_pfLogInterfaceIp6PktsOutDrop:
505143611Sphilip				val->v.counter64 =
506143611Sphilip				    pfs.pcounters[IPV6][OUT][PF_DROP];
507143611Sphilip				break;
508143611Sphilip
509143611Sphilip			default:
510143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
511143611Sphilip		}
512143611Sphilip
513143611Sphilip		return (SNMP_ERR_NOERROR);
514143611Sphilip	}
515143611Sphilip
516143611Sphilip	abort();
517143611Sphilip}
518143611Sphilip
519143611Sphilipint
520143611Sphilippf_interfaces(struct snmp_context __unused *ctx, struct snmp_value *val,
521143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
522143611Sphilip{
523143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
524143611Sphilip
525143611Sphilip	if (op == SNMP_OP_SET)
526143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
527143611Sphilip
528143611Sphilip	if (op == SNMP_OP_GET) {
529143611Sphilip		if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE)
530143611Sphilip			if (pfi_refresh() == -1)
531143611Sphilip			    return (SNMP_ERR_GENERR);
532143611Sphilip
533143611Sphilip		switch (which) {
534143611Sphilip			case LEAF_pfInterfacesIfNumber:
535143611Sphilip				val->v.uint32 = pfi_table_count;
536143611Sphilip				break;
537143611Sphilip
538143611Sphilip			default:
539143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
540143611Sphilip		}
541143611Sphilip
542143611Sphilip		return (SNMP_ERR_NOERROR);
543143611Sphilip	}
544143611Sphilip
545143611Sphilip	abort();
546143611Sphilip}
547143611Sphilip
548143611Sphilipint
549143611Sphilippf_iftable(struct snmp_context __unused *ctx, struct snmp_value *val,
550143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
551143611Sphilip{
552143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
553143611Sphilip	struct pfi_entry *e = NULL;
554143611Sphilip
555205312Ssyrinx	if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE)
556205312Ssyrinx		pfi_refresh();
557205312Ssyrinx
558143611Sphilip	switch (op) {
559143611Sphilip		case SNMP_OP_SET:
560143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
561143611Sphilip		case SNMP_OP_GETNEXT:
562143611Sphilip			if ((e = NEXT_OBJECT_INT(&pfi_table,
563143611Sphilip			    &val->var, sub)) == NULL)
564143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
565143611Sphilip			val->var.len = sub + 1;
566143611Sphilip			val->var.subs[sub] = e->index;
567143611Sphilip			break;
568143611Sphilip		case SNMP_OP_GET:
569143611Sphilip			if (val->var.len - sub != 1)
570143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
571143611Sphilip			if ((e = pfi_table_find(val->var.subs[sub])) == NULL)
572143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
573143611Sphilip			break;
574143611Sphilip
575143611Sphilip		case SNMP_OP_COMMIT:
576143611Sphilip		case SNMP_OP_ROLLBACK:
577143611Sphilip		default:
578143611Sphilip			abort();
579143611Sphilip	}
580143611Sphilip
581143611Sphilip	switch (which) {
582143611Sphilip		case LEAF_pfInterfacesIfDescr:
583171173Smlaier			return (string_get(val, e->pfi.pfik_name, -1));
584143611Sphilip		case LEAF_pfInterfacesIfType:
585143611Sphilip			val->v.integer = PFI_IFTYPE_INSTANCE;
586143611Sphilip			break;
587143611Sphilip		case LEAF_pfInterfacesIfTZero:
588143611Sphilip			val->v.uint32 =
589171173Smlaier			    (time(NULL) - e->pfi.pfik_tzero) * 100;
590143611Sphilip			break;
591143611Sphilip		case LEAF_pfInterfacesIfRefsRule:
592240233Sglebius			val->v.uint32 = e->pfi.pfik_rulerefs;
593143611Sphilip			break;
594143611Sphilip		case LEAF_pfInterfacesIf4BytesInPass:
595143611Sphilip			val->v.counter64 =
596171173Smlaier			    e->pfi.pfik_bytes[IPV4][IN][PASS];
597143611Sphilip			break;
598143611Sphilip		case LEAF_pfInterfacesIf4BytesInBlock:
599143611Sphilip			val->v.counter64 =
600171173Smlaier			    e->pfi.pfik_bytes[IPV4][IN][BLOCK];
601143611Sphilip			break;
602143611Sphilip		case LEAF_pfInterfacesIf4BytesOutPass:
603143611Sphilip			val->v.counter64 =
604171173Smlaier			    e->pfi.pfik_bytes[IPV4][OUT][PASS];
605143611Sphilip			break;
606143611Sphilip		case LEAF_pfInterfacesIf4BytesOutBlock:
607143611Sphilip			val->v.counter64 =
608171173Smlaier			    e->pfi.pfik_bytes[IPV4][OUT][BLOCK];
609143611Sphilip			break;
610143611Sphilip		case LEAF_pfInterfacesIf4PktsInPass:
611143611Sphilip			val->v.counter64 =
612171173Smlaier			    e->pfi.pfik_packets[IPV4][IN][PASS];
613143611Sphilip			break;
614143611Sphilip		case LEAF_pfInterfacesIf4PktsInBlock:
615143611Sphilip			val->v.counter64 =
616171173Smlaier			    e->pfi.pfik_packets[IPV4][IN][BLOCK];
617143611Sphilip			break;
618143611Sphilip		case LEAF_pfInterfacesIf4PktsOutPass:
619143611Sphilip			val->v.counter64 =
620171173Smlaier			    e->pfi.pfik_packets[IPV4][OUT][PASS];
621143611Sphilip			break;
622143611Sphilip		case LEAF_pfInterfacesIf4PktsOutBlock:
623143611Sphilip			val->v.counter64 =
624171173Smlaier			    e->pfi.pfik_packets[IPV4][OUT][BLOCK];
625143611Sphilip			break;
626143611Sphilip		case LEAF_pfInterfacesIf6BytesInPass:
627143611Sphilip			val->v.counter64 =
628171173Smlaier			    e->pfi.pfik_bytes[IPV6][IN][PASS];
629143611Sphilip			break;
630143611Sphilip		case LEAF_pfInterfacesIf6BytesInBlock:
631143611Sphilip			val->v.counter64 =
632171173Smlaier			    e->pfi.pfik_bytes[IPV6][IN][BLOCK];
633143611Sphilip			break;
634143611Sphilip		case LEAF_pfInterfacesIf6BytesOutPass:
635143611Sphilip			val->v.counter64 =
636171173Smlaier			    e->pfi.pfik_bytes[IPV6][OUT][PASS];
637143611Sphilip			break;
638143611Sphilip		case LEAF_pfInterfacesIf6BytesOutBlock:
639143611Sphilip			val->v.counter64 =
640171173Smlaier			    e->pfi.pfik_bytes[IPV6][OUT][BLOCK];
641143611Sphilip			break;
642143611Sphilip		case LEAF_pfInterfacesIf6PktsInPass:
643143611Sphilip			val->v.counter64 =
644171173Smlaier			    e->pfi.pfik_packets[IPV6][IN][PASS];
645143611Sphilip			break;
646143611Sphilip		case LEAF_pfInterfacesIf6PktsInBlock:
647143611Sphilip			val->v.counter64 =
648171173Smlaier			    e->pfi.pfik_packets[IPV6][IN][BLOCK];
649143611Sphilip			break;
650143611Sphilip		case LEAF_pfInterfacesIf6PktsOutPass:
651143611Sphilip			val->v.counter64 =
652171173Smlaier			    e->pfi.pfik_packets[IPV6][OUT][PASS];
653143611Sphilip			break;
654143611Sphilip		case LEAF_pfInterfacesIf6PktsOutBlock:
655310901Sngie			val->v.counter64 =
656171173Smlaier			    e->pfi.pfik_packets[IPV6][OUT][BLOCK];
657143611Sphilip			break;
658143611Sphilip
659143611Sphilip		default:
660143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
661143611Sphilip	}
662143611Sphilip
663143611Sphilip	return (SNMP_ERR_NOERROR);
664143611Sphilip}
665143611Sphilip
666143611Sphilipint
667143611Sphilippf_tables(struct snmp_context __unused *ctx, struct snmp_value *val,
668143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
669143611Sphilip{
670143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
671143611Sphilip
672143611Sphilip	if (op == SNMP_OP_SET)
673143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
674143611Sphilip
675143611Sphilip	if (op == SNMP_OP_GET) {
676143611Sphilip		if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
677143611Sphilip			if (pft_refresh() == -1)
678143611Sphilip			    return (SNMP_ERR_GENERR);
679143611Sphilip
680143611Sphilip		switch (which) {
681143611Sphilip			case LEAF_pfTablesTblNumber:
682143611Sphilip				val->v.uint32 = pft_table_count;
683143611Sphilip				break;
684143611Sphilip
685143611Sphilip			default:
686143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
687143611Sphilip		}
688143611Sphilip
689143611Sphilip		return (SNMP_ERR_NOERROR);
690143611Sphilip	}
691143611Sphilip
692143611Sphilip	abort();
693143611Sphilip}
694143611Sphilip
695143611Sphilipint
696143611Sphilippf_tbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
697143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
698143611Sphilip{
699143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
700143611Sphilip	struct pft_entry *e = NULL;
701143611Sphilip
702205312Ssyrinx	if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
703205312Ssyrinx		pft_refresh();
704205312Ssyrinx
705143611Sphilip	switch (op) {
706143611Sphilip		case SNMP_OP_SET:
707143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
708143611Sphilip		case SNMP_OP_GETNEXT:
709143611Sphilip			if ((e = NEXT_OBJECT_INT(&pft_table,
710143611Sphilip			    &val->var, sub)) == NULL)
711143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
712143611Sphilip			val->var.len = sub + 1;
713143611Sphilip			val->var.subs[sub] = e->index;
714143611Sphilip			break;
715143611Sphilip		case SNMP_OP_GET:
716143611Sphilip			if (val->var.len - sub != 1)
717143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
718143611Sphilip			if ((e = pft_table_find(val->var.subs[sub])) == NULL)
719143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
720143611Sphilip			break;
721143611Sphilip
722143611Sphilip		case SNMP_OP_COMMIT:
723143611Sphilip		case SNMP_OP_ROLLBACK:
724143611Sphilip		default:
725143611Sphilip			abort();
726143611Sphilip	}
727143611Sphilip
728143611Sphilip	switch (which) {
729143611Sphilip		case LEAF_pfTablesTblDescr:
730143611Sphilip			return (string_get(val, e->pft.pfrts_name, -1));
731143611Sphilip		case LEAF_pfTablesTblCount:
732143611Sphilip			val->v.integer = e->pft.pfrts_cnt;
733143611Sphilip			break;
734143611Sphilip		case LEAF_pfTablesTblTZero:
735143611Sphilip			val->v.uint32 =
736143611Sphilip			    (time(NULL) - e->pft.pfrts_tzero) * 100;
737143611Sphilip			break;
738143611Sphilip		case LEAF_pfTablesTblRefsAnchor:
739143611Sphilip			val->v.integer =
740143611Sphilip			    e->pft.pfrts_refcnt[PFR_REFCNT_ANCHOR];
741143611Sphilip			break;
742143611Sphilip		case LEAF_pfTablesTblRefsRule:
743143611Sphilip			val->v.integer =
744143611Sphilip			    e->pft.pfrts_refcnt[PFR_REFCNT_RULE];
745143611Sphilip			break;
746143611Sphilip		case LEAF_pfTablesTblEvalMatch:
747143611Sphilip			val->v.counter64 = e->pft.pfrts_match;
748143611Sphilip			break;
749143611Sphilip		case LEAF_pfTablesTblEvalNoMatch:
750143611Sphilip			val->v.counter64 = e->pft.pfrts_nomatch;
751143611Sphilip			break;
752143611Sphilip		case LEAF_pfTablesTblBytesInPass:
753143611Sphilip			val->v.counter64 =
754143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_PASS];
755143611Sphilip			break;
756143611Sphilip		case LEAF_pfTablesTblBytesInBlock:
757143611Sphilip			val->v.counter64 =
758143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_BLOCK];
759143611Sphilip			break;
760143611Sphilip		case LEAF_pfTablesTblBytesInXPass:
761143611Sphilip			val->v.counter64 =
762143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_XPASS];
763143611Sphilip			break;
764143611Sphilip		case LEAF_pfTablesTblBytesOutPass:
765143611Sphilip			val->v.counter64 =
766143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_PASS];
767143611Sphilip			break;
768143611Sphilip		case LEAF_pfTablesTblBytesOutBlock:
769143611Sphilip			val->v.counter64 =
770143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_BLOCK];
771143611Sphilip			break;
772143611Sphilip		case LEAF_pfTablesTblBytesOutXPass:
773143611Sphilip			val->v.counter64 =
774143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_XPASS];
775143611Sphilip			break;
776143611Sphilip		case LEAF_pfTablesTblPktsInPass:
777143611Sphilip			val->v.counter64 =
778143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_PASS];
779143611Sphilip			break;
780143611Sphilip		case LEAF_pfTablesTblPktsInBlock:
781143611Sphilip			val->v.counter64 =
782143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_BLOCK];
783143611Sphilip			break;
784143611Sphilip		case LEAF_pfTablesTblPktsInXPass:
785143611Sphilip			val->v.counter64 =
786143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_XPASS];
787143611Sphilip			break;
788143611Sphilip		case LEAF_pfTablesTblPktsOutPass:
789143611Sphilip			val->v.counter64 =
790143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_PASS];
791143611Sphilip			break;
792143611Sphilip		case LEAF_pfTablesTblPktsOutBlock:
793143611Sphilip			val->v.counter64 =
794143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_BLOCK];
795143611Sphilip			break;
796143611Sphilip		case LEAF_pfTablesTblPktsOutXPass:
797143611Sphilip			val->v.counter64 =
798143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_XPASS];
799143611Sphilip			break;
800143611Sphilip
801143611Sphilip		default:
802143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
803143611Sphilip	}
804143611Sphilip
805143611Sphilip	return (SNMP_ERR_NOERROR);
806143611Sphilip}
807143611Sphilip
808143611Sphilipint
809143611Sphilippf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val,
810143611Sphilip	u_int __unused sub, u_int __unused vindex, enum snmp_op __unused op)
811143611Sphilip{
812205607Ssyrinx	asn_subid_t	which = val->var.subs[sub - 1];
813205607Ssyrinx	struct pfa_entry *e = NULL;
814205607Ssyrinx
815205607Ssyrinx	if ((time(NULL) - pfa_table_age) > PFA_TABLE_MAXAGE)
816205607Ssyrinx		pfa_refresh();
817205607Ssyrinx
818205607Ssyrinx	switch (op) {
819205607Ssyrinx		case SNMP_OP_SET:
820205607Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
821205607Ssyrinx		case SNMP_OP_GETNEXT:
822205607Ssyrinx			if ((e = NEXT_OBJECT_INT(&pfa_table,
823205607Ssyrinx			    &val->var, sub)) == NULL)
824205607Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
825205607Ssyrinx			val->var.len = sub + 1;
826205607Ssyrinx			val->var.subs[sub] = e->index;
827205607Ssyrinx			break;
828205607Ssyrinx		case SNMP_OP_GET:
829205607Ssyrinx			if (val->var.len - sub != 1)
830205607Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
831205607Ssyrinx			if ((e = pfa_table_find(val->var.subs[sub])) == NULL)
832205607Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
833205607Ssyrinx			break;
834205607Ssyrinx
835205607Ssyrinx		case SNMP_OP_COMMIT:
836205607Ssyrinx		case SNMP_OP_ROLLBACK:
837205607Ssyrinx		default:
838205607Ssyrinx			abort();
839205607Ssyrinx	}
840205607Ssyrinx
841205607Ssyrinx	switch (which) {
842205607Ssyrinx		case LEAF_pfTablesAddrNetType:
843205607Ssyrinx			if (e->pfas.pfras_a.pfra_af == AF_INET)
844205607Ssyrinx				val->v.integer = pfTablesAddrNetType_ipv4;
845205607Ssyrinx			else if (e->pfas.pfras_a.pfra_af == AF_INET6)
846205607Ssyrinx				val->v.integer = pfTablesAddrNetType_ipv6;
847205607Ssyrinx			else
848205607Ssyrinx				return (SNMP_ERR_GENERR);
849205607Ssyrinx			break;
850205607Ssyrinx		case LEAF_pfTablesAddrNet:
851205607Ssyrinx			if (e->pfas.pfras_a.pfra_af == AF_INET) {
852205607Ssyrinx				return (string_get(val,
853205607Ssyrinx				    (u_char *)&e->pfas.pfras_a.pfra_ip4addr, 4));
854205607Ssyrinx			} else if (e->pfas.pfras_a.pfra_af == AF_INET6)
855205607Ssyrinx				return (string_get(val,
856205607Ssyrinx				    (u_char *)&e->pfas.pfras_a.pfra_ip6addr, 16));
857205607Ssyrinx			else
858205607Ssyrinx				return (SNMP_ERR_GENERR);
859205607Ssyrinx			break;
860205607Ssyrinx		case LEAF_pfTablesAddrPrefix:
861205607Ssyrinx			val->v.integer = (int32_t) e->pfas.pfras_a.pfra_net;
862205607Ssyrinx			break;
863205607Ssyrinx		case LEAF_pfTablesAddrTZero:
864205607Ssyrinx			val->v.uint32 =
865205607Ssyrinx			    (time(NULL) - e->pfas.pfras_tzero) * 100;
866205607Ssyrinx			break;
867205607Ssyrinx		case LEAF_pfTablesAddrBytesInPass:
868205607Ssyrinx			val->v.counter64 =
869205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_IN][PFR_OP_PASS];
870205607Ssyrinx			break;
871205607Ssyrinx		case LEAF_pfTablesAddrBytesInBlock:
872205607Ssyrinx			val->v.counter64 =
873205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_IN][PFR_OP_BLOCK];
874205607Ssyrinx			break;
875205607Ssyrinx		case LEAF_pfTablesAddrBytesOutPass:
876205607Ssyrinx			val->v.counter64 =
877205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_OUT][PFR_OP_PASS];
878205607Ssyrinx			break;
879205607Ssyrinx		case LEAF_pfTablesAddrBytesOutBlock:
880205607Ssyrinx			val->v.counter64 =
881205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_OUT][PFR_OP_BLOCK];
882205607Ssyrinx			break;
883205607Ssyrinx		case LEAF_pfTablesAddrPktsInPass:
884205607Ssyrinx			val->v.counter64 =
885205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_IN][PFR_OP_PASS];
886205607Ssyrinx			break;
887205607Ssyrinx		case LEAF_pfTablesAddrPktsInBlock:
888205607Ssyrinx			val->v.counter64 =
889205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_IN][PFR_OP_BLOCK];
890205607Ssyrinx			break;
891205607Ssyrinx		case LEAF_pfTablesAddrPktsOutPass:
892205607Ssyrinx			val->v.counter64 =
893205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_OUT][PFR_OP_PASS];
894205607Ssyrinx			break;
895205607Ssyrinx		case LEAF_pfTablesAddrPktsOutBlock:
896205607Ssyrinx			val->v.counter64 =
897205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_OUT][PFR_OP_BLOCK];
898205607Ssyrinx			break;
899205607Ssyrinx		default:
900205607Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
901205607Ssyrinx	}
902205607Ssyrinx
903205607Ssyrinx	return (SNMP_ERR_NOERROR);
904143611Sphilip}
905143611Sphilip
906143611Sphilipint
907143611Sphilippf_altq(struct snmp_context __unused *ctx, struct snmp_value *val,
908143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
909143611Sphilip{
910143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
911143611Sphilip
912205607Ssyrinx	if (!altq_enabled)
913205607Ssyrinx	   return (SNMP_ERR_NOSUCHNAME);
914152970Sphilip
915143611Sphilip	if (op == SNMP_OP_SET)
916143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
917143611Sphilip
918143611Sphilip	if (op == SNMP_OP_GET) {
919143611Sphilip		if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
920143611Sphilip			if (pfq_refresh() == -1)
921143611Sphilip			    return (SNMP_ERR_GENERR);
922143611Sphilip
923143611Sphilip		switch (which) {
924143611Sphilip			case LEAF_pfAltqQueueNumber:
925143611Sphilip				val->v.uint32 = pfq_table_count;
926143611Sphilip				break;
927143611Sphilip
928143611Sphilip			default:
929143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
930143611Sphilip		}
931143611Sphilip
932143611Sphilip		return (SNMP_ERR_NOERROR);
933143611Sphilip	}
934143611Sphilip
935143611Sphilip	abort();
936143611Sphilip	return (SNMP_ERR_GENERR);
937310901Sngie}
938143611Sphilip
939143611Sphilipint
940143611Sphilippf_altqq(struct snmp_context __unused *ctx, struct snmp_value *val,
941143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
942143611Sphilip{
943143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
944143611Sphilip	struct pfq_entry *e = NULL;
945143611Sphilip
946205607Ssyrinx	if (!altq_enabled)
947205607Ssyrinx	   return (SNMP_ERR_NOSUCHNAME);
948152970Sphilip
949205312Ssyrinx	if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
950205312Ssyrinx		pfq_refresh();
951205312Ssyrinx
952143611Sphilip	switch (op) {
953143611Sphilip		case SNMP_OP_SET:
954143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
955143611Sphilip		case SNMP_OP_GETNEXT:
956143611Sphilip			if ((e = NEXT_OBJECT_INT(&pfq_table,
957143611Sphilip			    &val->var, sub)) == NULL)
958143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
959143611Sphilip			val->var.len = sub + 1;
960143611Sphilip			val->var.subs[sub] = e->index;
961143611Sphilip			break;
962143611Sphilip		case SNMP_OP_GET:
963143611Sphilip			if (val->var.len - sub != 1)
964143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
965143611Sphilip			if ((e = pfq_table_find(val->var.subs[sub])) == NULL)
966143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
967143611Sphilip			break;
968143611Sphilip
969143611Sphilip		case SNMP_OP_COMMIT:
970143611Sphilip		case SNMP_OP_ROLLBACK:
971143611Sphilip		default:
972143611Sphilip			abort();
973143611Sphilip	}
974143611Sphilip
975143611Sphilip	switch (which) {
976143611Sphilip		case LEAF_pfAltqQueueDescr:
977143611Sphilip			return (string_get(val, e->altq.qname, -1));
978143611Sphilip		case LEAF_pfAltqQueueParent:
979143611Sphilip			return (string_get(val, e->altq.parent, -1));
980143611Sphilip		case LEAF_pfAltqQueueScheduler:
981143611Sphilip			val->v.integer = e->altq.scheduler;
982143611Sphilip			break;
983143611Sphilip		case LEAF_pfAltqQueueBandwidth:
984143611Sphilip			val->v.uint32 = e->altq.bandwidth;
985143611Sphilip			break;
986143611Sphilip		case LEAF_pfAltqQueuePriority:
987143611Sphilip			val->v.integer = e->altq.priority;
988143611Sphilip			break;
989143611Sphilip		case LEAF_pfAltqQueueLimit:
990143611Sphilip			val->v.integer = e->altq.qlimit;
991143611Sphilip			break;
992310901Sngie
993143611Sphilip		default:
994143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
995143611Sphilip	}
996143611Sphilip
997143611Sphilip	return (SNMP_ERR_NOERROR);
998205280Ssyrinx}
999143611Sphilip
1000205280Ssyrinxint
1001205280Ssyrinxpf_labels(struct snmp_context __unused *ctx, struct snmp_value *val,
1002205280Ssyrinx	u_int sub, u_int __unused vindex, enum snmp_op op)
1003205280Ssyrinx{
1004205280Ssyrinx	asn_subid_t	which = val->var.subs[sub - 1];
1005205280Ssyrinx
1006205280Ssyrinx	if (op == SNMP_OP_SET)
1007205280Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
1008205280Ssyrinx
1009205280Ssyrinx	if (op == SNMP_OP_GET) {
1010205280Ssyrinx		if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
1011205280Ssyrinx			if (pfl_refresh() == -1)
1012205280Ssyrinx				return (SNMP_ERR_GENERR);
1013205280Ssyrinx
1014205280Ssyrinx		switch (which) {
1015205280Ssyrinx			case LEAF_pfLabelsLblNumber:
1016205280Ssyrinx				val->v.uint32 = pfl_table_count;
1017205280Ssyrinx				break;
1018205280Ssyrinx
1019205280Ssyrinx			default:
1020205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1021205280Ssyrinx		}
1022205280Ssyrinx
1023205280Ssyrinx		return (SNMP_ERR_NOERROR);
1024205280Ssyrinx	}
1025205280Ssyrinx
1026205280Ssyrinx	abort();
1027205280Ssyrinx	return (SNMP_ERR_GENERR);
1028205280Ssyrinx}
1029205280Ssyrinx
1030205280Ssyrinxint
1031205280Ssyrinxpf_lbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
1032205280Ssyrinx	u_int sub, u_int __unused vindex, enum snmp_op op)
1033205280Ssyrinx{
1034205280Ssyrinx	asn_subid_t	which = val->var.subs[sub - 1];
1035205280Ssyrinx	struct pfl_entry *e = NULL;
1036205280Ssyrinx
1037205312Ssyrinx	if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
1038205312Ssyrinx		pfl_refresh();
1039205312Ssyrinx
1040205280Ssyrinx	switch (op) {
1041205280Ssyrinx		case SNMP_OP_SET:
1042205280Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
1043205280Ssyrinx		case SNMP_OP_GETNEXT:
1044205280Ssyrinx			if ((e = NEXT_OBJECT_INT(&pfl_table,
1045205280Ssyrinx			    &val->var, sub)) == NULL)
1046205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1047205280Ssyrinx			val->var.len = sub + 1;
1048205280Ssyrinx			val->var.subs[sub] = e->index;
1049205280Ssyrinx			break;
1050205280Ssyrinx		case SNMP_OP_GET:
1051205280Ssyrinx			if (val->var.len - sub != 1)
1052205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1053205280Ssyrinx			if ((e = pfl_table_find(val->var.subs[sub])) == NULL)
1054205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1055205280Ssyrinx			break;
1056205280Ssyrinx
1057205280Ssyrinx		case SNMP_OP_COMMIT:
1058205280Ssyrinx		case SNMP_OP_ROLLBACK:
1059205280Ssyrinx		default:
1060205280Ssyrinx			abort();
1061205280Ssyrinx	}
1062205280Ssyrinx
1063205280Ssyrinx	switch (which) {
1064205280Ssyrinx		case LEAF_pfLabelsLblName:
1065205280Ssyrinx			return (string_get(val, e->name, -1));
1066205280Ssyrinx		case LEAF_pfLabelsLblEvals:
1067205280Ssyrinx			val->v.counter64 = e->evals;
1068205280Ssyrinx			break;
1069205280Ssyrinx		case LEAF_pfLabelsLblBytesIn:
1070205280Ssyrinx			val->v.counter64 = e->bytes[IN];
1071205280Ssyrinx			break;
1072205280Ssyrinx		case LEAF_pfLabelsLblBytesOut:
1073205280Ssyrinx			val->v.counter64 = e->bytes[OUT];
1074205280Ssyrinx			break;
1075205280Ssyrinx		case LEAF_pfLabelsLblPktsIn:
1076205280Ssyrinx			val->v.counter64 = e->pkts[IN];
1077205280Ssyrinx			break;
1078205280Ssyrinx		case LEAF_pfLabelsLblPktsOut:
1079205280Ssyrinx			val->v.counter64 = e->pkts[OUT];
1080205280Ssyrinx			break;
1081205280Ssyrinx		default:
1082205280Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1083205280Ssyrinx	}
1084205280Ssyrinx
1085205280Ssyrinx	return (SNMP_ERR_NOERROR);
1086205280Ssyrinx}
1087205280Ssyrinx
1088143611Sphilipstatic struct pfi_entry *
1089143611Sphilippfi_table_find(u_int idx)
1090143611Sphilip{
1091143611Sphilip	struct pfi_entry *e;
1092143611Sphilip
1093143611Sphilip	TAILQ_FOREACH(e, &pfi_table, link)
1094143611Sphilip		if (e->index == idx)
1095143611Sphilip			return (e);
1096143611Sphilip	return (NULL);
1097143611Sphilip}
1098143611Sphilip
1099143611Sphilipstatic struct pfq_entry *
1100143611Sphilippfq_table_find(u_int idx)
1101143611Sphilip{
1102143611Sphilip	struct pfq_entry *e;
1103205280Ssyrinx
1104143611Sphilip	TAILQ_FOREACH(e, &pfq_table, link)
1105143611Sphilip		if (e->index == idx)
1106143611Sphilip			return (e);
1107143611Sphilip	return (NULL);
1108143611Sphilip}
1109143611Sphilip
1110143611Sphilipstatic struct pft_entry *
1111143611Sphilippft_table_find(u_int idx)
1112143611Sphilip{
1113143611Sphilip	struct pft_entry *e;
1114143611Sphilip
1115143611Sphilip	TAILQ_FOREACH(e, &pft_table, link)
1116143611Sphilip		if (e->index == idx)
1117143611Sphilip			return (e);
1118143611Sphilip	return (NULL);
1119143611Sphilip}
1120143611Sphilip
1121205607Ssyrinxstatic struct pfa_entry *
1122205607Ssyrinxpfa_table_find(u_int idx)
1123205607Ssyrinx{
1124205607Ssyrinx	struct pfa_entry *e;
1125205607Ssyrinx
1126205607Ssyrinx	TAILQ_FOREACH(e, &pfa_table, link)
1127205607Ssyrinx		if (e->index == idx)
1128205607Ssyrinx			return (e);
1129205607Ssyrinx	return (NULL);
1130205607Ssyrinx}
1131205607Ssyrinx
1132205280Ssyrinxstatic struct pfl_entry *
1133205280Ssyrinxpfl_table_find(u_int idx)
1134205280Ssyrinx{
1135205280Ssyrinx	struct pfl_entry *e;
1136205280Ssyrinx
1137205280Ssyrinx	TAILQ_FOREACH(e, &pfl_table, link)
1138205280Ssyrinx		if (e->index == idx)
1139205280Ssyrinx			return (e);
1140205280Ssyrinx
1141205280Ssyrinx	return (NULL);
1142205280Ssyrinx}
1143205280Ssyrinx
1144143611Sphilipstatic int
1145143611Sphilippfi_refresh(void)
1146143611Sphilip{
1147143611Sphilip	struct pfioc_iface io;
1148171173Smlaier	struct pfi_kif *p = NULL;
1149143611Sphilip	struct pfi_entry *e;
1150143611Sphilip	int i, numifs = 1;
1151143611Sphilip
1152143611Sphilip	if (started && this_tick <= pf_tick)
1153143611Sphilip		return (0);
1154143611Sphilip
1155143611Sphilip	while (!TAILQ_EMPTY(&pfi_table)) {
1156143611Sphilip		e = TAILQ_FIRST(&pfi_table);
1157143611Sphilip		TAILQ_REMOVE(&pfi_table, e, link);
1158143611Sphilip		free(e);
1159143611Sphilip	}
1160143611Sphilip
1161143611Sphilip	bzero(&io, sizeof(io));
1162171173Smlaier	io.pfiio_esize = sizeof(struct pfi_kif);
1163143611Sphilip
1164143611Sphilip	for (;;) {
1165171173Smlaier		p = reallocf(p, numifs * sizeof(struct pfi_kif));
1166149571Sphilip		if (p == NULL) {
1167149571Sphilip			syslog(LOG_ERR, "pfi_refresh(): reallocf() numifs=%d: %s",
1168149571Sphilip			    numifs, strerror(errno));
1169149571Sphilip			goto err2;
1170149571Sphilip		}
1171143611Sphilip		io.pfiio_size = numifs;
1172143611Sphilip		io.pfiio_buffer = p;
1173143611Sphilip
1174143611Sphilip		if (ioctl(dev, DIOCIGETIFACES, &io)) {
1175143611Sphilip			syslog(LOG_ERR, "pfi_refresh(): ioctl(): %s",
1176143611Sphilip			    strerror(errno));
1177149571Sphilip			goto err2;
1178143611Sphilip		}
1179143611Sphilip
1180143611Sphilip		if (numifs >= io.pfiio_size)
1181143611Sphilip			break;
1182143611Sphilip
1183143611Sphilip		numifs = io.pfiio_size;
1184143611Sphilip	}
1185143611Sphilip
1186143611Sphilip	for (i = 0; i < numifs; i++) {
1187143611Sphilip		e = malloc(sizeof(struct pfi_entry));
1188149571Sphilip		if (e == NULL)
1189149571Sphilip			goto err1;
1190143611Sphilip		e->index = i + 1;
1191171173Smlaier		memcpy(&e->pfi, p+i, sizeof(struct pfi_kif));
1192143611Sphilip		TAILQ_INSERT_TAIL(&pfi_table, e, link);
1193143611Sphilip	}
1194143611Sphilip
1195143611Sphilip	pfi_table_age = time(NULL);
1196143611Sphilip	pfi_table_count = numifs;
1197143611Sphilip	pf_tick = this_tick;
1198143611Sphilip
1199143611Sphilip	free(p);
1200143611Sphilip	return (0);
1201149571Sphilip
1202149571Sphiliperr1:
1203149571Sphilip	while (!TAILQ_EMPTY(&pfi_table)) {
1204149571Sphilip		e = TAILQ_FIRST(&pfi_table);
1205149571Sphilip		TAILQ_REMOVE(&pfi_table, e, link);
1206149571Sphilip		free(e);
1207149571Sphilip	}
1208149571Sphiliperr2:
1209149571Sphilip	free(p);
1210149571Sphilip	return(-1);
1211143611Sphilip}
1212143611Sphilip
1213143611Sphilipstatic int
1214143611Sphilippfq_refresh(void)
1215143611Sphilip{
1216143611Sphilip	struct pfioc_altq pa;
1217143611Sphilip	struct pfq_entry *e;
1218143611Sphilip	int i, numqs, ticket;
1219143611Sphilip
1220143611Sphilip	if (started && this_tick <= pf_tick)
1221143611Sphilip		return (0);
1222143611Sphilip
1223143611Sphilip	while (!TAILQ_EMPTY(&pfq_table)) {
1224143611Sphilip		e = TAILQ_FIRST(&pfq_table);
1225143611Sphilip		TAILQ_REMOVE(&pfq_table, e, link);
1226143611Sphilip		free(e);
1227143611Sphilip	}
1228143611Sphilip
1229143611Sphilip	bzero(&pa, sizeof(pa));
1230310901Sngie
1231143611Sphilip	if (ioctl(dev, DIOCGETALTQS, &pa)) {
1232143611Sphilip		syslog(LOG_ERR, "pfq_refresh: ioctl(DIOCGETALTQS): %s",
1233143611Sphilip		    strerror(errno));
1234143611Sphilip		return (-1);
1235143611Sphilip	}
1236143611Sphilip
1237143611Sphilip	numqs = pa.nr;
1238143611Sphilip	ticket = pa.ticket;
1239143611Sphilip
1240143611Sphilip	for (i = 0; i < numqs; i++) {
1241143611Sphilip		e = malloc(sizeof(struct pfq_entry));
1242149571Sphilip		if (e == NULL) {
1243149571Sphilip			syslog(LOG_ERR, "pfq_refresh(): "
1244149571Sphilip			    "malloc(): %s",
1245149571Sphilip			    strerror(errno));
1246149571Sphilip			goto err;
1247149571Sphilip		}
1248143611Sphilip		pa.ticket = ticket;
1249143611Sphilip		pa.nr = i;
1250143611Sphilip
1251143611Sphilip		if (ioctl(dev, DIOCGETALTQ, &pa)) {
1252143611Sphilip			syslog(LOG_ERR, "pfq_refresh(): "
1253143611Sphilip			    "ioctl(DIOCGETALTQ): %s",
1254143611Sphilip			    strerror(errno));
1255149571Sphilip			goto err;
1256143611Sphilip		}
1257143611Sphilip
1258143611Sphilip		if (pa.altq.qid > 0) {
1259143611Sphilip			memcpy(&e->altq, &pa.altq, sizeof(struct pf_altq));
1260143611Sphilip			e->index = pa.altq.qid;
1261143611Sphilip			pfq_table_count = i;
1262179476Sphilip			INSERT_OBJECT_INT_LINK_INDEX(e, &pfq_table, link, index);
1263143611Sphilip		}
1264143611Sphilip	}
1265310901Sngie
1266143611Sphilip	pfq_table_age = time(NULL);
1267143611Sphilip	pf_tick = this_tick;
1268143611Sphilip
1269143611Sphilip	return (0);
1270149571Sphiliperr:
1271149571Sphilip	free(e);
1272149571Sphilip	while (!TAILQ_EMPTY(&pfq_table)) {
1273149571Sphilip		e = TAILQ_FIRST(&pfq_table);
1274149571Sphilip		TAILQ_REMOVE(&pfq_table, e, link);
1275149571Sphilip		free(e);
1276149571Sphilip	}
1277149571Sphilip	return(-1);
1278143611Sphilip}
1279143611Sphilip
1280143611Sphilipstatic int
1281143611Sphilippfs_refresh(void)
1282143611Sphilip{
1283143611Sphilip	if (started && this_tick <= pf_tick)
1284143611Sphilip		return (0);
1285143611Sphilip
1286143611Sphilip	bzero(&pfs, sizeof(struct pf_status));
1287143611Sphilip
1288143611Sphilip	if (ioctl(dev, DIOCGETSTATUS, &pfs)) {
1289143611Sphilip		syslog(LOG_ERR, "pfs_refresh(): ioctl(): %s",
1290143611Sphilip		    strerror(errno));
1291143611Sphilip		return (-1);
1292143611Sphilip	}
1293143611Sphilip
1294143611Sphilip	pf_tick = this_tick;
1295143611Sphilip	return (0);
1296143611Sphilip}
1297143611Sphilip
1298143611Sphilipstatic int
1299143611Sphilippft_refresh(void)
1300143611Sphilip{
1301143611Sphilip	struct pfioc_table io;
1302149571Sphilip	struct pfr_tstats *t = NULL;
1303143611Sphilip	struct pft_entry *e;
1304143611Sphilip	int i, numtbls = 1;
1305143611Sphilip
1306143611Sphilip	if (started && this_tick <= pf_tick)
1307143611Sphilip		return (0);
1308143611Sphilip
1309143611Sphilip	while (!TAILQ_EMPTY(&pft_table)) {
1310143611Sphilip		e = TAILQ_FIRST(&pft_table);
1311143611Sphilip		TAILQ_REMOVE(&pft_table, e, link);
1312143611Sphilip		free(e);
1313143611Sphilip	}
1314143611Sphilip
1315143611Sphilip	bzero(&io, sizeof(io));
1316143611Sphilip	io.pfrio_esize = sizeof(struct pfr_tstats);
1317143611Sphilip
1318143611Sphilip	for (;;) {
1319149571Sphilip		t = reallocf(t, numtbls * sizeof(struct pfr_tstats));
1320149571Sphilip		if (t == NULL) {
1321149571Sphilip			syslog(LOG_ERR, "pft_refresh(): reallocf() numtbls=%d: %s",
1322149571Sphilip			    numtbls, strerror(errno));
1323149571Sphilip			goto err2;
1324149571Sphilip		}
1325143611Sphilip		io.pfrio_size = numtbls;
1326143611Sphilip		io.pfrio_buffer = t;
1327143611Sphilip
1328143611Sphilip		if (ioctl(dev, DIOCRGETTSTATS, &io)) {
1329143611Sphilip			syslog(LOG_ERR, "pft_refresh(): ioctl(): %s",
1330143611Sphilip			    strerror(errno));
1331149571Sphilip			goto err2;
1332143611Sphilip		}
1333143611Sphilip
1334143611Sphilip		if (numtbls >= io.pfrio_size)
1335143611Sphilip			break;
1336143611Sphilip
1337143611Sphilip		numtbls = io.pfrio_size;
1338143611Sphilip	}
1339143611Sphilip
1340143611Sphilip	for (i = 0; i < numtbls; i++) {
1341200122Ssyrinx		e = malloc(sizeof(struct pft_entry));
1342149571Sphilip		if (e == NULL)
1343149571Sphilip			goto err1;
1344143611Sphilip		e->index = i + 1;
1345143611Sphilip		memcpy(&e->pft, t+i, sizeof(struct pfr_tstats));
1346143611Sphilip		TAILQ_INSERT_TAIL(&pft_table, e, link);
1347143611Sphilip	}
1348143611Sphilip
1349143611Sphilip	pft_table_age = time(NULL);
1350143611Sphilip	pft_table_count = numtbls;
1351143611Sphilip	pf_tick = this_tick;
1352143611Sphilip
1353143611Sphilip	free(t);
1354143611Sphilip	return (0);
1355149571Sphiliperr1:
1356149571Sphilip	while (!TAILQ_EMPTY(&pft_table)) {
1357149571Sphilip		e = TAILQ_FIRST(&pft_table);
1358149571Sphilip		TAILQ_REMOVE(&pft_table, e, link);
1359149571Sphilip		free(e);
1360149571Sphilip	}
1361149571Sphiliperr2:
1362149571Sphilip	free(t);
1363149571Sphilip	return(-1);
1364143611Sphilip}
1365143611Sphilip
1366205280Ssyrinxstatic int
1367205607Ssyrinxpfa_table_addrs(u_int sidx, struct pfr_table *pt)
1368205607Ssyrinx{
1369205607Ssyrinx	struct pfioc_table io;
1370205607Ssyrinx	struct pfr_astats *t = NULL;
1371205607Ssyrinx	struct pfa_entry *e;
1372205607Ssyrinx	int i, numaddrs = 1;
1373205607Ssyrinx
1374205607Ssyrinx	if (pt == NULL)
1375205607Ssyrinx		return (-1);
1376205607Ssyrinx
1377205607Ssyrinx	memset(&io, 0, sizeof(io));
1378205607Ssyrinx	strlcpy(io.pfrio_table.pfrt_name, pt->pfrt_name,
1379205607Ssyrinx	    sizeof(io.pfrio_table.pfrt_name));
1380205607Ssyrinx
1381205607Ssyrinx	for (;;) {
1382205607Ssyrinx		t = reallocf(t, numaddrs * sizeof(struct pfr_astats));
1383205607Ssyrinx		if (t == NULL) {
1384205607Ssyrinx			syslog(LOG_ERR, "pfa_table_addrs(): reallocf(): %s",
1385205607Ssyrinx			    strerror(errno));
1386205607Ssyrinx			numaddrs = -1;
1387205607Ssyrinx			goto error;
1388205607Ssyrinx		}
1389205607Ssyrinx
1390205607Ssyrinx		memset(t, 0, sizeof(*t));
1391205607Ssyrinx		io.pfrio_size = numaddrs;
1392205607Ssyrinx		io.pfrio_buffer = t;
1393205607Ssyrinx		io.pfrio_esize = sizeof(struct pfr_astats);
1394205607Ssyrinx
1395205607Ssyrinx		if (ioctl(dev, DIOCRGETASTATS, &io)) {
1396205607Ssyrinx			syslog(LOG_ERR, "pfa_table_addrs(): ioctl() on %s: %s",
1397205607Ssyrinx			    pt->pfrt_name, strerror(errno));
1398205607Ssyrinx			numaddrs = -1;
1399205607Ssyrinx			break;
1400205607Ssyrinx		}
1401205607Ssyrinx
1402205607Ssyrinx		if (numaddrs >= io.pfrio_size)
1403205607Ssyrinx			break;
1404205607Ssyrinx
1405205607Ssyrinx		numaddrs = io.pfrio_size;
1406205607Ssyrinx	}
1407205607Ssyrinx
1408205607Ssyrinx	for (i = 0; i < numaddrs; i++) {
1409205607Ssyrinx		if ((t + i)->pfras_a.pfra_af != AF_INET &&
1410205607Ssyrinx		    (t + i)->pfras_a.pfra_af != AF_INET6) {
1411205607Ssyrinx			numaddrs = i;
1412205607Ssyrinx			break;
1413205607Ssyrinx		}
1414205607Ssyrinx
1415205607Ssyrinx		e = (struct pfa_entry *)malloc(sizeof(struct pfa_entry));
1416205607Ssyrinx		if (e == NULL) {
1417205607Ssyrinx			syslog(LOG_ERR, "pfa_table_addrs(): malloc(): %s",
1418205607Ssyrinx			    strerror(errno));
1419205607Ssyrinx			numaddrs = -1;
1420205607Ssyrinx			break;
1421205607Ssyrinx		}
1422205607Ssyrinx		e->index = sidx + i;
1423205607Ssyrinx		memcpy(&e->pfas, t + i, sizeof(struct pfr_astats));
1424205607Ssyrinx		TAILQ_INSERT_TAIL(&pfa_table, e, link);
1425205607Ssyrinx	}
1426205607Ssyrinx
1427205607Ssyrinx	free(t);
1428205607Ssyrinxerror:
1429205607Ssyrinx	return (numaddrs);
1430205607Ssyrinx}
1431205607Ssyrinx
1432205607Ssyrinxstatic int
1433205607Ssyrinxpfa_refresh(void)
1434205607Ssyrinx{
1435205607Ssyrinx	struct pfioc_table io;
1436205607Ssyrinx	struct pfr_table *pt = NULL, *it = NULL;
1437205607Ssyrinx	struct pfa_entry *e;
1438205607Ssyrinx	int i, numtbls = 1, cidx, naddrs;
1439205607Ssyrinx
1440205607Ssyrinx	if (started && this_tick <= pf_tick)
1441205607Ssyrinx		return (0);
1442205607Ssyrinx
1443205607Ssyrinx	while (!TAILQ_EMPTY(&pfa_table)) {
1444205607Ssyrinx		e = TAILQ_FIRST(&pfa_table);
1445205607Ssyrinx		TAILQ_REMOVE(&pfa_table, e, link);
1446205607Ssyrinx		free(e);
1447205607Ssyrinx	}
1448205607Ssyrinx
1449205607Ssyrinx	memset(&io, 0, sizeof(io));
1450205607Ssyrinx	io.pfrio_esize = sizeof(struct pfr_table);
1451205607Ssyrinx
1452205607Ssyrinx	for (;;) {
1453205607Ssyrinx		pt = reallocf(pt, numtbls * sizeof(struct pfr_table));
1454205607Ssyrinx		if (pt == NULL) {
1455205607Ssyrinx			syslog(LOG_ERR, "pfa_refresh(): reallocf() %s",
1456205607Ssyrinx			    strerror(errno));
1457205607Ssyrinx			return (-1);
1458205607Ssyrinx		}
1459205607Ssyrinx		memset(pt, 0, sizeof(*pt));
1460205607Ssyrinx		io.pfrio_size = numtbls;
1461205607Ssyrinx		io.pfrio_buffer = pt;
1462205607Ssyrinx
1463205607Ssyrinx		if (ioctl(dev, DIOCRGETTABLES, &io)) {
1464205607Ssyrinx			syslog(LOG_ERR, "pfa_refresh(): ioctl(): %s",
1465205607Ssyrinx			    strerror(errno));
1466205607Ssyrinx			goto err2;
1467205607Ssyrinx		}
1468205607Ssyrinx
1469205607Ssyrinx		if (numtbls >= io.pfrio_size)
1470205607Ssyrinx			break;
1471205607Ssyrinx
1472205607Ssyrinx		numtbls = io.pfrio_size;
1473205607Ssyrinx	}
1474205607Ssyrinx
1475205607Ssyrinx	cidx = 1;
1476205607Ssyrinx
1477205607Ssyrinx	for (it = pt, i = 0; i < numtbls; it++, i++) {
1478205607Ssyrinx		/*
1479205607Ssyrinx		 * Skip the table if not active - ioctl(DIOCRGETASTATS) will
1480205607Ssyrinx		 * return ESRCH for this entry anyway.
1481205607Ssyrinx		 */
1482205607Ssyrinx		if (!(it->pfrt_flags & PFR_TFLAG_ACTIVE))
1483205607Ssyrinx			continue;
1484205607Ssyrinx
1485205607Ssyrinx		if ((naddrs = pfa_table_addrs(cidx, it)) < 0)
1486205607Ssyrinx			goto err1;
1487205607Ssyrinx
1488205607Ssyrinx		cidx += naddrs;
1489205607Ssyrinx	}
1490205607Ssyrinx
1491205607Ssyrinx	pfa_table_age = time(NULL);
1492205607Ssyrinx	pfa_table_count = cidx;
1493205607Ssyrinx	pf_tick = this_tick;
1494205607Ssyrinx
1495205607Ssyrinx	free(pt);
1496205607Ssyrinx	return (0);
1497205607Ssyrinxerr1:
1498205607Ssyrinx	while (!TAILQ_EMPTY(&pfa_table)) {
1499205607Ssyrinx		e = TAILQ_FIRST(&pfa_table);
1500205607Ssyrinx		TAILQ_REMOVE(&pfa_table, e, link);
1501205607Ssyrinx		free(e);
1502205607Ssyrinx	}
1503205607Ssyrinx
1504205607Ssyrinxerr2:
1505205607Ssyrinx	free(pt);
1506205607Ssyrinx	return (-1);
1507205607Ssyrinx}
1508205607Ssyrinx
1509205607Ssyrinxstatic int
1510205280Ssyrinxpfl_scan_ruleset(const char *path)
1511205280Ssyrinx{
1512205280Ssyrinx	struct pfioc_rule pr;
1513205280Ssyrinx	struct pfl_entry *e;
1514205280Ssyrinx	u_int32_t nr, i;
1515205280Ssyrinx
1516205280Ssyrinx	bzero(&pr, sizeof(pr));
1517205280Ssyrinx	strlcpy(pr.anchor, path, sizeof(pr.anchor));
1518205280Ssyrinx	pr.rule.action = PF_PASS;
1519205280Ssyrinx	if (ioctl(dev, DIOCGETRULES, &pr)) {
1520205280Ssyrinx		syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULES): %s",
1521205280Ssyrinx		    strerror(errno));
1522205280Ssyrinx		goto err;
1523205280Ssyrinx	}
1524205280Ssyrinx
1525205280Ssyrinx	for (nr = pr.nr, i = 0; i < nr; i++) {
1526205280Ssyrinx		pr.nr = i;
1527205280Ssyrinx		if (ioctl(dev, DIOCGETRULE, &pr)) {
1528205280Ssyrinx			syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULE):"
1529205280Ssyrinx			    " %s", strerror(errno));
1530205280Ssyrinx			goto err;
1531205280Ssyrinx		}
1532205280Ssyrinx
1533205280Ssyrinx		if (pr.rule.label[0]) {
1534205280Ssyrinx			e = (struct pfl_entry *)malloc(sizeof(*e));
1535205280Ssyrinx			if (e == NULL)
1536205280Ssyrinx				goto err;
1537205280Ssyrinx
1538205280Ssyrinx			strlcpy(e->name, path, sizeof(e->name));
1539205280Ssyrinx			if (path[0])
1540205280Ssyrinx				strlcat(e->name, "/", sizeof(e->name));
1541205280Ssyrinx			strlcat(e->name, pr.rule.label, sizeof(e->name));
1542205280Ssyrinx
1543205280Ssyrinx			e->evals = pr.rule.evaluations;
1544205280Ssyrinx			e->bytes[IN] = pr.rule.bytes[IN];
1545205280Ssyrinx			e->bytes[OUT] = pr.rule.bytes[OUT];
1546205280Ssyrinx			e->pkts[IN] = pr.rule.packets[IN];
1547205280Ssyrinx			e->pkts[OUT] = pr.rule.packets[OUT];
1548205280Ssyrinx			e->index = ++pfl_table_count;
1549205280Ssyrinx
1550205280Ssyrinx			TAILQ_INSERT_TAIL(&pfl_table, e, link);
1551205280Ssyrinx		}
1552205280Ssyrinx	}
1553205280Ssyrinx
1554205280Ssyrinx	return (0);
1555205280Ssyrinx
1556205280Ssyrinxerr:
1557205280Ssyrinx	return (-1);
1558205280Ssyrinx}
1559205280Ssyrinx
1560205280Ssyrinxstatic int
1561205280Ssyrinxpfl_walk_rulesets(const char *path)
1562205280Ssyrinx{
1563205280Ssyrinx	struct pfioc_ruleset prs;
1564205280Ssyrinx	char newpath[MAXPATHLEN];
1565205280Ssyrinx	u_int32_t nr, i;
1566205280Ssyrinx
1567205280Ssyrinx	if (pfl_scan_ruleset(path))
1568205280Ssyrinx		goto err;
1569205280Ssyrinx
1570205280Ssyrinx	bzero(&prs, sizeof(prs));
1571205280Ssyrinx	strlcpy(prs.path, path, sizeof(prs.path));
1572205280Ssyrinx	if (ioctl(dev, DIOCGETRULESETS, &prs)) {
1573205280Ssyrinx		syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESETS): %s",
1574205280Ssyrinx		    strerror(errno));
1575205280Ssyrinx		goto err;
1576205280Ssyrinx	}
1577205280Ssyrinx
1578205280Ssyrinx	for (nr = prs.nr, i = 0; i < nr; i++) {
1579205280Ssyrinx		prs.nr = i;
1580205280Ssyrinx		if (ioctl(dev, DIOCGETRULESET, &prs)) {
1581205280Ssyrinx			syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESET):"
1582205280Ssyrinx			    " %s", strerror(errno));
1583205280Ssyrinx			goto err;
1584205280Ssyrinx		}
1585205280Ssyrinx
1586205280Ssyrinx		if (strcmp(prs.name, PF_RESERVED_ANCHOR) == 0)
1587205280Ssyrinx			continue;
1588205280Ssyrinx
1589205280Ssyrinx		strlcpy(newpath, path, sizeof(newpath));
1590205280Ssyrinx		if (path[0])
1591205280Ssyrinx			strlcat(newpath, "/", sizeof(newpath));
1592205280Ssyrinx
1593205280Ssyrinx		strlcat(newpath, prs.name, sizeof(newpath));
1594205280Ssyrinx		if (pfl_walk_rulesets(newpath))
1595205280Ssyrinx			goto err;
1596205280Ssyrinx	}
1597205280Ssyrinx
1598205280Ssyrinx	return (0);
1599205280Ssyrinx
1600205280Ssyrinxerr:
1601205280Ssyrinx	return (-1);
1602205280Ssyrinx}
1603205280Ssyrinx
1604205280Ssyrinxstatic int
1605205280Ssyrinxpfl_refresh(void)
1606205280Ssyrinx{
1607205280Ssyrinx	struct pfl_entry *e;
1608205280Ssyrinx
1609205280Ssyrinx	if (started && this_tick <= pf_tick)
1610205280Ssyrinx		return (0);
1611205280Ssyrinx
1612205280Ssyrinx	while (!TAILQ_EMPTY(&pfl_table)) {
1613205280Ssyrinx		e = TAILQ_FIRST(&pfl_table);
1614205280Ssyrinx		TAILQ_REMOVE(&pfl_table, e, link);
1615205280Ssyrinx		free(e);
1616205280Ssyrinx	}
1617205280Ssyrinx	pfl_table_count = 0;
1618205280Ssyrinx
1619205280Ssyrinx	if (pfl_walk_rulesets(""))
1620205280Ssyrinx		goto err;
1621205280Ssyrinx
1622205280Ssyrinx	pfl_table_age = time(NULL);
1623205280Ssyrinx	pf_tick = this_tick;
1624205280Ssyrinx
1625205280Ssyrinx	return (0);
1626205280Ssyrinx
1627205280Ssyrinxerr:
1628205280Ssyrinx	while (!TAILQ_EMPTY(&pfl_table)) {
1629205280Ssyrinx		e = TAILQ_FIRST(&pfl_table);
1630205280Ssyrinx		TAILQ_REMOVE(&pfl_table, e, link);
1631205280Ssyrinx		free(e);
1632205280Ssyrinx	}
1633205280Ssyrinx	pfl_table_count = 0;
1634205280Ssyrinx
1635205280Ssyrinx	return (-1);
1636205280Ssyrinx}
1637205280Ssyrinx
1638143611Sphilip/*
1639152970Sphilip * check whether altq support is enabled in kernel
1640152970Sphilip */
1641152970Sphilip
1642152970Sphilipstatic int
1643152970Sphilipaltq_is_enabled(int pfdev)
1644152970Sphilip{
1645310902Sngie	struct pfioc_altq pa;
1646152970Sphilip
1647152970Sphilip	errno = 0;
1648310902Sngie	if (ioctl(pfdev, DIOCGETALTQS, &pa)) {
1649310902Sngie		if (errno == ENODEV) {
1650152970Sphilip			syslog(LOG_INFO, "No ALTQ support in kernel\n"
1651152970Sphilip			    "ALTQ related functions disabled\n");
1652310902Sngie			return (0);
1653357523Sdim		} else {
1654310902Sngie			syslog(LOG_ERR, "DIOCGETALTQS returned an error: %s",
1655152970Sphilip			    strerror(errno));
1656152970Sphilip			return (-1);
1657357523Sdim		}
1658310902Sngie	}
1659310902Sngie	return (1);
1660152970Sphilip}
1661152970Sphilip
1662152970Sphilip/*
1663143611Sphilip * Implement the bsnmpd module interface
1664143611Sphilip */
1665143611Sphilipstatic int
1666143611Sphilippf_init(struct lmodule *mod, int __unused argc, char __unused *argv[])
1667143611Sphilip{
1668143611Sphilip	module = mod;
1669143611Sphilip
1670143611Sphilip	if ((dev = open("/dev/pf", O_RDONLY)) == -1) {
1671143611Sphilip		syslog(LOG_ERR, "pf_init(): open(): %s\n",
1672143611Sphilip		    strerror(errno));
1673143611Sphilip		return (-1);
1674143611Sphilip	}
1675143611Sphilip
1676152970Sphilip	if ((altq_enabled = altq_is_enabled(dev)) == -1) {
1677152970Sphilip		syslog(LOG_ERR, "pf_init(): altq test failed");
1678152970Sphilip		return (-1);
1679152970Sphilip	}
1680310901Sngie
1681143611Sphilip	/* Prepare internal state */
1682143611Sphilip	TAILQ_INIT(&pfi_table);
1683143611Sphilip	TAILQ_INIT(&pfq_table);
1684143611Sphilip	TAILQ_INIT(&pft_table);
1685205607Ssyrinx	TAILQ_INIT(&pfa_table);
1686205280Ssyrinx	TAILQ_INIT(&pfl_table);
1687143611Sphilip
1688143611Sphilip	pfi_refresh();
1689152970Sphilip	if (altq_enabled) {
1690152970Sphilip		pfq_refresh();
1691152970Sphilip	}
1692152970Sphilip
1693143611Sphilip	pfs_refresh();
1694143611Sphilip	pft_refresh();
1695205607Ssyrinx	pfa_refresh();
1696205280Ssyrinx	pfl_refresh();
1697143611Sphilip
1698143611Sphilip	started = 1;
1699143611Sphilip
1700143611Sphilip	return (0);
1701143611Sphilip}
1702143611Sphilip
1703143611Sphilipstatic int
1704143611Sphilippf_fini(void)
1705143611Sphilip{
1706143611Sphilip	struct pfi_entry *i1, *i2;
1707143611Sphilip	struct pfq_entry *q1, *q2;
1708143611Sphilip	struct pft_entry *t1, *t2;
1709205607Ssyrinx	struct pfa_entry *a1, *a2;
1710205280Ssyrinx	struct pfl_entry *l1, *l2;
1711143611Sphilip
1712143611Sphilip	/* Empty the list of interfaces */
1713143611Sphilip	i1 = TAILQ_FIRST(&pfi_table);
1714143611Sphilip	while (i1 != NULL) {
1715143611Sphilip		i2 = TAILQ_NEXT(i1, link);
1716143611Sphilip		free(i1);
1717143611Sphilip		i1 = i2;
1718143611Sphilip	}
1719143611Sphilip
1720143611Sphilip	/* List of queues */
1721143611Sphilip	q1 = TAILQ_FIRST(&pfq_table);
1722143611Sphilip	while (q1 != NULL) {
1723143611Sphilip		q2 = TAILQ_NEXT(q1, link);
1724143611Sphilip		free(q1);
1725143611Sphilip		q1 = q2;
1726143611Sphilip	}
1727143611Sphilip
1728205280Ssyrinx	/* List of tables */
1729143611Sphilip	t1 = TAILQ_FIRST(&pft_table);
1730143611Sphilip	while (t1 != NULL) {
1731143611Sphilip		t2 = TAILQ_NEXT(t1, link);
1732143611Sphilip		free(t1);
1733143611Sphilip		t1 = t2;
1734143611Sphilip	}
1735143611Sphilip
1736205607Ssyrinx	/* List of table addresses */
1737205607Ssyrinx	a1 = TAILQ_FIRST(&pfa_table);
1738205607Ssyrinx	while (a1 != NULL) {
1739205607Ssyrinx		a2 = TAILQ_NEXT(a1, link);
1740205607Ssyrinx		free(a1);
1741205607Ssyrinx		a1 = a2;
1742205607Ssyrinx	}
1743205607Ssyrinx
1744205280Ssyrinx	/* And the list of labeled filter rules */
1745205280Ssyrinx	l1 = TAILQ_FIRST(&pfl_table);
1746205280Ssyrinx	while (l1 != NULL) {
1747205280Ssyrinx		l2 = TAILQ_NEXT(l1, link);
1748205280Ssyrinx		free(l1);
1749205280Ssyrinx		l1 = l2;
1750205280Ssyrinx	}
1751205280Ssyrinx
1752143611Sphilip	close(dev);
1753143611Sphilip	return (0);
1754143611Sphilip}
1755143611Sphilip
1756143611Sphilipstatic void
1757143611Sphilippf_dump(void)
1758143611Sphilip{
1759143611Sphilip	pfi_refresh();
1760152970Sphilip	if (altq_enabled) {
1761152970Sphilip		pfq_refresh();
1762152970Sphilip	}
1763143611Sphilip	pft_refresh();
1764205607Ssyrinx	pfa_refresh();
1765205280Ssyrinx	pfl_refresh();
1766143611Sphilip
1767143654Sphilip	syslog(LOG_ERR, "Dump: pfi_table_age = %jd",
1768143654Sphilip	    (intmax_t)pfi_table_age);
1769143611Sphilip	syslog(LOG_ERR, "Dump: pfi_table_count = %d",
1770143611Sphilip	    pfi_table_count);
1771310901Sngie
1772143654Sphilip	syslog(LOG_ERR, "Dump: pfq_table_age = %jd",
1773143654Sphilip	    (intmax_t)pfq_table_age);
1774143611Sphilip	syslog(LOG_ERR, "Dump: pfq_table_count = %d",
1775143611Sphilip	    pfq_table_count);
1776143611Sphilip
1777143654Sphilip	syslog(LOG_ERR, "Dump: pft_table_age = %jd",
1778143654Sphilip	    (intmax_t)pft_table_age);
1779143611Sphilip	syslog(LOG_ERR, "Dump: pft_table_count = %d",
1780143611Sphilip	    pft_table_count);
1781205280Ssyrinx
1782205607Ssyrinx	syslog(LOG_ERR, "Dump: pfa_table_age = %jd",
1783205607Ssyrinx	    (intmax_t)pfa_table_age);
1784205607Ssyrinx	syslog(LOG_ERR, "Dump: pfa_table_count = %d",
1785205607Ssyrinx	    pfa_table_count);
1786205607Ssyrinx
1787205280Ssyrinx	syslog(LOG_ERR, "Dump: pfl_table_age = %jd",
1788205280Ssyrinx	    (intmax_t)pfl_table_age);
1789205280Ssyrinx	syslog(LOG_ERR, "Dump: pfl_table_count = %d",
1790205280Ssyrinx	    pfl_table_count);
1791143611Sphilip}
1792143611Sphilip
1793143611Sphilipconst struct snmp_module config = {
1794143611Sphilip	.comment = "This module implements a MIB for the pf packet filter.",
1795143611Sphilip	.init =		pf_init,
1796143611Sphilip	.fini =		pf_fini,
1797143611Sphilip	.tree =		pf_ctree,
1798143611Sphilip	.dump =		pf_dump,
1799143611Sphilip	.tree_size =	pf_CTREE_SIZE,
1800143611Sphilip};
1801