pf_snmp.c revision 143654
1143611Sphilip/*-
2143611Sphilip * Copyright (c) 2005 Philip Paeps <philip@FreeBSD.org>
3143611Sphilip * All rights reserved.
4143611Sphilip *
5143611Sphilip * Redistribution and use in source and binary forms, with or without
6143611Sphilip * modification, are permitted provided that the following conditions
7143611Sphilip * are met:
8143611Sphilip * 1. Redistributions of source code must retain the above copyright
9143611Sphilip *    notice, this list of conditions and the following disclaimer.
10143611Sphilip * 2. Redistributions in binary form must reproduce the above copyright
11143611Sphilip *    notice, this list of conditions and the following disclaimer in the
12143611Sphilip *    documentation and/or other materials provided with the distribution.
13143611Sphilip *
14143611Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15143611Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16143611Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17143611Sphilip * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18143611Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19143611Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20143611Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21143611Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22143611Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23143611Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24143611Sphilip * SUCH DAMAGE.
25143611Sphilip *
26143611Sphilip * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c 143654 2005-03-15 14:52:11Z philip $
27143611Sphilip */
28143611Sphilip
29143611Sphilip#include <bsnmp/snmpmod.h>
30143611Sphilip
31143611Sphilip#include <net/pfvar.h>
32143611Sphilip#include <sys/ioctl.h>
33143611Sphilip
34143611Sphilip#include <errno.h>
35143611Sphilip#include <fcntl.h>
36143626Sphilip#include <stdint.h>
37143611Sphilip#include <stdio.h>
38143611Sphilip#include <stdlib.h>
39143611Sphilip#include <string.h>
40143611Sphilip#include <syslog.h>
41143611Sphilip#include <unistd.h>
42143611Sphilip
43143611Sphilip#include "pf_oid.h"
44143611Sphilip#include "pf_tree.h"
45143611Sphilip
46143611Sphilipstruct lmodule *module;
47143611Sphilip
48143611Sphilipstatic int dev = -1;
49143611Sphilipstatic int started;
50143611Sphilipstatic uint32_t pf_tick;
51143611Sphilip
52143611Sphilipstatic struct pf_status pfs;
53143611Sphilip
54143611Sphilipenum { IN, OUT };
55143611Sphilipenum { IPV4, IPV6 };
56143611Sphilipenum { PASS, BLOCK };
57143611Sphilip
58143611Sphilip#define PFI_IFTYPE_GROUP	0
59143611Sphilip#define PFI_IFTYPE_INSTANCE	1
60143611Sphilip#define PFI_IFTYPE_DETACHED	2
61143611Sphilip
62143611Sphilipstruct pfi_entry {
63143611Sphilip	struct pfi_if	pfi;
64143611Sphilip	u_int		index;
65143611Sphilip	TAILQ_ENTRY(pfi_entry) link;
66143611Sphilip};
67143611SphilipTAILQ_HEAD(pfi_table, pfi_entry);
68143611Sphilip
69143611Sphilipstatic struct pfi_table pfi_table;
70143611Sphilipstatic time_t pfi_table_age;
71143611Sphilipstatic int pfi_table_count;
72143611Sphilip
73143611Sphilip#define PFI_TABLE_MAXAGE	5
74143611Sphilip
75143611Sphilipstruct pft_entry {
76143611Sphilip	struct pfr_tstats pft;
77143611Sphilip	u_int		index;
78143611Sphilip	TAILQ_ENTRY(pft_entry) link;
79143611Sphilip};
80143611SphilipTAILQ_HEAD(pft_table, pft_entry);
81143611Sphilip
82143611Sphilipstatic struct pft_table pft_table;
83143611Sphilipstatic time_t pft_table_age;
84143611Sphilipstatic int pft_table_count;
85143611Sphilip
86143611Sphilip#define PFT_TABLE_MAXAGE	5
87143611Sphilip
88143611Sphilipstruct pfq_entry {
89143611Sphilip	struct pf_altq	altq;
90143611Sphilip	u_int		index;
91143611Sphilip	TAILQ_ENTRY(pfq_entry) link;
92143611Sphilip};
93143611SphilipTAILQ_HEAD(pfq_table, pfq_entry);
94143611Sphilip
95143611Sphilipstatic struct pfq_table pfq_table;
96143611Sphilipstatic time_t pfq_table_age;
97143611Sphilipstatic int pfq_table_count;
98143611Sphilip
99143611Sphilip#define PFQ_TABLE_MAXAGE	5
100143611Sphilip
101143611Sphilip/* Forward declarations */
102143611Sphilipstatic int pfi_refresh(void);
103143611Sphilipstatic int pfq_refresh(void);
104143611Sphilipstatic int pfs_refresh(void);
105143611Sphilipstatic int pft_refresh(void);
106143611Sphilipstatic struct pfi_entry * pfi_table_find(u_int idx);
107143611Sphilipstatic struct pfq_entry * pfq_table_find(u_int idx);
108143611Sphilipstatic struct pft_entry * pft_table_find(u_int idx);
109143611Sphilip
110143611Sphilipint
111143611Sphilippf_status(struct snmp_context __unused *ctx, struct snmp_value *val,
112143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
113143611Sphilip{
114143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
115143611Sphilip	time_t		runtime;
116143611Sphilip	unsigned char	str[128];
117143611Sphilip
118143611Sphilip	if (op == SNMP_OP_SET)
119143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
120143611Sphilip
121143611Sphilip	if (op == SNMP_OP_GET) {
122143611Sphilip		if (pfs_refresh() == -1)
123143611Sphilip			return (SNMP_ERR_GENERR);
124143611Sphilip
125143611Sphilip		switch (which) {
126143611Sphilip			case LEAF_pfStatusRunning:
127143611Sphilip			    val->v.uint32 = pfs.running;
128143611Sphilip			    break;
129143611Sphilip			case LEAF_pfStatusRuntime:
130143611Sphilip			    runtime = (pfs.since > 0) ?
131143611Sphilip				time(NULL) - pfs.since : 0;
132143611Sphilip			    val->v.uint32 = runtime * 100;
133143611Sphilip			    break;
134143611Sphilip			case LEAF_pfStatusDebug:
135143611Sphilip			    val->v.uint32 = pfs.debug;
136143611Sphilip			    break;
137143611Sphilip			case LEAF_pfStatusHostId:
138143611Sphilip			    sprintf(str, "0x%08x", ntohl(pfs.hostid));
139143611Sphilip			    return (string_get(val, str, strlen(str)));
140143611Sphilip
141143611Sphilip			default:
142143611Sphilip			    return (SNMP_ERR_NOSUCHNAME);
143143611Sphilip		}
144143611Sphilip
145143611Sphilip		return (SNMP_ERR_NOERROR);
146143611Sphilip	}
147143611Sphilip
148143611Sphilip	abort();
149143611Sphilip}
150143611Sphilip
151143611Sphilipint
152143611Sphilippf_counter(struct snmp_context __unused *ctx, struct snmp_value *val,
153143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
154143611Sphilip{
155143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
156143611Sphilip
157143611Sphilip	if (op == SNMP_OP_SET)
158143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
159143611Sphilip
160143611Sphilip	if (op == SNMP_OP_GET) {
161143611Sphilip		if (pfs_refresh() == -1)
162143611Sphilip			return (SNMP_ERR_GENERR);
163143611Sphilip
164143611Sphilip		switch (which) {
165143611Sphilip			case LEAF_pfCounterMatch:
166143611Sphilip				val->v.counter64 = pfs.counters[PFRES_MATCH];
167143611Sphilip				break;
168143611Sphilip			case LEAF_pfCounterBadOffset:
169143611Sphilip				val->v.counter64 = pfs.counters[PFRES_BADOFF];
170143611Sphilip				break;
171143611Sphilip			case LEAF_pfCounterFragment:
172143611Sphilip				val->v.counter64 = pfs.counters[PFRES_FRAG];
173143611Sphilip				break;
174143611Sphilip			case LEAF_pfCounterShort:
175143611Sphilip				val->v.counter64 = pfs.counters[PFRES_SHORT];
176143611Sphilip				break;
177143611Sphilip			case LEAF_pfCounterNormalize:
178143611Sphilip				val->v.counter64 = pfs.counters[PFRES_NORM];
179143611Sphilip				break;
180143611Sphilip			case LEAF_pfCounterMemDrop:
181143611Sphilip				val->v.counter64 = pfs.counters[PFRES_MEMORY];
182143611Sphilip				break;
183143611Sphilip
184143611Sphilip			default:
185143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
186143611Sphilip		}
187143611Sphilip
188143611Sphilip		return (SNMP_ERR_NOERROR);
189143611Sphilip	}
190143611Sphilip
191143611Sphilip	abort();
192143611Sphilip}
193143611Sphilip
194143611Sphilipint
195143611Sphilippf_statetable(struct snmp_context __unused *ctx, struct snmp_value *val,
196143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
197143611Sphilip{
198143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
199143611Sphilip
200143611Sphilip	if (op == SNMP_OP_SET)
201143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
202143611Sphilip
203143611Sphilip	if (op == SNMP_OP_GET) {
204143611Sphilip		if (pfs_refresh() == -1)
205143611Sphilip			return (SNMP_ERR_GENERR);
206143611Sphilip
207143611Sphilip		switch (which) {
208143611Sphilip			case LEAF_pfStateTableCount:
209143611Sphilip				val->v.uint32 = pfs.states;
210143611Sphilip				break;
211143611Sphilip			case LEAF_pfStateTableSearches:
212143611Sphilip				val->v.counter64 =
213143611Sphilip				    pfs.fcounters[FCNT_STATE_SEARCH];
214143611Sphilip				break;
215143611Sphilip			case LEAF_pfStateTableInserts:
216143611Sphilip				val->v.counter64 =
217143611Sphilip				    pfs.fcounters[FCNT_STATE_INSERT];
218143611Sphilip				break;
219143611Sphilip			case LEAF_pfStateTableRemovals:
220143611Sphilip				val->v.counter64 =
221143611Sphilip				    pfs.fcounters[FCNT_STATE_REMOVALS];
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_srcnodes(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_pfSrcNodesCount:
249143611Sphilip				val->v.uint32 = pfs.src_nodes;
250143611Sphilip				break;
251143611Sphilip			case LEAF_pfSrcNodesSearches:
252143611Sphilip				val->v.counter64 =
253143611Sphilip				    pfs.scounters[SCNT_SRC_NODE_SEARCH];
254143611Sphilip				break;
255143611Sphilip			case LEAF_pfSrcNodesInserts:
256143611Sphilip				val->v.counter64 =
257143611Sphilip				    pfs.scounters[SCNT_SRC_NODE_INSERT];
258143611Sphilip				break;
259143611Sphilip			case LEAF_pfSrcNodesRemovals:
260143611Sphilip				val->v.counter64 =
261143611Sphilip				    pfs.scounters[SCNT_SRC_NODE_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_limits(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	struct pfioc_limit	pl;
280143611Sphilip
281143611Sphilip	if (op == SNMP_OP_SET)
282143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
283143611Sphilip
284143611Sphilip	if (op == SNMP_OP_GET) {
285143611Sphilip		bzero(&pl, sizeof(struct pfioc_limit));
286143611Sphilip
287143611Sphilip		switch (which) {
288143611Sphilip			case LEAF_pfLimitsStates:
289143611Sphilip				pl.index = PF_LIMIT_STATES;
290143611Sphilip				break;
291143611Sphilip			case LEAF_pfLimitsSrcNodes:
292143611Sphilip				pl.index = PF_LIMIT_SRC_NODES;
293143611Sphilip				break;
294143611Sphilip			case LEAF_pfLimitsFrags:
295143611Sphilip				pl.index = PF_LIMIT_FRAGS;
296143611Sphilip				break;
297143611Sphilip
298143611Sphilip			default:
299143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
300143611Sphilip		}
301143611Sphilip
302143611Sphilip		if (ioctl(dev, DIOCGETLIMIT, &pl)) {
303143611Sphilip			syslog(LOG_ERR, "pf_limits(): ioctl(): %s",
304143611Sphilip			    strerror(errno));
305143611Sphilip			return (SNMP_ERR_GENERR);
306143611Sphilip		}
307143611Sphilip
308143611Sphilip		val->v.uint32 = pl.limit;
309143611Sphilip
310143611Sphilip		return (SNMP_ERR_NOERROR);
311143611Sphilip	}
312143611Sphilip
313143611Sphilip	abort();
314143611Sphilip}
315143611Sphilip
316143611Sphilipint
317143611Sphilippf_timeouts(struct snmp_context __unused *ctx, struct snmp_value *val,
318143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
319143611Sphilip{
320143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
321143611Sphilip	struct pfioc_tm	pt;
322143611Sphilip
323143611Sphilip	if (op == SNMP_OP_SET)
324143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
325143611Sphilip
326143611Sphilip	if (op == SNMP_OP_GET) {
327143611Sphilip		bzero(&pt, sizeof(struct pfioc_tm));
328143611Sphilip
329143611Sphilip		switch (which) {
330143611Sphilip			case LEAF_pfTimeoutsTcpFirst:
331143611Sphilip				pt.timeout = PFTM_TCP_FIRST_PACKET;
332143611Sphilip				break;
333143611Sphilip			case LEAF_pfTimeoutsTcpOpening:
334143611Sphilip				pt.timeout = PFTM_TCP_OPENING;
335143611Sphilip				break;
336143611Sphilip			case LEAF_pfTimeoutsTcpEstablished:
337143611Sphilip				pt.timeout = PFTM_TCP_ESTABLISHED;
338143611Sphilip				break;
339143611Sphilip			case LEAF_pfTimeoutsTcpClosing:
340143611Sphilip				pt.timeout = PFTM_TCP_CLOSING;
341143611Sphilip				break;
342143611Sphilip			case LEAF_pfTimeoutsTcpFinWait:
343143611Sphilip				pt.timeout = PFTM_TCP_FIN_WAIT;
344143611Sphilip				break;
345143611Sphilip			case LEAF_pfTimeoutsTcpClosed:
346143611Sphilip				pt.timeout = PFTM_TCP_CLOSED;
347143611Sphilip				break;
348143611Sphilip			case LEAF_pfTimeoutsUdpFirst:
349143611Sphilip				pt.timeout = PFTM_UDP_FIRST_PACKET;
350143611Sphilip				break;
351143611Sphilip			case LEAF_pfTimeoutsUdpSingle:
352143611Sphilip				pt.timeout = PFTM_UDP_SINGLE;
353143611Sphilip				break;
354143611Sphilip			case LEAF_pfTimeoutsUdpMultiple:
355143611Sphilip				pt.timeout = PFTM_UDP_MULTIPLE;
356143611Sphilip				break;
357143611Sphilip			case LEAF_pfTimeoutsIcmpFirst:
358143611Sphilip				pt.timeout = PFTM_ICMP_FIRST_PACKET;
359143611Sphilip				break;
360143611Sphilip			case LEAF_pfTimeoutsIcmpError:
361143611Sphilip				pt.timeout = PFTM_ICMP_ERROR_REPLY;
362143611Sphilip				break;
363143611Sphilip			case LEAF_pfTimeoutsOtherFirst:
364143611Sphilip				pt.timeout = PFTM_OTHER_FIRST_PACKET;
365143611Sphilip				break;
366143611Sphilip			case LEAF_pfTimeoutsOtherSingle:
367143611Sphilip				pt.timeout = PFTM_OTHER_SINGLE;
368143611Sphilip				break;
369143611Sphilip			case LEAF_pfTimeoutsOtherMultiple:
370143611Sphilip				pt.timeout = PFTM_OTHER_MULTIPLE;
371143611Sphilip				break;
372143611Sphilip			case LEAF_pfTimeoutsFragment:
373143611Sphilip				pt.timeout = PFTM_FRAG;
374143611Sphilip				break;
375143611Sphilip			case LEAF_pfTimeoutsInterval:
376143611Sphilip				pt.timeout = PFTM_INTERVAL;
377143611Sphilip				break;
378143611Sphilip			case LEAF_pfTimeoutsAdaptiveStart:
379143611Sphilip				pt.timeout = PFTM_ADAPTIVE_START;
380143611Sphilip				break;
381143611Sphilip			case LEAF_pfTimeoutsAdaptiveEnd:
382143611Sphilip				pt.timeout = PFTM_ADAPTIVE_END;
383143611Sphilip				break;
384143611Sphilip			case LEAF_pfTimeoutsSrcNode:
385143611Sphilip				pt.timeout = PFTM_SRC_NODE;
386143611Sphilip				break;
387143611Sphilip
388143611Sphilip			default:
389143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
390143611Sphilip		}
391143611Sphilip
392143611Sphilip		if (ioctl(dev, DIOCGETTIMEOUT, &pt)) {
393143611Sphilip			syslog(LOG_ERR, "pf_timeouts(): ioctl(): %s",
394143611Sphilip			    strerror(errno));
395143611Sphilip			return (SNMP_ERR_GENERR);
396143611Sphilip		}
397143611Sphilip
398143611Sphilip		val->v.integer = pt.seconds;
399143611Sphilip
400143611Sphilip		return (SNMP_ERR_NOERROR);
401143611Sphilip	}
402143611Sphilip
403143611Sphilip	abort();
404143611Sphilip}
405143611Sphilip
406143611Sphilipint
407143611Sphilippf_logif(struct snmp_context __unused *ctx, struct snmp_value *val,
408143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
409143611Sphilip{
410143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
411143611Sphilip	unsigned char	str[IFNAMSIZ];
412143611Sphilip
413143611Sphilip	if (op == SNMP_OP_SET)
414143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
415143611Sphilip
416143611Sphilip	if (op == SNMP_OP_GET) {
417143611Sphilip		if (pfs_refresh() == -1)
418143611Sphilip			return (SNMP_ERR_GENERR);
419143611Sphilip
420143611Sphilip		switch (which) {
421143611Sphilip	 		case LEAF_pfLogInterfaceName:
422143611Sphilip				strlcpy(str, pfs.ifname, sizeof str);
423143611Sphilip				return (string_get(val, str, strlen(str)));
424143611Sphilip			case LEAF_pfLogInterfaceIp4BytesIn:
425143611Sphilip				val->v.counter64 = pfs.bcounters[IPV4][IN];
426143611Sphilip				break;
427143611Sphilip			case LEAF_pfLogInterfaceIp4BytesOut:
428143611Sphilip				val->v.counter64 = pfs.bcounters[IPV4][OUT];
429143611Sphilip				break;
430143611Sphilip			case LEAF_pfLogInterfaceIp4PktsInPass:
431143611Sphilip				val->v.counter64 =
432143611Sphilip				    pfs.pcounters[IPV4][IN][PF_PASS];
433143611Sphilip				break;
434143611Sphilip			case LEAF_pfLogInterfaceIp4PktsInDrop:
435143611Sphilip				val->v.counter64 =
436143611Sphilip				    pfs.pcounters[IPV4][IN][PF_DROP];
437143611Sphilip				break;
438143611Sphilip			case LEAF_pfLogInterfaceIp4PktsOutPass:
439143611Sphilip				val->v.counter64 =
440143611Sphilip				    pfs.pcounters[IPV4][OUT][PF_PASS];
441143611Sphilip				break;
442143611Sphilip			case LEAF_pfLogInterfaceIp4PktsOutDrop:
443143611Sphilip				val->v.counter64 =
444143611Sphilip				    pfs.pcounters[IPV4][OUT][PF_DROP];
445143611Sphilip				break;
446143611Sphilip			case LEAF_pfLogInterfaceIp6BytesIn:
447143611Sphilip				val->v.counter64 = pfs.bcounters[IPV6][IN];
448143611Sphilip				break;
449143611Sphilip			case LEAF_pfLogInterfaceIp6BytesOut:
450143611Sphilip				val->v.counter64 = pfs.bcounters[IPV6][OUT];
451143611Sphilip				break;
452143611Sphilip			case LEAF_pfLogInterfaceIp6PktsInPass:
453143611Sphilip				val->v.counter64 =
454143611Sphilip				    pfs.pcounters[IPV6][IN][PF_PASS];
455143611Sphilip				break;
456143611Sphilip			case LEAF_pfLogInterfaceIp6PktsInDrop:
457143611Sphilip				val->v.counter64 =
458143611Sphilip				    pfs.pcounters[IPV6][IN][PF_DROP];
459143611Sphilip				break;
460143611Sphilip			case LEAF_pfLogInterfaceIp6PktsOutPass:
461143611Sphilip				val->v.counter64 =
462143611Sphilip				    pfs.pcounters[IPV6][OUT][PF_PASS];
463143611Sphilip				break;
464143611Sphilip			case LEAF_pfLogInterfaceIp6PktsOutDrop:
465143611Sphilip				val->v.counter64 =
466143611Sphilip				    pfs.pcounters[IPV6][OUT][PF_DROP];
467143611Sphilip				break;
468143611Sphilip
469143611Sphilip			default:
470143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
471143611Sphilip		}
472143611Sphilip
473143611Sphilip		return (SNMP_ERR_NOERROR);
474143611Sphilip	}
475143611Sphilip
476143611Sphilip	abort();
477143611Sphilip}
478143611Sphilip
479143611Sphilipint
480143611Sphilippf_interfaces(struct snmp_context __unused *ctx, struct snmp_value *val,
481143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
482143611Sphilip{
483143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
484143611Sphilip
485143611Sphilip	if (op == SNMP_OP_SET)
486143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
487143611Sphilip
488143611Sphilip	if (op == SNMP_OP_GET) {
489143611Sphilip		if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE)
490143611Sphilip			if (pfi_refresh() == -1)
491143611Sphilip			    return (SNMP_ERR_GENERR);
492143611Sphilip
493143611Sphilip		switch (which) {
494143611Sphilip			case LEAF_pfInterfacesIfNumber:
495143611Sphilip				val->v.uint32 = pfi_table_count;
496143611Sphilip				break;
497143611Sphilip
498143611Sphilip			default:
499143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
500143611Sphilip		}
501143611Sphilip
502143611Sphilip		return (SNMP_ERR_NOERROR);
503143611Sphilip	}
504143611Sphilip
505143611Sphilip	abort();
506143611Sphilip}
507143611Sphilip
508143611Sphilipint
509143611Sphilippf_iftable(struct snmp_context __unused *ctx, struct snmp_value *val,
510143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
511143611Sphilip{
512143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
513143611Sphilip	struct pfi_entry *e = NULL;
514143611Sphilip
515143611Sphilip	switch (op) {
516143611Sphilip		case SNMP_OP_SET:
517143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
518143611Sphilip		case SNMP_OP_GETNEXT:
519143611Sphilip			if ((e = NEXT_OBJECT_INT(&pfi_table,
520143611Sphilip			    &val->var, sub)) == NULL)
521143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
522143611Sphilip			val->var.len = sub + 1;
523143611Sphilip			val->var.subs[sub] = e->index;
524143611Sphilip			break;
525143611Sphilip		case SNMP_OP_GET:
526143611Sphilip			if (val->var.len - sub != 1)
527143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
528143611Sphilip			if ((e = pfi_table_find(val->var.subs[sub])) == NULL)
529143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
530143611Sphilip			break;
531143611Sphilip
532143611Sphilip		case SNMP_OP_COMMIT:
533143611Sphilip		case SNMP_OP_ROLLBACK:
534143611Sphilip		default:
535143611Sphilip			abort();
536143611Sphilip	}
537143611Sphilip
538143611Sphilip	if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE)
539143611Sphilip		pfi_refresh();
540143611Sphilip
541143611Sphilip	switch (which) {
542143611Sphilip		case LEAF_pfInterfacesIfDescr:
543143611Sphilip			return (string_get(val, e->pfi.pfif_name, -1));
544143611Sphilip		case LEAF_pfInterfacesIfType:
545143611Sphilip			val->v.integer = PFI_IFTYPE_INSTANCE;
546143611Sphilip			break;
547143611Sphilip		case LEAF_pfInterfacesIfTZero:
548143611Sphilip			val->v.uint32 =
549143611Sphilip			    (time(NULL) - e->pfi.pfif_tzero) * 100;
550143611Sphilip			break;
551143611Sphilip		case LEAF_pfInterfacesIfRefsState:
552143611Sphilip			val->v.uint32 = e->pfi.pfif_states;
553143611Sphilip			break;
554143611Sphilip		case LEAF_pfInterfacesIfRefsRule:
555143611Sphilip			val->v.uint32 = e->pfi.pfif_rules;
556143611Sphilip			break;
557143611Sphilip		case LEAF_pfInterfacesIf4BytesInPass:
558143611Sphilip			val->v.counter64 =
559143611Sphilip			    e->pfi.pfif_bytes[IPV4][IN][PASS];
560143611Sphilip			break;
561143611Sphilip		case LEAF_pfInterfacesIf4BytesInBlock:
562143611Sphilip			val->v.counter64 =
563143611Sphilip			    e->pfi.pfif_bytes[IPV4][IN][BLOCK];
564143611Sphilip			break;
565143611Sphilip		case LEAF_pfInterfacesIf4BytesOutPass:
566143611Sphilip			val->v.counter64 =
567143611Sphilip			    e->pfi.pfif_bytes[IPV4][OUT][PASS];
568143611Sphilip			break;
569143611Sphilip		case LEAF_pfInterfacesIf4BytesOutBlock:
570143611Sphilip			val->v.counter64 =
571143611Sphilip			    e->pfi.pfif_bytes[IPV4][OUT][BLOCK];
572143611Sphilip			break;
573143611Sphilip		case LEAF_pfInterfacesIf4PktsInPass:
574143611Sphilip			val->v.counter64 =
575143611Sphilip			    e->pfi.pfif_packets[IPV4][IN][PASS];
576143611Sphilip			break;
577143611Sphilip		case LEAF_pfInterfacesIf4PktsInBlock:
578143611Sphilip			val->v.counter64 =
579143611Sphilip			    e->pfi.pfif_packets[IPV4][IN][BLOCK];
580143611Sphilip			break;
581143611Sphilip		case LEAF_pfInterfacesIf4PktsOutPass:
582143611Sphilip			val->v.counter64 =
583143611Sphilip			    e->pfi.pfif_packets[IPV4][OUT][PASS];
584143611Sphilip			break;
585143611Sphilip		case LEAF_pfInterfacesIf4PktsOutBlock:
586143611Sphilip			val->v.counter64 =
587143611Sphilip			    e->pfi.pfif_packets[IPV4][OUT][BLOCK];
588143611Sphilip			break;
589143611Sphilip		case LEAF_pfInterfacesIf6BytesInPass:
590143611Sphilip			val->v.counter64 =
591143611Sphilip			    e->pfi.pfif_bytes[IPV6][IN][PASS];
592143611Sphilip			break;
593143611Sphilip		case LEAF_pfInterfacesIf6BytesInBlock:
594143611Sphilip			val->v.counter64 =
595143611Sphilip			    e->pfi.pfif_bytes[IPV6][IN][BLOCK];
596143611Sphilip			break;
597143611Sphilip		case LEAF_pfInterfacesIf6BytesOutPass:
598143611Sphilip			val->v.counter64 =
599143611Sphilip			    e->pfi.pfif_bytes[IPV6][OUT][PASS];
600143611Sphilip			break;
601143611Sphilip		case LEAF_pfInterfacesIf6BytesOutBlock:
602143611Sphilip			val->v.counter64 =
603143611Sphilip			    e->pfi.pfif_bytes[IPV6][OUT][BLOCK];
604143611Sphilip			break;
605143611Sphilip		case LEAF_pfInterfacesIf6PktsInPass:
606143611Sphilip			val->v.counter64 =
607143611Sphilip			    e->pfi.pfif_packets[IPV6][IN][PASS];
608143611Sphilip			break;
609143611Sphilip		case LEAF_pfInterfacesIf6PktsInBlock:
610143611Sphilip			val->v.counter64 =
611143611Sphilip			    e->pfi.pfif_packets[IPV6][IN][BLOCK];
612143611Sphilip			break;
613143611Sphilip		case LEAF_pfInterfacesIf6PktsOutPass:
614143611Sphilip			val->v.counter64 =
615143611Sphilip			    e->pfi.pfif_packets[IPV6][OUT][PASS];
616143611Sphilip			break;
617143611Sphilip		case LEAF_pfInterfacesIf6PktsOutBlock:
618143611Sphilip			val->v.counter64 =
619143611Sphilip			    e->pfi.pfif_packets[IPV6][OUT][BLOCK];
620143611Sphilip			break;
621143611Sphilip
622143611Sphilip		default:
623143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
624143611Sphilip	}
625143611Sphilip
626143611Sphilip	return (SNMP_ERR_NOERROR);
627143611Sphilip}
628143611Sphilip
629143611Sphilipint
630143611Sphilippf_tables(struct snmp_context __unused *ctx, struct snmp_value *val,
631143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
632143611Sphilip{
633143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
634143611Sphilip
635143611Sphilip	if (op == SNMP_OP_SET)
636143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
637143611Sphilip
638143611Sphilip	if (op == SNMP_OP_GET) {
639143611Sphilip		if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
640143611Sphilip			if (pft_refresh() == -1)
641143611Sphilip			    return (SNMP_ERR_GENERR);
642143611Sphilip
643143611Sphilip		switch (which) {
644143611Sphilip			case LEAF_pfTablesTblNumber:
645143611Sphilip				val->v.uint32 = pft_table_count;
646143611Sphilip				break;
647143611Sphilip
648143611Sphilip			default:
649143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
650143611Sphilip		}
651143611Sphilip
652143611Sphilip		return (SNMP_ERR_NOERROR);
653143611Sphilip	}
654143611Sphilip
655143611Sphilip	abort();
656143611Sphilip}
657143611Sphilip
658143611Sphilipint
659143611Sphilippf_tbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
660143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
661143611Sphilip{
662143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
663143611Sphilip	struct pft_entry *e = NULL;
664143611Sphilip
665143611Sphilip	switch (op) {
666143611Sphilip		case SNMP_OP_SET:
667143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
668143611Sphilip		case SNMP_OP_GETNEXT:
669143611Sphilip			if ((e = NEXT_OBJECT_INT(&pft_table,
670143611Sphilip			    &val->var, sub)) == NULL)
671143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
672143611Sphilip			val->var.len = sub + 1;
673143611Sphilip			val->var.subs[sub] = e->index;
674143611Sphilip			break;
675143611Sphilip		case SNMP_OP_GET:
676143611Sphilip			if (val->var.len - sub != 1)
677143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
678143611Sphilip			if ((e = pft_table_find(val->var.subs[sub])) == NULL)
679143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
680143611Sphilip			break;
681143611Sphilip
682143611Sphilip		case SNMP_OP_COMMIT:
683143611Sphilip		case SNMP_OP_ROLLBACK:
684143611Sphilip		default:
685143611Sphilip			abort();
686143611Sphilip	}
687143611Sphilip
688143611Sphilip	if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
689143611Sphilip		pft_refresh();
690143611Sphilip
691143611Sphilip	switch (which) {
692143611Sphilip		case LEAF_pfTablesTblDescr:
693143611Sphilip			return (string_get(val, e->pft.pfrts_name, -1));
694143611Sphilip		case LEAF_pfTablesTblCount:
695143611Sphilip			val->v.integer = e->pft.pfrts_cnt;
696143611Sphilip			break;
697143611Sphilip		case LEAF_pfTablesTblTZero:
698143611Sphilip			val->v.uint32 =
699143611Sphilip			    (time(NULL) - e->pft.pfrts_tzero) * 100;
700143611Sphilip			break;
701143611Sphilip		case LEAF_pfTablesTblRefsAnchor:
702143611Sphilip			val->v.integer =
703143611Sphilip			    e->pft.pfrts_refcnt[PFR_REFCNT_ANCHOR];
704143611Sphilip			break;
705143611Sphilip		case LEAF_pfTablesTblRefsRule:
706143611Sphilip			val->v.integer =
707143611Sphilip			    e->pft.pfrts_refcnt[PFR_REFCNT_RULE];
708143611Sphilip			break;
709143611Sphilip		case LEAF_pfTablesTblEvalMatch:
710143611Sphilip			val->v.counter64 = e->pft.pfrts_match;
711143611Sphilip			break;
712143611Sphilip		case LEAF_pfTablesTblEvalNoMatch:
713143611Sphilip			val->v.counter64 = e->pft.pfrts_nomatch;
714143611Sphilip			break;
715143611Sphilip		case LEAF_pfTablesTblBytesInPass:
716143611Sphilip			val->v.counter64 =
717143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_PASS];
718143611Sphilip			break;
719143611Sphilip		case LEAF_pfTablesTblBytesInBlock:
720143611Sphilip			val->v.counter64 =
721143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_BLOCK];
722143611Sphilip			break;
723143611Sphilip		case LEAF_pfTablesTblBytesInXPass:
724143611Sphilip			val->v.counter64 =
725143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_XPASS];
726143611Sphilip			break;
727143611Sphilip		case LEAF_pfTablesTblBytesOutPass:
728143611Sphilip			val->v.counter64 =
729143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_PASS];
730143611Sphilip			break;
731143611Sphilip		case LEAF_pfTablesTblBytesOutBlock:
732143611Sphilip			val->v.counter64 =
733143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_BLOCK];
734143611Sphilip			break;
735143611Sphilip		case LEAF_pfTablesTblBytesOutXPass:
736143611Sphilip			val->v.counter64 =
737143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_XPASS];
738143611Sphilip			break;
739143611Sphilip		case LEAF_pfTablesTblPktsInPass:
740143611Sphilip			val->v.counter64 =
741143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_PASS];
742143611Sphilip			break;
743143611Sphilip		case LEAF_pfTablesTblPktsInBlock:
744143611Sphilip			val->v.counter64 =
745143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_BLOCK];
746143611Sphilip			break;
747143611Sphilip		case LEAF_pfTablesTblPktsInXPass:
748143611Sphilip			val->v.counter64 =
749143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_XPASS];
750143611Sphilip			break;
751143611Sphilip		case LEAF_pfTablesTblPktsOutPass:
752143611Sphilip			val->v.counter64 =
753143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_PASS];
754143611Sphilip			break;
755143611Sphilip		case LEAF_pfTablesTblPktsOutBlock:
756143611Sphilip			val->v.counter64 =
757143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_BLOCK];
758143611Sphilip			break;
759143611Sphilip		case LEAF_pfTablesTblPktsOutXPass:
760143611Sphilip			val->v.counter64 =
761143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_XPASS];
762143611Sphilip			break;
763143611Sphilip
764143611Sphilip		default:
765143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
766143611Sphilip	}
767143611Sphilip
768143611Sphilip	return (SNMP_ERR_NOERROR);
769143611Sphilip}
770143611Sphilip
771143611Sphilipint
772143611Sphilippf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val,
773143611Sphilip	u_int __unused sub, u_int __unused vindex, enum snmp_op __unused op)
774143611Sphilip{
775143611Sphilip	return (SNMP_ERR_GENERR);
776143611Sphilip}
777143611Sphilip
778143611Sphilipint
779143611Sphilippf_altq(struct snmp_context __unused *ctx, struct snmp_value *val,
780143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
781143611Sphilip{
782143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
783143611Sphilip
784143611Sphilip	if (op == SNMP_OP_SET)
785143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
786143611Sphilip
787143611Sphilip	if (op == SNMP_OP_GET) {
788143611Sphilip		if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
789143611Sphilip			if (pfq_refresh() == -1)
790143611Sphilip			    return (SNMP_ERR_GENERR);
791143611Sphilip
792143611Sphilip		switch (which) {
793143611Sphilip			case LEAF_pfAltqQueueNumber:
794143611Sphilip				val->v.uint32 = pfq_table_count;
795143611Sphilip				break;
796143611Sphilip
797143611Sphilip			default:
798143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
799143611Sphilip		}
800143611Sphilip
801143611Sphilip		return (SNMP_ERR_NOERROR);
802143611Sphilip	}
803143611Sphilip
804143611Sphilip	abort();
805143611Sphilip	return (SNMP_ERR_GENERR);
806143611Sphilip}
807143611Sphilip
808143611Sphilipint
809143611Sphilippf_altqq(struct snmp_context __unused *ctx, struct snmp_value *val,
810143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
811143611Sphilip{
812143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
813143611Sphilip	struct pfq_entry *e = NULL;
814143611Sphilip
815143611Sphilip	switch (op) {
816143611Sphilip		case SNMP_OP_SET:
817143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
818143611Sphilip		case SNMP_OP_GETNEXT:
819143611Sphilip			if ((e = NEXT_OBJECT_INT(&pfq_table,
820143611Sphilip			    &val->var, sub)) == NULL)
821143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
822143611Sphilip			val->var.len = sub + 1;
823143611Sphilip			val->var.subs[sub] = e->index;
824143611Sphilip			break;
825143611Sphilip		case SNMP_OP_GET:
826143611Sphilip			if (val->var.len - sub != 1)
827143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
828143611Sphilip			if ((e = pfq_table_find(val->var.subs[sub])) == NULL)
829143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
830143611Sphilip			break;
831143611Sphilip
832143611Sphilip		case SNMP_OP_COMMIT:
833143611Sphilip		case SNMP_OP_ROLLBACK:
834143611Sphilip		default:
835143611Sphilip			abort();
836143611Sphilip	}
837143611Sphilip
838143611Sphilip	if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
839143611Sphilip		pfq_refresh();
840143611Sphilip
841143611Sphilip	switch (which) {
842143611Sphilip		case LEAF_pfAltqQueueDescr:
843143611Sphilip			return (string_get(val, e->altq.qname, -1));
844143611Sphilip		case LEAF_pfAltqQueueParent:
845143611Sphilip			return (string_get(val, e->altq.parent, -1));
846143611Sphilip		case LEAF_pfAltqQueueScheduler:
847143611Sphilip			val->v.integer = e->altq.scheduler;
848143611Sphilip			break;
849143611Sphilip		case LEAF_pfAltqQueueBandwidth:
850143611Sphilip			val->v.uint32 = e->altq.bandwidth;
851143611Sphilip			break;
852143611Sphilip		case LEAF_pfAltqQueuePriority:
853143611Sphilip			val->v.integer = e->altq.priority;
854143611Sphilip			break;
855143611Sphilip		case LEAF_pfAltqQueueLimit:
856143611Sphilip			val->v.integer = e->altq.qlimit;
857143611Sphilip			break;
858143611Sphilip
859143611Sphilip		default:
860143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
861143611Sphilip	}
862143611Sphilip
863143611Sphilip	return (SNMP_ERR_NOERROR);
864143611Sphilip}
865143611Sphilip
866143611Sphilipstatic struct pfi_entry *
867143611Sphilippfi_table_find(u_int idx)
868143611Sphilip{
869143611Sphilip	struct pfi_entry *e;
870143611Sphilip
871143611Sphilip	TAILQ_FOREACH(e, &pfi_table, link)
872143611Sphilip		if (e->index == idx)
873143611Sphilip			return (e);
874143611Sphilip	return (NULL);
875143611Sphilip}
876143611Sphilip
877143611Sphilipstatic struct pfq_entry *
878143611Sphilippfq_table_find(u_int idx)
879143611Sphilip{
880143611Sphilip	struct pfq_entry *e;
881143611Sphilip	TAILQ_FOREACH(e, &pfq_table, link)
882143611Sphilip		if (e->index == idx)
883143611Sphilip			return (e);
884143611Sphilip	return (NULL);
885143611Sphilip}
886143611Sphilip
887143611Sphilipstatic struct pft_entry *
888143611Sphilippft_table_find(u_int idx)
889143611Sphilip{
890143611Sphilip	struct pft_entry *e;
891143611Sphilip
892143611Sphilip	TAILQ_FOREACH(e, &pft_table, link)
893143611Sphilip		if (e->index == idx)
894143611Sphilip			return (e);
895143611Sphilip	return (NULL);
896143611Sphilip}
897143611Sphilip
898143611Sphilipstatic int
899143611Sphilippfi_refresh(void)
900143611Sphilip{
901143611Sphilip	struct pfioc_iface io;
902143611Sphilip	struct pfi_if *p;
903143611Sphilip	struct pfi_entry *e;
904143611Sphilip	int i, numifs = 1;
905143611Sphilip
906143611Sphilip	if (started && this_tick <= pf_tick)
907143611Sphilip		return (0);
908143611Sphilip
909143611Sphilip	while (!TAILQ_EMPTY(&pfi_table)) {
910143611Sphilip		e = TAILQ_FIRST(&pfi_table);
911143611Sphilip		TAILQ_REMOVE(&pfi_table, e, link);
912143611Sphilip		free(e);
913143611Sphilip	}
914143611Sphilip
915143611Sphilip	bzero(&io, sizeof(io));
916143611Sphilip	p = malloc(sizeof(struct pfi_if));
917143611Sphilip	io.pfiio_flags = PFI_FLAG_INSTANCE;
918143611Sphilip	io.pfiio_esize = sizeof(struct pfi_if);
919143611Sphilip
920143611Sphilip	for (;;) {
921143611Sphilip		p = realloc(p, numifs * sizeof(struct pfi_if));
922143611Sphilip		io.pfiio_size = numifs;
923143611Sphilip		io.pfiio_buffer = p;
924143611Sphilip
925143611Sphilip		if (ioctl(dev, DIOCIGETIFACES, &io)) {
926143611Sphilip			syslog(LOG_ERR, "pfi_refresh(): ioctl(): %s",
927143611Sphilip			    strerror(errno));
928143611Sphilip			return (-1);
929143611Sphilip		}
930143611Sphilip
931143611Sphilip		if (numifs >= io.pfiio_size)
932143611Sphilip			break;
933143611Sphilip
934143611Sphilip		numifs = io.pfiio_size;
935143611Sphilip	}
936143611Sphilip
937143611Sphilip	for (i = 0; i < numifs; i++) {
938143611Sphilip		e = malloc(sizeof(struct pfi_entry));
939143611Sphilip		e->index = i + 1;
940143611Sphilip		memcpy(&e->pfi, p+i, sizeof(struct pfi_if));
941143611Sphilip		TAILQ_INSERT_TAIL(&pfi_table, e, link);
942143611Sphilip	}
943143611Sphilip
944143611Sphilip	pfi_table_age = time(NULL);
945143611Sphilip	pfi_table_count = numifs;
946143611Sphilip	pf_tick = this_tick;
947143611Sphilip
948143611Sphilip	free(p);
949143611Sphilip	return (0);
950143611Sphilip}
951143611Sphilip
952143611Sphilipstatic int
953143611Sphilippfq_refresh(void)
954143611Sphilip{
955143611Sphilip	struct pfioc_altq pa;
956143611Sphilip	struct pfq_entry *e;
957143611Sphilip	int i, numqs, ticket;
958143611Sphilip
959143611Sphilip	if (started && this_tick <= pf_tick)
960143611Sphilip		return (0);
961143611Sphilip
962143611Sphilip	while (!TAILQ_EMPTY(&pfq_table)) {
963143611Sphilip		e = TAILQ_FIRST(&pfq_table);
964143611Sphilip		TAILQ_REMOVE(&pfq_table, e, link);
965143611Sphilip		free(e);
966143611Sphilip	}
967143611Sphilip
968143611Sphilip	bzero(&pa, sizeof(pa));
969143611Sphilip
970143611Sphilip	if (ioctl(dev, DIOCGETALTQS, &pa)) {
971143611Sphilip		syslog(LOG_ERR, "pfq_refresh: ioctl(DIOCGETALTQS): %s",
972143611Sphilip		    strerror(errno));
973143611Sphilip		return (-1);
974143611Sphilip	}
975143611Sphilip
976143611Sphilip	numqs = pa.nr;
977143611Sphilip	ticket = pa.ticket;
978143611Sphilip
979143611Sphilip	for (i = 0; i < numqs; i++) {
980143611Sphilip		e = malloc(sizeof(struct pfq_entry));
981143611Sphilip		pa.ticket = ticket;
982143611Sphilip		pa.nr = i;
983143611Sphilip
984143611Sphilip		if (ioctl(dev, DIOCGETALTQ, &pa)) {
985143611Sphilip			syslog(LOG_ERR, "pfq_refresh(): "
986143611Sphilip			    "ioctl(DIOCGETALTQ): %s",
987143611Sphilip			    strerror(errno));
988143611Sphilip			return (-1);
989143611Sphilip		}
990143611Sphilip
991143611Sphilip		if (pa.altq.qid > 0) {
992143611Sphilip			memcpy(&e->altq, &pa.altq, sizeof(struct pf_altq));
993143611Sphilip			e->index = pa.altq.qid;
994143611Sphilip			pfq_table_count = i;
995143611Sphilip			TAILQ_INSERT_TAIL(&pfq_table, e, link);
996143611Sphilip		}
997143611Sphilip	}
998143611Sphilip
999143611Sphilip	pfq_table_age = time(NULL);
1000143611Sphilip	pf_tick = this_tick;
1001143611Sphilip
1002143611Sphilip	return (0);
1003143611Sphilip}
1004143611Sphilip
1005143611Sphilipstatic int
1006143611Sphilippfs_refresh(void)
1007143611Sphilip{
1008143611Sphilip	if (started && this_tick <= pf_tick)
1009143611Sphilip		return (0);
1010143611Sphilip
1011143611Sphilip	bzero(&pfs, sizeof(struct pf_status));
1012143611Sphilip
1013143611Sphilip	if (ioctl(dev, DIOCGETSTATUS, &pfs)) {
1014143611Sphilip		syslog(LOG_ERR, "pfs_refresh(): ioctl(): %s",
1015143611Sphilip		    strerror(errno));
1016143611Sphilip		return (-1);
1017143611Sphilip	}
1018143611Sphilip
1019143611Sphilip	pf_tick = this_tick;
1020143611Sphilip	return (0);
1021143611Sphilip}
1022143611Sphilip
1023143611Sphilipstatic int
1024143611Sphilippft_refresh(void)
1025143611Sphilip{
1026143611Sphilip	struct pfioc_table io;
1027143611Sphilip	struct pfr_tstats *t;
1028143611Sphilip	struct pft_entry *e;
1029143611Sphilip	int i, numtbls = 1;
1030143611Sphilip
1031143611Sphilip	if (started && this_tick <= pf_tick)
1032143611Sphilip		return (0);
1033143611Sphilip
1034143611Sphilip	while (!TAILQ_EMPTY(&pft_table)) {
1035143611Sphilip		e = TAILQ_FIRST(&pft_table);
1036143611Sphilip		TAILQ_REMOVE(&pft_table, e, link);
1037143611Sphilip		free(e);
1038143611Sphilip	}
1039143611Sphilip
1040143611Sphilip	bzero(&io, sizeof(io));
1041143611Sphilip	t = malloc(sizeof(struct pfr_tstats));
1042143611Sphilip	io.pfrio_esize = sizeof(struct pfr_tstats);
1043143611Sphilip
1044143611Sphilip	for (;;) {
1045143611Sphilip		t = realloc(t, numtbls * sizeof(struct pfr_tstats));
1046143611Sphilip		io.pfrio_size = numtbls;
1047143611Sphilip		io.pfrio_buffer = t;
1048143611Sphilip
1049143611Sphilip		if (ioctl(dev, DIOCRGETTSTATS, &io)) {
1050143611Sphilip			syslog(LOG_ERR, "pft_refresh(): ioctl(): %s",
1051143611Sphilip			    strerror(errno));
1052143611Sphilip			return (-1);
1053143611Sphilip		}
1054143611Sphilip
1055143611Sphilip		if (numtbls >= io.pfrio_size)
1056143611Sphilip			break;
1057143611Sphilip
1058143611Sphilip		numtbls = io.pfrio_size;
1059143611Sphilip	}
1060143611Sphilip
1061143611Sphilip	for (i = 0; i < numtbls; i++) {
1062143611Sphilip		e = malloc(sizeof(struct pfr_tstats));
1063143611Sphilip		e->index = i + 1;
1064143611Sphilip		memcpy(&e->pft, t+i, sizeof(struct pfr_tstats));
1065143611Sphilip		TAILQ_INSERT_TAIL(&pft_table, e, link);
1066143611Sphilip	}
1067143611Sphilip
1068143611Sphilip	pft_table_age = time(NULL);
1069143611Sphilip	pft_table_count = numtbls;
1070143611Sphilip	pf_tick = this_tick;
1071143611Sphilip
1072143611Sphilip	free(t);
1073143611Sphilip	return (0);
1074143611Sphilip}
1075143611Sphilip
1076143611Sphilip/*
1077143611Sphilip * Implement the bsnmpd module interface
1078143611Sphilip */
1079143611Sphilipstatic int
1080143611Sphilippf_init(struct lmodule *mod, int __unused argc, char __unused *argv[])
1081143611Sphilip{
1082143611Sphilip	module = mod;
1083143611Sphilip
1084143611Sphilip	if ((dev = open("/dev/pf", O_RDONLY)) == -1) {
1085143611Sphilip		syslog(LOG_ERR, "pf_init(): open(): %s\n",
1086143611Sphilip		    strerror(errno));
1087143611Sphilip		return (-1);
1088143611Sphilip	}
1089143611Sphilip
1090143611Sphilip	/* Prepare internal state */
1091143611Sphilip	TAILQ_INIT(&pfi_table);
1092143611Sphilip	TAILQ_INIT(&pfq_table);
1093143611Sphilip	TAILQ_INIT(&pft_table);
1094143611Sphilip
1095143611Sphilip	pfi_refresh();
1096143611Sphilip	pfq_refresh();
1097143611Sphilip	pfs_refresh();
1098143611Sphilip	pft_refresh();
1099143611Sphilip
1100143611Sphilip	started = 1;
1101143611Sphilip
1102143611Sphilip	return (0);
1103143611Sphilip}
1104143611Sphilip
1105143611Sphilipstatic int
1106143611Sphilippf_fini(void)
1107143611Sphilip{
1108143611Sphilip	struct pfi_entry *i1, *i2;
1109143611Sphilip	struct pfq_entry *q1, *q2;
1110143611Sphilip	struct pft_entry *t1, *t2;
1111143611Sphilip
1112143611Sphilip	/* Empty the list of interfaces */
1113143611Sphilip	i1 = TAILQ_FIRST(&pfi_table);
1114143611Sphilip	while (i1 != NULL) {
1115143611Sphilip		i2 = TAILQ_NEXT(i1, link);
1116143611Sphilip		free(i1);
1117143611Sphilip		i1 = i2;
1118143611Sphilip	}
1119143611Sphilip
1120143611Sphilip	/* List of queues */
1121143611Sphilip	q1 = TAILQ_FIRST(&pfq_table);
1122143611Sphilip	while (q1 != NULL) {
1123143611Sphilip		q2 = TAILQ_NEXT(q1, link);
1124143611Sphilip		free(q1);
1125143611Sphilip		q1 = q2;
1126143611Sphilip	}
1127143611Sphilip
1128143611Sphilip	/* And the list of tables */
1129143611Sphilip	t1 = TAILQ_FIRST(&pft_table);
1130143611Sphilip	while (t1 != NULL) {
1131143611Sphilip		t2 = TAILQ_NEXT(t1, link);
1132143611Sphilip		free(t1);
1133143611Sphilip		t1 = t2;
1134143611Sphilip	}
1135143611Sphilip
1136143611Sphilip	close(dev);
1137143611Sphilip	return (0);
1138143611Sphilip}
1139143611Sphilip
1140143611Sphilipstatic void
1141143611Sphilippf_dump(void)
1142143611Sphilip{
1143143611Sphilip	pfi_refresh();
1144143611Sphilip	pfq_refresh();
1145143611Sphilip	pft_refresh();
1146143611Sphilip
1147143654Sphilip	syslog(LOG_ERR, "Dump: pfi_table_age = %jd",
1148143654Sphilip	    (intmax_t)pfi_table_age);
1149143611Sphilip	syslog(LOG_ERR, "Dump: pfi_table_count = %d",
1150143611Sphilip	    pfi_table_count);
1151143611Sphilip
1152143654Sphilip	syslog(LOG_ERR, "Dump: pfq_table_age = %jd",
1153143654Sphilip	    (intmax_t)pfq_table_age);
1154143611Sphilip	syslog(LOG_ERR, "Dump: pfq_table_count = %d",
1155143611Sphilip	    pfq_table_count);
1156143611Sphilip
1157143654Sphilip	syslog(LOG_ERR, "Dump: pft_table_age = %jd",
1158143654Sphilip	    (intmax_t)pft_table_age);
1159143611Sphilip
1160143611Sphilip	syslog(LOG_ERR, "Dump: pft_table_count = %d",
1161143611Sphilip	    pft_table_count);
1162143611Sphilip}
1163143611Sphilip
1164143611Sphilipconst struct snmp_module config = {
1165143611Sphilip	.comment = "This module implements a MIB for the pf packet filter.",
1166143611Sphilip	.init =		pf_init,
1167143611Sphilip	.fini =		pf_fini,
1168143611Sphilip	.tree =		pf_ctree,
1169143611Sphilip	.dump =		pf_dump,
1170143611Sphilip	.tree_size =	pf_CTREE_SIZE,
1171143611Sphilip};
1172