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