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$
27143611Sphilip */
28143611Sphilip
29216294Ssyrinx#include <sys/queue.h>
30143611Sphilip#include <bsnmp/snmpmod.h>
31143611Sphilip
32143611Sphilip#include <net/pfvar.h>
33143611Sphilip#include <sys/ioctl.h>
34143611Sphilip
35143611Sphilip#include <errno.h>
36143611Sphilip#include <fcntl.h>
37143626Sphilip#include <stdint.h>
38143611Sphilip#include <stdio.h>
39143611Sphilip#include <stdlib.h>
40143611Sphilip#include <string.h>
41143611Sphilip#include <syslog.h>
42143611Sphilip#include <unistd.h>
43143611Sphilip
44143611Sphilip#include "pf_oid.h"
45143611Sphilip#include "pf_tree.h"
46143611Sphilip
47143611Sphilipstruct lmodule *module;
48143611Sphilip
49143611Sphilipstatic int dev = -1;
50143611Sphilipstatic int started;
51146531Sphilipstatic uint64_t pf_tick;
52143611Sphilip
53143611Sphilipstatic struct pf_status pfs;
54143611Sphilip
55143611Sphilipenum { IN, OUT };
56143611Sphilipenum { IPV4, IPV6 };
57143611Sphilipenum { PASS, BLOCK };
58143611Sphilip
59143611Sphilip#define PFI_IFTYPE_GROUP	0
60143611Sphilip#define PFI_IFTYPE_INSTANCE	1
61143611Sphilip#define PFI_IFTYPE_DETACHED	2
62143611Sphilip
63143611Sphilipstruct pfi_entry {
64171173Smlaier	struct pfi_kif	pfi;
65143611Sphilip	u_int		index;
66143611Sphilip	TAILQ_ENTRY(pfi_entry) link;
67143611Sphilip};
68143611SphilipTAILQ_HEAD(pfi_table, pfi_entry);
69143611Sphilip
70143611Sphilipstatic struct pfi_table pfi_table;
71143611Sphilipstatic time_t pfi_table_age;
72143611Sphilipstatic int pfi_table_count;
73143611Sphilip
74143611Sphilip#define PFI_TABLE_MAXAGE	5
75143611Sphilip
76143611Sphilipstruct pft_entry {
77143611Sphilip	struct pfr_tstats pft;
78143611Sphilip	u_int		index;
79143611Sphilip	TAILQ_ENTRY(pft_entry) link;
80143611Sphilip};
81143611SphilipTAILQ_HEAD(pft_table, pft_entry);
82143611Sphilip
83143611Sphilipstatic struct pft_table pft_table;
84143611Sphilipstatic time_t pft_table_age;
85143611Sphilipstatic int pft_table_count;
86143611Sphilip
87143611Sphilip#define PFT_TABLE_MAXAGE	5
88143611Sphilip
89205607Ssyrinxstruct pfa_entry {
90205607Ssyrinx	struct pfr_astats pfas;
91205607Ssyrinx	u_int		index;
92205607Ssyrinx	TAILQ_ENTRY(pfa_entry) link;
93205607Ssyrinx};
94205607SsyrinxTAILQ_HEAD(pfa_table, pfa_entry);
95205607Ssyrinx
96205607Ssyrinxstatic struct pfa_table pfa_table;
97205607Ssyrinxstatic time_t pfa_table_age;
98205607Ssyrinxstatic int pfa_table_count;
99205607Ssyrinx
100205607Ssyrinx#define	PFA_TABLE_MAXAGE	5
101205607Ssyrinx
102143611Sphilipstruct pfq_entry {
103143611Sphilip	struct pf_altq	altq;
104143611Sphilip	u_int		index;
105143611Sphilip	TAILQ_ENTRY(pfq_entry) link;
106143611Sphilip};
107143611SphilipTAILQ_HEAD(pfq_table, pfq_entry);
108143611Sphilip
109143611Sphilipstatic struct pfq_table pfq_table;
110143611Sphilipstatic time_t pfq_table_age;
111143611Sphilipstatic int pfq_table_count;
112143611Sphilip
113152970Sphilipstatic int altq_enabled = 0;
114152970Sphilip
115143611Sphilip#define PFQ_TABLE_MAXAGE	5
116143611Sphilip
117205280Ssyrinxstruct pfl_entry {
118205280Ssyrinx	char		name[MAXPATHLEN + PF_RULE_LABEL_SIZE];
119205280Ssyrinx	u_int64_t	evals;
120205280Ssyrinx	u_int64_t	bytes[2];
121205280Ssyrinx	u_int64_t	pkts[2];
122205280Ssyrinx	u_int		index;
123205280Ssyrinx	TAILQ_ENTRY(pfl_entry) link;
124205280Ssyrinx};
125205280SsyrinxTAILQ_HEAD(pfl_table, pfl_entry);
126205280Ssyrinx
127205280Ssyrinxstatic struct pfl_table pfl_table;
128205280Ssyrinxstatic time_t pfl_table_age;
129205280Ssyrinxstatic int pfl_table_count;
130205280Ssyrinx
131205280Ssyrinx#define	PFL_TABLE_MAXAGE	5
132205280Ssyrinx
133143611Sphilip/* Forward declarations */
134143611Sphilipstatic int pfi_refresh(void);
135143611Sphilipstatic int pfq_refresh(void);
136143611Sphilipstatic int pfs_refresh(void);
137143611Sphilipstatic int pft_refresh(void);
138205607Ssyrinxstatic int pfa_refresh(void);
139205280Ssyrinxstatic int pfl_refresh(void);
140143611Sphilipstatic struct pfi_entry * pfi_table_find(u_int idx);
141143611Sphilipstatic struct pfq_entry * pfq_table_find(u_int idx);
142143611Sphilipstatic struct pft_entry * pft_table_find(u_int idx);
143205607Ssyrinxstatic struct pfa_entry * pfa_table_find(u_int idx);
144205280Ssyrinxstatic struct pfl_entry * pfl_table_find(u_int idx);
145143611Sphilip
146152970Sphilipstatic int altq_is_enabled(int pfdevice);
147152970Sphilip
148143611Sphilipint
149143611Sphilippf_status(struct snmp_context __unused *ctx, struct snmp_value *val,
150143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
151143611Sphilip{
152143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
153143611Sphilip	time_t		runtime;
154143611Sphilip	unsigned char	str[128];
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_pfStatusRunning:
165143611Sphilip			    val->v.uint32 = pfs.running;
166143611Sphilip			    break;
167143611Sphilip			case LEAF_pfStatusRuntime:
168143611Sphilip			    runtime = (pfs.since > 0) ?
169143611Sphilip				time(NULL) - pfs.since : 0;
170143611Sphilip			    val->v.uint32 = runtime * 100;
171143611Sphilip			    break;
172143611Sphilip			case LEAF_pfStatusDebug:
173143611Sphilip			    val->v.uint32 = pfs.debug;
174143611Sphilip			    break;
175143611Sphilip			case LEAF_pfStatusHostId:
176143611Sphilip			    sprintf(str, "0x%08x", ntohl(pfs.hostid));
177143611Sphilip			    return (string_get(val, str, strlen(str)));
178143611Sphilip
179143611Sphilip			default:
180143611Sphilip			    return (SNMP_ERR_NOSUCHNAME);
181143611Sphilip		}
182143611Sphilip
183143611Sphilip		return (SNMP_ERR_NOERROR);
184143611Sphilip	}
185143611Sphilip
186143611Sphilip	abort();
187143611Sphilip}
188143611Sphilip
189143611Sphilipint
190143611Sphilippf_counter(struct snmp_context __unused *ctx, struct snmp_value *val,
191143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
192143611Sphilip{
193143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
194143611Sphilip
195143611Sphilip	if (op == SNMP_OP_SET)
196143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
197143611Sphilip
198143611Sphilip	if (op == SNMP_OP_GET) {
199143611Sphilip		if (pfs_refresh() == -1)
200143611Sphilip			return (SNMP_ERR_GENERR);
201143611Sphilip
202143611Sphilip		switch (which) {
203143611Sphilip			case LEAF_pfCounterMatch:
204143611Sphilip				val->v.counter64 = pfs.counters[PFRES_MATCH];
205143611Sphilip				break;
206143611Sphilip			case LEAF_pfCounterBadOffset:
207143611Sphilip				val->v.counter64 = pfs.counters[PFRES_BADOFF];
208143611Sphilip				break;
209143611Sphilip			case LEAF_pfCounterFragment:
210143611Sphilip				val->v.counter64 = pfs.counters[PFRES_FRAG];
211143611Sphilip				break;
212143611Sphilip			case LEAF_pfCounterShort:
213143611Sphilip				val->v.counter64 = pfs.counters[PFRES_SHORT];
214143611Sphilip				break;
215143611Sphilip			case LEAF_pfCounterNormalize:
216143611Sphilip				val->v.counter64 = pfs.counters[PFRES_NORM];
217143611Sphilip				break;
218143611Sphilip			case LEAF_pfCounterMemDrop:
219143611Sphilip				val->v.counter64 = pfs.counters[PFRES_MEMORY];
220143611Sphilip				break;
221143611Sphilip
222143611Sphilip			default:
223143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
224143611Sphilip		}
225143611Sphilip
226143611Sphilip		return (SNMP_ERR_NOERROR);
227143611Sphilip	}
228143611Sphilip
229143611Sphilip	abort();
230143611Sphilip}
231143611Sphilip
232143611Sphilipint
233143611Sphilippf_statetable(struct snmp_context __unused *ctx, struct snmp_value *val,
234143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
235143611Sphilip{
236143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
237143611Sphilip
238143611Sphilip	if (op == SNMP_OP_SET)
239143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
240143611Sphilip
241143611Sphilip	if (op == SNMP_OP_GET) {
242143611Sphilip		if (pfs_refresh() == -1)
243143611Sphilip			return (SNMP_ERR_GENERR);
244143611Sphilip
245143611Sphilip		switch (which) {
246143611Sphilip			case LEAF_pfStateTableCount:
247143611Sphilip				val->v.uint32 = pfs.states;
248143611Sphilip				break;
249143611Sphilip			case LEAF_pfStateTableSearches:
250143611Sphilip				val->v.counter64 =
251143611Sphilip				    pfs.fcounters[FCNT_STATE_SEARCH];
252143611Sphilip				break;
253143611Sphilip			case LEAF_pfStateTableInserts:
254143611Sphilip				val->v.counter64 =
255143611Sphilip				    pfs.fcounters[FCNT_STATE_INSERT];
256143611Sphilip				break;
257143611Sphilip			case LEAF_pfStateTableRemovals:
258143611Sphilip				val->v.counter64 =
259143611Sphilip				    pfs.fcounters[FCNT_STATE_REMOVALS];
260143611Sphilip				break;
261143611Sphilip
262143611Sphilip			default:
263143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
264143611Sphilip		}
265143611Sphilip
266143611Sphilip		return (SNMP_ERR_NOERROR);
267143611Sphilip	}
268143611Sphilip
269143611Sphilip	abort();
270143611Sphilip}
271143611Sphilip
272143611Sphilipint
273143611Sphilippf_srcnodes(struct snmp_context __unused *ctx, struct snmp_value *val,
274143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
275143611Sphilip{
276143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
277143611Sphilip
278143611Sphilip	if (op == SNMP_OP_SET)
279143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
280143611Sphilip
281143611Sphilip	if (op == SNMP_OP_GET) {
282143611Sphilip		if (pfs_refresh() == -1)
283143611Sphilip			return (SNMP_ERR_GENERR);
284143611Sphilip
285143611Sphilip		switch (which) {
286143611Sphilip			case LEAF_pfSrcNodesCount:
287143611Sphilip				val->v.uint32 = pfs.src_nodes;
288143611Sphilip				break;
289143611Sphilip			case LEAF_pfSrcNodesSearches:
290143611Sphilip				val->v.counter64 =
291143611Sphilip				    pfs.scounters[SCNT_SRC_NODE_SEARCH];
292143611Sphilip				break;
293143611Sphilip			case LEAF_pfSrcNodesInserts:
294143611Sphilip				val->v.counter64 =
295143611Sphilip				    pfs.scounters[SCNT_SRC_NODE_INSERT];
296143611Sphilip				break;
297143611Sphilip			case LEAF_pfSrcNodesRemovals:
298143611Sphilip				val->v.counter64 =
299143611Sphilip				    pfs.scounters[SCNT_SRC_NODE_REMOVALS];
300143611Sphilip				break;
301143611Sphilip
302143611Sphilip			default:
303143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
304143611Sphilip		}
305143611Sphilip
306143611Sphilip		return (SNMP_ERR_NOERROR);
307143611Sphilip	}
308143611Sphilip
309143611Sphilip	abort();
310143611Sphilip}
311143611Sphilip
312143611Sphilipint
313143611Sphilippf_limits(struct snmp_context __unused *ctx, struct snmp_value *val,
314143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
315143611Sphilip{
316143611Sphilip	asn_subid_t		which = val->var.subs[sub - 1];
317143611Sphilip	struct pfioc_limit	pl;
318143611Sphilip
319143611Sphilip	if (op == SNMP_OP_SET)
320143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
321143611Sphilip
322143611Sphilip	if (op == SNMP_OP_GET) {
323143611Sphilip		bzero(&pl, sizeof(struct pfioc_limit));
324143611Sphilip
325143611Sphilip		switch (which) {
326143611Sphilip			case LEAF_pfLimitsStates:
327143611Sphilip				pl.index = PF_LIMIT_STATES;
328143611Sphilip				break;
329143611Sphilip			case LEAF_pfLimitsSrcNodes:
330143611Sphilip				pl.index = PF_LIMIT_SRC_NODES;
331143611Sphilip				break;
332143611Sphilip			case LEAF_pfLimitsFrags:
333143611Sphilip				pl.index = PF_LIMIT_FRAGS;
334143611Sphilip				break;
335143611Sphilip
336143611Sphilip			default:
337143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
338143611Sphilip		}
339143611Sphilip
340143611Sphilip		if (ioctl(dev, DIOCGETLIMIT, &pl)) {
341143611Sphilip			syslog(LOG_ERR, "pf_limits(): ioctl(): %s",
342143611Sphilip			    strerror(errno));
343143611Sphilip			return (SNMP_ERR_GENERR);
344143611Sphilip		}
345143611Sphilip
346143611Sphilip		val->v.uint32 = pl.limit;
347143611Sphilip
348143611Sphilip		return (SNMP_ERR_NOERROR);
349143611Sphilip	}
350143611Sphilip
351143611Sphilip	abort();
352143611Sphilip}
353143611Sphilip
354143611Sphilipint
355143611Sphilippf_timeouts(struct snmp_context __unused *ctx, struct snmp_value *val,
356143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
357143611Sphilip{
358143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
359143611Sphilip	struct pfioc_tm	pt;
360143611Sphilip
361143611Sphilip	if (op == SNMP_OP_SET)
362143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
363143611Sphilip
364143611Sphilip	if (op == SNMP_OP_GET) {
365143611Sphilip		bzero(&pt, sizeof(struct pfioc_tm));
366143611Sphilip
367143611Sphilip		switch (which) {
368143611Sphilip			case LEAF_pfTimeoutsTcpFirst:
369143611Sphilip				pt.timeout = PFTM_TCP_FIRST_PACKET;
370143611Sphilip				break;
371143611Sphilip			case LEAF_pfTimeoutsTcpOpening:
372143611Sphilip				pt.timeout = PFTM_TCP_OPENING;
373143611Sphilip				break;
374143611Sphilip			case LEAF_pfTimeoutsTcpEstablished:
375143611Sphilip				pt.timeout = PFTM_TCP_ESTABLISHED;
376143611Sphilip				break;
377143611Sphilip			case LEAF_pfTimeoutsTcpClosing:
378143611Sphilip				pt.timeout = PFTM_TCP_CLOSING;
379143611Sphilip				break;
380143611Sphilip			case LEAF_pfTimeoutsTcpFinWait:
381143611Sphilip				pt.timeout = PFTM_TCP_FIN_WAIT;
382143611Sphilip				break;
383143611Sphilip			case LEAF_pfTimeoutsTcpClosed:
384143611Sphilip				pt.timeout = PFTM_TCP_CLOSED;
385143611Sphilip				break;
386143611Sphilip			case LEAF_pfTimeoutsUdpFirst:
387143611Sphilip				pt.timeout = PFTM_UDP_FIRST_PACKET;
388143611Sphilip				break;
389143611Sphilip			case LEAF_pfTimeoutsUdpSingle:
390143611Sphilip				pt.timeout = PFTM_UDP_SINGLE;
391143611Sphilip				break;
392143611Sphilip			case LEAF_pfTimeoutsUdpMultiple:
393143611Sphilip				pt.timeout = PFTM_UDP_MULTIPLE;
394143611Sphilip				break;
395143611Sphilip			case LEAF_pfTimeoutsIcmpFirst:
396143611Sphilip				pt.timeout = PFTM_ICMP_FIRST_PACKET;
397143611Sphilip				break;
398143611Sphilip			case LEAF_pfTimeoutsIcmpError:
399143611Sphilip				pt.timeout = PFTM_ICMP_ERROR_REPLY;
400143611Sphilip				break;
401143611Sphilip			case LEAF_pfTimeoutsOtherFirst:
402143611Sphilip				pt.timeout = PFTM_OTHER_FIRST_PACKET;
403143611Sphilip				break;
404143611Sphilip			case LEAF_pfTimeoutsOtherSingle:
405143611Sphilip				pt.timeout = PFTM_OTHER_SINGLE;
406143611Sphilip				break;
407143611Sphilip			case LEAF_pfTimeoutsOtherMultiple:
408143611Sphilip				pt.timeout = PFTM_OTHER_MULTIPLE;
409143611Sphilip				break;
410143611Sphilip			case LEAF_pfTimeoutsFragment:
411143611Sphilip				pt.timeout = PFTM_FRAG;
412143611Sphilip				break;
413143611Sphilip			case LEAF_pfTimeoutsInterval:
414143611Sphilip				pt.timeout = PFTM_INTERVAL;
415143611Sphilip				break;
416143611Sphilip			case LEAF_pfTimeoutsAdaptiveStart:
417143611Sphilip				pt.timeout = PFTM_ADAPTIVE_START;
418143611Sphilip				break;
419143611Sphilip			case LEAF_pfTimeoutsAdaptiveEnd:
420143611Sphilip				pt.timeout = PFTM_ADAPTIVE_END;
421143611Sphilip				break;
422143611Sphilip			case LEAF_pfTimeoutsSrcNode:
423143611Sphilip				pt.timeout = PFTM_SRC_NODE;
424143611Sphilip				break;
425143611Sphilip
426143611Sphilip			default:
427143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
428143611Sphilip		}
429143611Sphilip
430143611Sphilip		if (ioctl(dev, DIOCGETTIMEOUT, &pt)) {
431143611Sphilip			syslog(LOG_ERR, "pf_timeouts(): ioctl(): %s",
432143611Sphilip			    strerror(errno));
433143611Sphilip			return (SNMP_ERR_GENERR);
434143611Sphilip		}
435143611Sphilip
436143611Sphilip		val->v.integer = pt.seconds;
437143611Sphilip
438143611Sphilip		return (SNMP_ERR_NOERROR);
439143611Sphilip	}
440143611Sphilip
441143611Sphilip	abort();
442143611Sphilip}
443143611Sphilip
444143611Sphilipint
445143611Sphilippf_logif(struct snmp_context __unused *ctx, struct snmp_value *val,
446143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
447143611Sphilip{
448143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
449143611Sphilip	unsigned char	str[IFNAMSIZ];
450143611Sphilip
451143611Sphilip	if (op == SNMP_OP_SET)
452143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
453143611Sphilip
454143611Sphilip	if (op == SNMP_OP_GET) {
455143611Sphilip		if (pfs_refresh() == -1)
456143611Sphilip			return (SNMP_ERR_GENERR);
457143611Sphilip
458143611Sphilip		switch (which) {
459143611Sphilip	 		case LEAF_pfLogInterfaceName:
460143611Sphilip				strlcpy(str, pfs.ifname, sizeof str);
461143611Sphilip				return (string_get(val, str, strlen(str)));
462143611Sphilip			case LEAF_pfLogInterfaceIp4BytesIn:
463143611Sphilip				val->v.counter64 = pfs.bcounters[IPV4][IN];
464143611Sphilip				break;
465143611Sphilip			case LEAF_pfLogInterfaceIp4BytesOut:
466143611Sphilip				val->v.counter64 = pfs.bcounters[IPV4][OUT];
467143611Sphilip				break;
468143611Sphilip			case LEAF_pfLogInterfaceIp4PktsInPass:
469143611Sphilip				val->v.counter64 =
470143611Sphilip				    pfs.pcounters[IPV4][IN][PF_PASS];
471143611Sphilip				break;
472143611Sphilip			case LEAF_pfLogInterfaceIp4PktsInDrop:
473143611Sphilip				val->v.counter64 =
474143611Sphilip				    pfs.pcounters[IPV4][IN][PF_DROP];
475143611Sphilip				break;
476143611Sphilip			case LEAF_pfLogInterfaceIp4PktsOutPass:
477143611Sphilip				val->v.counter64 =
478143611Sphilip				    pfs.pcounters[IPV4][OUT][PF_PASS];
479143611Sphilip				break;
480143611Sphilip			case LEAF_pfLogInterfaceIp4PktsOutDrop:
481143611Sphilip				val->v.counter64 =
482143611Sphilip				    pfs.pcounters[IPV4][OUT][PF_DROP];
483143611Sphilip				break;
484143611Sphilip			case LEAF_pfLogInterfaceIp6BytesIn:
485143611Sphilip				val->v.counter64 = pfs.bcounters[IPV6][IN];
486143611Sphilip				break;
487143611Sphilip			case LEAF_pfLogInterfaceIp6BytesOut:
488143611Sphilip				val->v.counter64 = pfs.bcounters[IPV6][OUT];
489143611Sphilip				break;
490143611Sphilip			case LEAF_pfLogInterfaceIp6PktsInPass:
491143611Sphilip				val->v.counter64 =
492143611Sphilip				    pfs.pcounters[IPV6][IN][PF_PASS];
493143611Sphilip				break;
494143611Sphilip			case LEAF_pfLogInterfaceIp6PktsInDrop:
495143611Sphilip				val->v.counter64 =
496143611Sphilip				    pfs.pcounters[IPV6][IN][PF_DROP];
497143611Sphilip				break;
498143611Sphilip			case LEAF_pfLogInterfaceIp6PktsOutPass:
499143611Sphilip				val->v.counter64 =
500143611Sphilip				    pfs.pcounters[IPV6][OUT][PF_PASS];
501143611Sphilip				break;
502143611Sphilip			case LEAF_pfLogInterfaceIp6PktsOutDrop:
503143611Sphilip				val->v.counter64 =
504143611Sphilip				    pfs.pcounters[IPV6][OUT][PF_DROP];
505143611Sphilip				break;
506143611Sphilip
507143611Sphilip			default:
508143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
509143611Sphilip		}
510143611Sphilip
511143611Sphilip		return (SNMP_ERR_NOERROR);
512143611Sphilip	}
513143611Sphilip
514143611Sphilip	abort();
515143611Sphilip}
516143611Sphilip
517143611Sphilipint
518143611Sphilippf_interfaces(struct snmp_context __unused *ctx, struct snmp_value *val,
519143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
520143611Sphilip{
521143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
522143611Sphilip
523143611Sphilip	if (op == SNMP_OP_SET)
524143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
525143611Sphilip
526143611Sphilip	if (op == SNMP_OP_GET) {
527143611Sphilip		if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE)
528143611Sphilip			if (pfi_refresh() == -1)
529143611Sphilip			    return (SNMP_ERR_GENERR);
530143611Sphilip
531143611Sphilip		switch (which) {
532143611Sphilip			case LEAF_pfInterfacesIfNumber:
533143611Sphilip				val->v.uint32 = pfi_table_count;
534143611Sphilip				break;
535143611Sphilip
536143611Sphilip			default:
537143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
538143611Sphilip		}
539143611Sphilip
540143611Sphilip		return (SNMP_ERR_NOERROR);
541143611Sphilip	}
542143611Sphilip
543143611Sphilip	abort();
544143611Sphilip}
545143611Sphilip
546143611Sphilipint
547143611Sphilippf_iftable(struct snmp_context __unused *ctx, struct snmp_value *val,
548143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
549143611Sphilip{
550143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
551143611Sphilip	struct pfi_entry *e = NULL;
552143611Sphilip
553205312Ssyrinx	if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE)
554205312Ssyrinx		pfi_refresh();
555205312Ssyrinx
556143611Sphilip	switch (op) {
557143611Sphilip		case SNMP_OP_SET:
558143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
559143611Sphilip		case SNMP_OP_GETNEXT:
560143611Sphilip			if ((e = NEXT_OBJECT_INT(&pfi_table,
561143611Sphilip			    &val->var, sub)) == NULL)
562143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
563143611Sphilip			val->var.len = sub + 1;
564143611Sphilip			val->var.subs[sub] = e->index;
565143611Sphilip			break;
566143611Sphilip		case SNMP_OP_GET:
567143611Sphilip			if (val->var.len - sub != 1)
568143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
569143611Sphilip			if ((e = pfi_table_find(val->var.subs[sub])) == NULL)
570143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
571143611Sphilip			break;
572143611Sphilip
573143611Sphilip		case SNMP_OP_COMMIT:
574143611Sphilip		case SNMP_OP_ROLLBACK:
575143611Sphilip		default:
576143611Sphilip			abort();
577143611Sphilip	}
578143611Sphilip
579143611Sphilip	switch (which) {
580143611Sphilip		case LEAF_pfInterfacesIfDescr:
581171173Smlaier			return (string_get(val, e->pfi.pfik_name, -1));
582143611Sphilip		case LEAF_pfInterfacesIfType:
583143611Sphilip			val->v.integer = PFI_IFTYPE_INSTANCE;
584143611Sphilip			break;
585143611Sphilip		case LEAF_pfInterfacesIfTZero:
586143611Sphilip			val->v.uint32 =
587171173Smlaier			    (time(NULL) - e->pfi.pfik_tzero) * 100;
588143611Sphilip			break;
589143611Sphilip		case LEAF_pfInterfacesIfRefsState:
590171173Smlaier			val->v.uint32 = e->pfi.pfik_states;
591143611Sphilip			break;
592143611Sphilip		case LEAF_pfInterfacesIfRefsRule:
593171173Smlaier			val->v.uint32 = e->pfi.pfik_rules;
594143611Sphilip			break;
595143611Sphilip		case LEAF_pfInterfacesIf4BytesInPass:
596143611Sphilip			val->v.counter64 =
597171173Smlaier			    e->pfi.pfik_bytes[IPV4][IN][PASS];
598143611Sphilip			break;
599143611Sphilip		case LEAF_pfInterfacesIf4BytesInBlock:
600143611Sphilip			val->v.counter64 =
601171173Smlaier			    e->pfi.pfik_bytes[IPV4][IN][BLOCK];
602143611Sphilip			break;
603143611Sphilip		case LEAF_pfInterfacesIf4BytesOutPass:
604143611Sphilip			val->v.counter64 =
605171173Smlaier			    e->pfi.pfik_bytes[IPV4][OUT][PASS];
606143611Sphilip			break;
607143611Sphilip		case LEAF_pfInterfacesIf4BytesOutBlock:
608143611Sphilip			val->v.counter64 =
609171173Smlaier			    e->pfi.pfik_bytes[IPV4][OUT][BLOCK];
610143611Sphilip			break;
611143611Sphilip		case LEAF_pfInterfacesIf4PktsInPass:
612143611Sphilip			val->v.counter64 =
613171173Smlaier			    e->pfi.pfik_packets[IPV4][IN][PASS];
614143611Sphilip			break;
615143611Sphilip		case LEAF_pfInterfacesIf4PktsInBlock:
616143611Sphilip			val->v.counter64 =
617171173Smlaier			    e->pfi.pfik_packets[IPV4][IN][BLOCK];
618143611Sphilip			break;
619143611Sphilip		case LEAF_pfInterfacesIf4PktsOutPass:
620143611Sphilip			val->v.counter64 =
621171173Smlaier			    e->pfi.pfik_packets[IPV4][OUT][PASS];
622143611Sphilip			break;
623143611Sphilip		case LEAF_pfInterfacesIf4PktsOutBlock:
624143611Sphilip			val->v.counter64 =
625171173Smlaier			    e->pfi.pfik_packets[IPV4][OUT][BLOCK];
626143611Sphilip			break;
627143611Sphilip		case LEAF_pfInterfacesIf6BytesInPass:
628143611Sphilip			val->v.counter64 =
629171173Smlaier			    e->pfi.pfik_bytes[IPV6][IN][PASS];
630143611Sphilip			break;
631143611Sphilip		case LEAF_pfInterfacesIf6BytesInBlock:
632143611Sphilip			val->v.counter64 =
633171173Smlaier			    e->pfi.pfik_bytes[IPV6][IN][BLOCK];
634143611Sphilip			break;
635143611Sphilip		case LEAF_pfInterfacesIf6BytesOutPass:
636143611Sphilip			val->v.counter64 =
637171173Smlaier			    e->pfi.pfik_bytes[IPV6][OUT][PASS];
638143611Sphilip			break;
639143611Sphilip		case LEAF_pfInterfacesIf6BytesOutBlock:
640143611Sphilip			val->v.counter64 =
641171173Smlaier			    e->pfi.pfik_bytes[IPV6][OUT][BLOCK];
642143611Sphilip			break;
643143611Sphilip		case LEAF_pfInterfacesIf6PktsInPass:
644143611Sphilip			val->v.counter64 =
645171173Smlaier			    e->pfi.pfik_packets[IPV6][IN][PASS];
646143611Sphilip			break;
647143611Sphilip		case LEAF_pfInterfacesIf6PktsInBlock:
648143611Sphilip			val->v.counter64 =
649171173Smlaier			    e->pfi.pfik_packets[IPV6][IN][BLOCK];
650143611Sphilip			break;
651143611Sphilip		case LEAF_pfInterfacesIf6PktsOutPass:
652143611Sphilip			val->v.counter64 =
653171173Smlaier			    e->pfi.pfik_packets[IPV6][OUT][PASS];
654143611Sphilip			break;
655143611Sphilip		case LEAF_pfInterfacesIf6PktsOutBlock:
656143611Sphilip			val->v.counter64 =
657171173Smlaier			    e->pfi.pfik_packets[IPV6][OUT][BLOCK];
658143611Sphilip			break;
659143611Sphilip
660143611Sphilip		default:
661143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
662143611Sphilip	}
663143611Sphilip
664143611Sphilip	return (SNMP_ERR_NOERROR);
665143611Sphilip}
666143611Sphilip
667143611Sphilipint
668143611Sphilippf_tables(struct snmp_context __unused *ctx, struct snmp_value *val,
669143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
670143611Sphilip{
671143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
672143611Sphilip
673143611Sphilip	if (op == SNMP_OP_SET)
674143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
675143611Sphilip
676143611Sphilip	if (op == SNMP_OP_GET) {
677143611Sphilip		if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
678143611Sphilip			if (pft_refresh() == -1)
679143611Sphilip			    return (SNMP_ERR_GENERR);
680143611Sphilip
681143611Sphilip		switch (which) {
682143611Sphilip			case LEAF_pfTablesTblNumber:
683143611Sphilip				val->v.uint32 = pft_table_count;
684143611Sphilip				break;
685143611Sphilip
686143611Sphilip			default:
687143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
688143611Sphilip		}
689143611Sphilip
690143611Sphilip		return (SNMP_ERR_NOERROR);
691143611Sphilip	}
692143611Sphilip
693143611Sphilip	abort();
694143611Sphilip}
695143611Sphilip
696143611Sphilipint
697143611Sphilippf_tbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
698143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
699143611Sphilip{
700143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
701143611Sphilip	struct pft_entry *e = NULL;
702143611Sphilip
703205312Ssyrinx	if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
704205312Ssyrinx		pft_refresh();
705205312Ssyrinx
706143611Sphilip	switch (op) {
707143611Sphilip		case SNMP_OP_SET:
708143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
709143611Sphilip		case SNMP_OP_GETNEXT:
710143611Sphilip			if ((e = NEXT_OBJECT_INT(&pft_table,
711143611Sphilip			    &val->var, sub)) == NULL)
712143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
713143611Sphilip			val->var.len = sub + 1;
714143611Sphilip			val->var.subs[sub] = e->index;
715143611Sphilip			break;
716143611Sphilip		case SNMP_OP_GET:
717143611Sphilip			if (val->var.len - sub != 1)
718143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
719143611Sphilip			if ((e = pft_table_find(val->var.subs[sub])) == NULL)
720143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
721143611Sphilip			break;
722143611Sphilip
723143611Sphilip		case SNMP_OP_COMMIT:
724143611Sphilip		case SNMP_OP_ROLLBACK:
725143611Sphilip		default:
726143611Sphilip			abort();
727143611Sphilip	}
728143611Sphilip
729143611Sphilip	switch (which) {
730143611Sphilip		case LEAF_pfTablesTblDescr:
731143611Sphilip			return (string_get(val, e->pft.pfrts_name, -1));
732143611Sphilip		case LEAF_pfTablesTblCount:
733143611Sphilip			val->v.integer = e->pft.pfrts_cnt;
734143611Sphilip			break;
735143611Sphilip		case LEAF_pfTablesTblTZero:
736143611Sphilip			val->v.uint32 =
737143611Sphilip			    (time(NULL) - e->pft.pfrts_tzero) * 100;
738143611Sphilip			break;
739143611Sphilip		case LEAF_pfTablesTblRefsAnchor:
740143611Sphilip			val->v.integer =
741143611Sphilip			    e->pft.pfrts_refcnt[PFR_REFCNT_ANCHOR];
742143611Sphilip			break;
743143611Sphilip		case LEAF_pfTablesTblRefsRule:
744143611Sphilip			val->v.integer =
745143611Sphilip			    e->pft.pfrts_refcnt[PFR_REFCNT_RULE];
746143611Sphilip			break;
747143611Sphilip		case LEAF_pfTablesTblEvalMatch:
748143611Sphilip			val->v.counter64 = e->pft.pfrts_match;
749143611Sphilip			break;
750143611Sphilip		case LEAF_pfTablesTblEvalNoMatch:
751143611Sphilip			val->v.counter64 = e->pft.pfrts_nomatch;
752143611Sphilip			break;
753143611Sphilip		case LEAF_pfTablesTblBytesInPass:
754143611Sphilip			val->v.counter64 =
755143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_PASS];
756143611Sphilip			break;
757143611Sphilip		case LEAF_pfTablesTblBytesInBlock:
758143611Sphilip			val->v.counter64 =
759143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_BLOCK];
760143611Sphilip			break;
761143611Sphilip		case LEAF_pfTablesTblBytesInXPass:
762143611Sphilip			val->v.counter64 =
763143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_XPASS];
764143611Sphilip			break;
765143611Sphilip		case LEAF_pfTablesTblBytesOutPass:
766143611Sphilip			val->v.counter64 =
767143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_PASS];
768143611Sphilip			break;
769143611Sphilip		case LEAF_pfTablesTblBytesOutBlock:
770143611Sphilip			val->v.counter64 =
771143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_BLOCK];
772143611Sphilip			break;
773143611Sphilip		case LEAF_pfTablesTblBytesOutXPass:
774143611Sphilip			val->v.counter64 =
775143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_XPASS];
776143611Sphilip			break;
777143611Sphilip		case LEAF_pfTablesTblPktsInPass:
778143611Sphilip			val->v.counter64 =
779143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_PASS];
780143611Sphilip			break;
781143611Sphilip		case LEAF_pfTablesTblPktsInBlock:
782143611Sphilip			val->v.counter64 =
783143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_BLOCK];
784143611Sphilip			break;
785143611Sphilip		case LEAF_pfTablesTblPktsInXPass:
786143611Sphilip			val->v.counter64 =
787143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_XPASS];
788143611Sphilip			break;
789143611Sphilip		case LEAF_pfTablesTblPktsOutPass:
790143611Sphilip			val->v.counter64 =
791143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_PASS];
792143611Sphilip			break;
793143611Sphilip		case LEAF_pfTablesTblPktsOutBlock:
794143611Sphilip			val->v.counter64 =
795143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_BLOCK];
796143611Sphilip			break;
797143611Sphilip		case LEAF_pfTablesTblPktsOutXPass:
798143611Sphilip			val->v.counter64 =
799143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_XPASS];
800143611Sphilip			break;
801143611Sphilip
802143611Sphilip		default:
803143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
804143611Sphilip	}
805143611Sphilip
806143611Sphilip	return (SNMP_ERR_NOERROR);
807143611Sphilip}
808143611Sphilip
809143611Sphilipint
810143611Sphilippf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val,
811143611Sphilip	u_int __unused sub, u_int __unused vindex, enum snmp_op __unused op)
812143611Sphilip{
813205607Ssyrinx	asn_subid_t	which = val->var.subs[sub - 1];
814205607Ssyrinx	struct pfa_entry *e = NULL;
815205607Ssyrinx
816205607Ssyrinx	if ((time(NULL) - pfa_table_age) > PFA_TABLE_MAXAGE)
817205607Ssyrinx		pfa_refresh();
818205607Ssyrinx
819205607Ssyrinx	switch (op) {
820205607Ssyrinx		case SNMP_OP_SET:
821205607Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
822205607Ssyrinx		case SNMP_OP_GETNEXT:
823205607Ssyrinx			if ((e = NEXT_OBJECT_INT(&pfa_table,
824205607Ssyrinx			    &val->var, sub)) == NULL)
825205607Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
826205607Ssyrinx			val->var.len = sub + 1;
827205607Ssyrinx			val->var.subs[sub] = e->index;
828205607Ssyrinx			break;
829205607Ssyrinx		case SNMP_OP_GET:
830205607Ssyrinx			if (val->var.len - sub != 1)
831205607Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
832205607Ssyrinx			if ((e = pfa_table_find(val->var.subs[sub])) == NULL)
833205607Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
834205607Ssyrinx			break;
835205607Ssyrinx
836205607Ssyrinx		case SNMP_OP_COMMIT:
837205607Ssyrinx		case SNMP_OP_ROLLBACK:
838205607Ssyrinx		default:
839205607Ssyrinx			abort();
840205607Ssyrinx	}
841205607Ssyrinx
842205607Ssyrinx	switch (which) {
843205607Ssyrinx		case LEAF_pfTablesAddrNetType:
844205607Ssyrinx			if (e->pfas.pfras_a.pfra_af == AF_INET)
845205607Ssyrinx				val->v.integer = pfTablesAddrNetType_ipv4;
846205607Ssyrinx			else if (e->pfas.pfras_a.pfra_af == AF_INET6)
847205607Ssyrinx				val->v.integer = pfTablesAddrNetType_ipv6;
848205607Ssyrinx			else
849205607Ssyrinx				return (SNMP_ERR_GENERR);
850205607Ssyrinx			break;
851205607Ssyrinx		case LEAF_pfTablesAddrNet:
852205607Ssyrinx			if (e->pfas.pfras_a.pfra_af == AF_INET) {
853205607Ssyrinx				return (string_get(val,
854205607Ssyrinx				    (u_char *)&e->pfas.pfras_a.pfra_ip4addr, 4));
855205607Ssyrinx			} else if (e->pfas.pfras_a.pfra_af == AF_INET6)
856205607Ssyrinx				return (string_get(val,
857205607Ssyrinx				    (u_char *)&e->pfas.pfras_a.pfra_ip6addr, 16));
858205607Ssyrinx			else
859205607Ssyrinx				return (SNMP_ERR_GENERR);
860205607Ssyrinx			break;
861205607Ssyrinx		case LEAF_pfTablesAddrPrefix:
862205607Ssyrinx			val->v.integer = (int32_t) e->pfas.pfras_a.pfra_net;
863205607Ssyrinx			break;
864205607Ssyrinx		case LEAF_pfTablesAddrTZero:
865205607Ssyrinx			val->v.uint32 =
866205607Ssyrinx			    (time(NULL) - e->pfas.pfras_tzero) * 100;
867205607Ssyrinx			break;
868205607Ssyrinx		case LEAF_pfTablesAddrBytesInPass:
869205607Ssyrinx			val->v.counter64 =
870205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_IN][PFR_OP_PASS];
871205607Ssyrinx			break;
872205607Ssyrinx		case LEAF_pfTablesAddrBytesInBlock:
873205607Ssyrinx			val->v.counter64 =
874205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_IN][PFR_OP_BLOCK];
875205607Ssyrinx			break;
876205607Ssyrinx		case LEAF_pfTablesAddrBytesOutPass:
877205607Ssyrinx			val->v.counter64 =
878205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_OUT][PFR_OP_PASS];
879205607Ssyrinx			break;
880205607Ssyrinx		case LEAF_pfTablesAddrBytesOutBlock:
881205607Ssyrinx			val->v.counter64 =
882205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_OUT][PFR_OP_BLOCK];
883205607Ssyrinx			break;
884205607Ssyrinx		case LEAF_pfTablesAddrPktsInPass:
885205607Ssyrinx			val->v.counter64 =
886205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_IN][PFR_OP_PASS];
887205607Ssyrinx			break;
888205607Ssyrinx		case LEAF_pfTablesAddrPktsInBlock:
889205607Ssyrinx			val->v.counter64 =
890205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_IN][PFR_OP_BLOCK];
891205607Ssyrinx			break;
892205607Ssyrinx		case LEAF_pfTablesAddrPktsOutPass:
893205607Ssyrinx			val->v.counter64 =
894205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_OUT][PFR_OP_PASS];
895205607Ssyrinx			break;
896205607Ssyrinx		case LEAF_pfTablesAddrPktsOutBlock:
897205607Ssyrinx			val->v.counter64 =
898205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_OUT][PFR_OP_BLOCK];
899205607Ssyrinx			break;
900205607Ssyrinx		default:
901205607Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
902205607Ssyrinx	}
903205607Ssyrinx
904205607Ssyrinx	return (SNMP_ERR_NOERROR);
905143611Sphilip}
906143611Sphilip
907143611Sphilipint
908143611Sphilippf_altq(struct snmp_context __unused *ctx, struct snmp_value *val,
909143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
910143611Sphilip{
911143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
912143611Sphilip
913205607Ssyrinx	if (!altq_enabled)
914205607Ssyrinx	   return (SNMP_ERR_NOSUCHNAME);
915152970Sphilip
916143611Sphilip	if (op == SNMP_OP_SET)
917143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
918143611Sphilip
919143611Sphilip	if (op == SNMP_OP_GET) {
920143611Sphilip		if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
921143611Sphilip			if (pfq_refresh() == -1)
922143611Sphilip			    return (SNMP_ERR_GENERR);
923143611Sphilip
924143611Sphilip		switch (which) {
925143611Sphilip			case LEAF_pfAltqQueueNumber:
926143611Sphilip				val->v.uint32 = pfq_table_count;
927143611Sphilip				break;
928143611Sphilip
929143611Sphilip			default:
930143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
931143611Sphilip		}
932143611Sphilip
933143611Sphilip		return (SNMP_ERR_NOERROR);
934143611Sphilip	}
935143611Sphilip
936143611Sphilip	abort();
937143611Sphilip	return (SNMP_ERR_GENERR);
938143611Sphilip}
939143611Sphilip
940143611Sphilipint
941143611Sphilippf_altqq(struct snmp_context __unused *ctx, struct snmp_value *val,
942143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
943143611Sphilip{
944143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
945143611Sphilip	struct pfq_entry *e = NULL;
946143611Sphilip
947205607Ssyrinx	if (!altq_enabled)
948205607Ssyrinx	   return (SNMP_ERR_NOSUCHNAME);
949152970Sphilip
950205312Ssyrinx	if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
951205312Ssyrinx		pfq_refresh();
952205312Ssyrinx
953143611Sphilip	switch (op) {
954143611Sphilip		case SNMP_OP_SET:
955143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
956143611Sphilip		case SNMP_OP_GETNEXT:
957143611Sphilip			if ((e = NEXT_OBJECT_INT(&pfq_table,
958143611Sphilip			    &val->var, sub)) == NULL)
959143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
960143611Sphilip			val->var.len = sub + 1;
961143611Sphilip			val->var.subs[sub] = e->index;
962143611Sphilip			break;
963143611Sphilip		case SNMP_OP_GET:
964143611Sphilip			if (val->var.len - sub != 1)
965143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
966143611Sphilip			if ((e = pfq_table_find(val->var.subs[sub])) == NULL)
967143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
968143611Sphilip			break;
969143611Sphilip
970143611Sphilip		case SNMP_OP_COMMIT:
971143611Sphilip		case SNMP_OP_ROLLBACK:
972143611Sphilip		default:
973143611Sphilip			abort();
974143611Sphilip	}
975143611Sphilip
976143611Sphilip	switch (which) {
977143611Sphilip		case LEAF_pfAltqQueueDescr:
978143611Sphilip			return (string_get(val, e->altq.qname, -1));
979143611Sphilip		case LEAF_pfAltqQueueParent:
980143611Sphilip			return (string_get(val, e->altq.parent, -1));
981143611Sphilip		case LEAF_pfAltqQueueScheduler:
982143611Sphilip			val->v.integer = e->altq.scheduler;
983143611Sphilip			break;
984143611Sphilip		case LEAF_pfAltqQueueBandwidth:
985143611Sphilip			val->v.uint32 = e->altq.bandwidth;
986143611Sphilip			break;
987143611Sphilip		case LEAF_pfAltqQueuePriority:
988143611Sphilip			val->v.integer = e->altq.priority;
989143611Sphilip			break;
990143611Sphilip		case LEAF_pfAltqQueueLimit:
991143611Sphilip			val->v.integer = e->altq.qlimit;
992143611Sphilip			break;
993143611Sphilip
994143611Sphilip		default:
995143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
996143611Sphilip	}
997143611Sphilip
998143611Sphilip	return (SNMP_ERR_NOERROR);
999205280Ssyrinx}
1000143611Sphilip
1001205280Ssyrinxint
1002205280Ssyrinxpf_labels(struct snmp_context __unused *ctx, struct snmp_value *val,
1003205280Ssyrinx	u_int sub, u_int __unused vindex, enum snmp_op op)
1004205280Ssyrinx{
1005205280Ssyrinx	asn_subid_t	which = val->var.subs[sub - 1];
1006205280Ssyrinx
1007205280Ssyrinx	if (op == SNMP_OP_SET)
1008205280Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
1009205280Ssyrinx
1010205280Ssyrinx	if (op == SNMP_OP_GET) {
1011205280Ssyrinx		if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
1012205280Ssyrinx			if (pfl_refresh() == -1)
1013205280Ssyrinx				return (SNMP_ERR_GENERR);
1014205280Ssyrinx
1015205280Ssyrinx		switch (which) {
1016205280Ssyrinx			case LEAF_pfLabelsLblNumber:
1017205280Ssyrinx				val->v.uint32 = pfl_table_count;
1018205280Ssyrinx				break;
1019205280Ssyrinx
1020205280Ssyrinx			default:
1021205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1022205280Ssyrinx		}
1023205280Ssyrinx
1024205280Ssyrinx		return (SNMP_ERR_NOERROR);
1025205280Ssyrinx	}
1026205280Ssyrinx
1027205280Ssyrinx	abort();
1028205280Ssyrinx	return (SNMP_ERR_GENERR);
1029205280Ssyrinx}
1030205280Ssyrinx
1031205280Ssyrinxint
1032205280Ssyrinxpf_lbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
1033205280Ssyrinx	u_int sub, u_int __unused vindex, enum snmp_op op)
1034205280Ssyrinx{
1035205280Ssyrinx	asn_subid_t	which = val->var.subs[sub - 1];
1036205280Ssyrinx	struct pfl_entry *e = NULL;
1037205280Ssyrinx
1038205312Ssyrinx	if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
1039205312Ssyrinx		pfl_refresh();
1040205312Ssyrinx
1041205280Ssyrinx	switch (op) {
1042205280Ssyrinx		case SNMP_OP_SET:
1043205280Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
1044205280Ssyrinx		case SNMP_OP_GETNEXT:
1045205280Ssyrinx			if ((e = NEXT_OBJECT_INT(&pfl_table,
1046205280Ssyrinx			    &val->var, sub)) == NULL)
1047205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1048205280Ssyrinx			val->var.len = sub + 1;
1049205280Ssyrinx			val->var.subs[sub] = e->index;
1050205280Ssyrinx			break;
1051205280Ssyrinx		case SNMP_OP_GET:
1052205280Ssyrinx			if (val->var.len - sub != 1)
1053205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1054205280Ssyrinx			if ((e = pfl_table_find(val->var.subs[sub])) == NULL)
1055205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1056205280Ssyrinx			break;
1057205280Ssyrinx
1058205280Ssyrinx		case SNMP_OP_COMMIT:
1059205280Ssyrinx		case SNMP_OP_ROLLBACK:
1060205280Ssyrinx		default:
1061205280Ssyrinx			abort();
1062205280Ssyrinx	}
1063205280Ssyrinx
1064205280Ssyrinx	switch (which) {
1065205280Ssyrinx		case LEAF_pfLabelsLblName:
1066205280Ssyrinx			return (string_get(val, e->name, -1));
1067205280Ssyrinx		case LEAF_pfLabelsLblEvals:
1068205280Ssyrinx			val->v.counter64 = e->evals;
1069205280Ssyrinx			break;
1070205280Ssyrinx		case LEAF_pfLabelsLblBytesIn:
1071205280Ssyrinx			val->v.counter64 = e->bytes[IN];
1072205280Ssyrinx			break;
1073205280Ssyrinx		case LEAF_pfLabelsLblBytesOut:
1074205280Ssyrinx			val->v.counter64 = e->bytes[OUT];
1075205280Ssyrinx			break;
1076205280Ssyrinx		case LEAF_pfLabelsLblPktsIn:
1077205280Ssyrinx			val->v.counter64 = e->pkts[IN];
1078205280Ssyrinx			break;
1079205280Ssyrinx		case LEAF_pfLabelsLblPktsOut:
1080205280Ssyrinx			val->v.counter64 = e->pkts[OUT];
1081205280Ssyrinx			break;
1082205280Ssyrinx		default:
1083205280Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1084205280Ssyrinx	}
1085205280Ssyrinx
1086205280Ssyrinx	return (SNMP_ERR_NOERROR);
1087205280Ssyrinx}
1088205280Ssyrinx
1089143611Sphilipstatic struct pfi_entry *
1090143611Sphilippfi_table_find(u_int idx)
1091143611Sphilip{
1092143611Sphilip	struct pfi_entry *e;
1093143611Sphilip
1094143611Sphilip	TAILQ_FOREACH(e, &pfi_table, link)
1095143611Sphilip		if (e->index == idx)
1096143611Sphilip			return (e);
1097143611Sphilip	return (NULL);
1098143611Sphilip}
1099143611Sphilip
1100143611Sphilipstatic struct pfq_entry *
1101143611Sphilippfq_table_find(u_int idx)
1102143611Sphilip{
1103143611Sphilip	struct pfq_entry *e;
1104205280Ssyrinx
1105143611Sphilip	TAILQ_FOREACH(e, &pfq_table, link)
1106143611Sphilip		if (e->index == idx)
1107143611Sphilip			return (e);
1108143611Sphilip	return (NULL);
1109143611Sphilip}
1110143611Sphilip
1111143611Sphilipstatic struct pft_entry *
1112143611Sphilippft_table_find(u_int idx)
1113143611Sphilip{
1114143611Sphilip	struct pft_entry *e;
1115143611Sphilip
1116143611Sphilip	TAILQ_FOREACH(e, &pft_table, link)
1117143611Sphilip		if (e->index == idx)
1118143611Sphilip			return (e);
1119143611Sphilip	return (NULL);
1120143611Sphilip}
1121143611Sphilip
1122205607Ssyrinxstatic struct pfa_entry *
1123205607Ssyrinxpfa_table_find(u_int idx)
1124205607Ssyrinx{
1125205607Ssyrinx	struct pfa_entry *e;
1126205607Ssyrinx
1127205607Ssyrinx	TAILQ_FOREACH(e, &pfa_table, link)
1128205607Ssyrinx		if (e->index == idx)
1129205607Ssyrinx			return (e);
1130205607Ssyrinx	return (NULL);
1131205607Ssyrinx}
1132205607Ssyrinx
1133205280Ssyrinxstatic struct pfl_entry *
1134205280Ssyrinxpfl_table_find(u_int idx)
1135205280Ssyrinx{
1136205280Ssyrinx	struct pfl_entry *e;
1137205280Ssyrinx
1138205280Ssyrinx	TAILQ_FOREACH(e, &pfl_table, link)
1139205280Ssyrinx		if (e->index == idx)
1140205280Ssyrinx			return (e);
1141205280Ssyrinx
1142205280Ssyrinx	return (NULL);
1143205280Ssyrinx}
1144205280Ssyrinx
1145143611Sphilipstatic int
1146143611Sphilippfi_refresh(void)
1147143611Sphilip{
1148143611Sphilip	struct pfioc_iface io;
1149171173Smlaier	struct pfi_kif *p = NULL;
1150143611Sphilip	struct pfi_entry *e;
1151143611Sphilip	int i, numifs = 1;
1152143611Sphilip
1153143611Sphilip	if (started && this_tick <= pf_tick)
1154143611Sphilip		return (0);
1155143611Sphilip
1156143611Sphilip	while (!TAILQ_EMPTY(&pfi_table)) {
1157143611Sphilip		e = TAILQ_FIRST(&pfi_table);
1158143611Sphilip		TAILQ_REMOVE(&pfi_table, e, link);
1159143611Sphilip		free(e);
1160143611Sphilip	}
1161143611Sphilip
1162143611Sphilip	bzero(&io, sizeof(io));
1163171173Smlaier	io.pfiio_esize = sizeof(struct pfi_kif);
1164143611Sphilip
1165143611Sphilip	for (;;) {
1166171173Smlaier		p = reallocf(p, numifs * sizeof(struct pfi_kif));
1167149571Sphilip		if (p == NULL) {
1168149571Sphilip			syslog(LOG_ERR, "pfi_refresh(): reallocf() numifs=%d: %s",
1169149571Sphilip			    numifs, strerror(errno));
1170149571Sphilip			goto err2;
1171149571Sphilip		}
1172143611Sphilip		io.pfiio_size = numifs;
1173143611Sphilip		io.pfiio_buffer = p;
1174143611Sphilip
1175143611Sphilip		if (ioctl(dev, DIOCIGETIFACES, &io)) {
1176143611Sphilip			syslog(LOG_ERR, "pfi_refresh(): ioctl(): %s",
1177143611Sphilip			    strerror(errno));
1178149571Sphilip			goto err2;
1179143611Sphilip		}
1180143611Sphilip
1181143611Sphilip		if (numifs >= io.pfiio_size)
1182143611Sphilip			break;
1183143611Sphilip
1184143611Sphilip		numifs = io.pfiio_size;
1185143611Sphilip	}
1186143611Sphilip
1187143611Sphilip	for (i = 0; i < numifs; i++) {
1188143611Sphilip		e = malloc(sizeof(struct pfi_entry));
1189149571Sphilip		if (e == NULL)
1190149571Sphilip			goto err1;
1191143611Sphilip		e->index = i + 1;
1192171173Smlaier		memcpy(&e->pfi, p+i, sizeof(struct pfi_kif));
1193143611Sphilip		TAILQ_INSERT_TAIL(&pfi_table, e, link);
1194143611Sphilip	}
1195143611Sphilip
1196143611Sphilip	pfi_table_age = time(NULL);
1197143611Sphilip	pfi_table_count = numifs;
1198143611Sphilip	pf_tick = this_tick;
1199143611Sphilip
1200143611Sphilip	free(p);
1201143611Sphilip	return (0);
1202149571Sphilip
1203149571Sphiliperr1:
1204149571Sphilip	while (!TAILQ_EMPTY(&pfi_table)) {
1205149571Sphilip		e = TAILQ_FIRST(&pfi_table);
1206149571Sphilip		TAILQ_REMOVE(&pfi_table, e, link);
1207149571Sphilip		free(e);
1208149571Sphilip	}
1209149571Sphiliperr2:
1210149571Sphilip	free(p);
1211149571Sphilip	return(-1);
1212143611Sphilip}
1213143611Sphilip
1214143611Sphilipstatic int
1215143611Sphilippfq_refresh(void)
1216143611Sphilip{
1217143611Sphilip	struct pfioc_altq pa;
1218143611Sphilip	struct pfq_entry *e;
1219143611Sphilip	int i, numqs, ticket;
1220143611Sphilip
1221143611Sphilip	if (started && this_tick <= pf_tick)
1222143611Sphilip		return (0);
1223143611Sphilip
1224143611Sphilip	while (!TAILQ_EMPTY(&pfq_table)) {
1225143611Sphilip		e = TAILQ_FIRST(&pfq_table);
1226143611Sphilip		TAILQ_REMOVE(&pfq_table, e, link);
1227143611Sphilip		free(e);
1228143611Sphilip	}
1229143611Sphilip
1230143611Sphilip	bzero(&pa, sizeof(pa));
1231143611Sphilip
1232143611Sphilip	if (ioctl(dev, DIOCGETALTQS, &pa)) {
1233143611Sphilip		syslog(LOG_ERR, "pfq_refresh: ioctl(DIOCGETALTQS): %s",
1234143611Sphilip		    strerror(errno));
1235143611Sphilip		return (-1);
1236143611Sphilip	}
1237143611Sphilip
1238143611Sphilip	numqs = pa.nr;
1239143611Sphilip	ticket = pa.ticket;
1240143611Sphilip
1241143611Sphilip	for (i = 0; i < numqs; i++) {
1242143611Sphilip		e = malloc(sizeof(struct pfq_entry));
1243149571Sphilip		if (e == NULL) {
1244149571Sphilip			syslog(LOG_ERR, "pfq_refresh(): "
1245149571Sphilip			    "malloc(): %s",
1246149571Sphilip			    strerror(errno));
1247149571Sphilip			goto err;
1248149571Sphilip		}
1249143611Sphilip		pa.ticket = ticket;
1250143611Sphilip		pa.nr = i;
1251143611Sphilip
1252143611Sphilip		if (ioctl(dev, DIOCGETALTQ, &pa)) {
1253143611Sphilip			syslog(LOG_ERR, "pfq_refresh(): "
1254143611Sphilip			    "ioctl(DIOCGETALTQ): %s",
1255143611Sphilip			    strerror(errno));
1256149571Sphilip			goto err;
1257143611Sphilip		}
1258143611Sphilip
1259143611Sphilip		if (pa.altq.qid > 0) {
1260143611Sphilip			memcpy(&e->altq, &pa.altq, sizeof(struct pf_altq));
1261143611Sphilip			e->index = pa.altq.qid;
1262143611Sphilip			pfq_table_count = i;
1263179476Sphilip			INSERT_OBJECT_INT_LINK_INDEX(e, &pfq_table, link, index);
1264143611Sphilip		}
1265143611Sphilip	}
1266143611Sphilip
1267143611Sphilip	pfq_table_age = time(NULL);
1268143611Sphilip	pf_tick = this_tick;
1269143611Sphilip
1270143611Sphilip	return (0);
1271149571Sphiliperr:
1272149571Sphilip	free(e);
1273149571Sphilip	while (!TAILQ_EMPTY(&pfq_table)) {
1274149571Sphilip		e = TAILQ_FIRST(&pfq_table);
1275149571Sphilip		TAILQ_REMOVE(&pfq_table, e, link);
1276149571Sphilip		free(e);
1277149571Sphilip	}
1278149571Sphilip	return(-1);
1279143611Sphilip}
1280143611Sphilip
1281143611Sphilipstatic int
1282143611Sphilippfs_refresh(void)
1283143611Sphilip{
1284143611Sphilip	if (started && this_tick <= pf_tick)
1285143611Sphilip		return (0);
1286143611Sphilip
1287143611Sphilip	bzero(&pfs, sizeof(struct pf_status));
1288143611Sphilip
1289143611Sphilip	if (ioctl(dev, DIOCGETSTATUS, &pfs)) {
1290143611Sphilip		syslog(LOG_ERR, "pfs_refresh(): ioctl(): %s",
1291143611Sphilip		    strerror(errno));
1292143611Sphilip		return (-1);
1293143611Sphilip	}
1294143611Sphilip
1295143611Sphilip	pf_tick = this_tick;
1296143611Sphilip	return (0);
1297143611Sphilip}
1298143611Sphilip
1299143611Sphilipstatic int
1300143611Sphilippft_refresh(void)
1301143611Sphilip{
1302143611Sphilip	struct pfioc_table io;
1303149571Sphilip	struct pfr_tstats *t = NULL;
1304143611Sphilip	struct pft_entry *e;
1305143611Sphilip	int i, numtbls = 1;
1306143611Sphilip
1307143611Sphilip	if (started && this_tick <= pf_tick)
1308143611Sphilip		return (0);
1309143611Sphilip
1310143611Sphilip	while (!TAILQ_EMPTY(&pft_table)) {
1311143611Sphilip		e = TAILQ_FIRST(&pft_table);
1312143611Sphilip		TAILQ_REMOVE(&pft_table, e, link);
1313143611Sphilip		free(e);
1314143611Sphilip	}
1315143611Sphilip
1316143611Sphilip	bzero(&io, sizeof(io));
1317143611Sphilip	io.pfrio_esize = sizeof(struct pfr_tstats);
1318143611Sphilip
1319143611Sphilip	for (;;) {
1320149571Sphilip		t = reallocf(t, numtbls * sizeof(struct pfr_tstats));
1321149571Sphilip		if (t == NULL) {
1322149571Sphilip			syslog(LOG_ERR, "pft_refresh(): reallocf() numtbls=%d: %s",
1323149571Sphilip			    numtbls, strerror(errno));
1324149571Sphilip			goto err2;
1325149571Sphilip		}
1326143611Sphilip		io.pfrio_size = numtbls;
1327143611Sphilip		io.pfrio_buffer = t;
1328143611Sphilip
1329143611Sphilip		if (ioctl(dev, DIOCRGETTSTATS, &io)) {
1330143611Sphilip			syslog(LOG_ERR, "pft_refresh(): ioctl(): %s",
1331143611Sphilip			    strerror(errno));
1332149571Sphilip			goto err2;
1333143611Sphilip		}
1334143611Sphilip
1335143611Sphilip		if (numtbls >= io.pfrio_size)
1336143611Sphilip			break;
1337143611Sphilip
1338143611Sphilip		numtbls = io.pfrio_size;
1339143611Sphilip	}
1340143611Sphilip
1341143611Sphilip	for (i = 0; i < numtbls; i++) {
1342200122Ssyrinx		e = malloc(sizeof(struct pft_entry));
1343149571Sphilip		if (e == NULL)
1344149571Sphilip			goto err1;
1345143611Sphilip		e->index = i + 1;
1346143611Sphilip		memcpy(&e->pft, t+i, sizeof(struct pfr_tstats));
1347143611Sphilip		TAILQ_INSERT_TAIL(&pft_table, e, link);
1348143611Sphilip	}
1349143611Sphilip
1350143611Sphilip	pft_table_age = time(NULL);
1351143611Sphilip	pft_table_count = numtbls;
1352143611Sphilip	pf_tick = this_tick;
1353143611Sphilip
1354143611Sphilip	free(t);
1355143611Sphilip	return (0);
1356149571Sphiliperr1:
1357149571Sphilip	while (!TAILQ_EMPTY(&pft_table)) {
1358149571Sphilip		e = TAILQ_FIRST(&pft_table);
1359149571Sphilip		TAILQ_REMOVE(&pft_table, e, link);
1360149571Sphilip		free(e);
1361149571Sphilip	}
1362149571Sphiliperr2:
1363149571Sphilip	free(t);
1364149571Sphilip	return(-1);
1365143611Sphilip}
1366143611Sphilip
1367205280Ssyrinxstatic int
1368205607Ssyrinxpfa_table_addrs(u_int sidx, struct pfr_table *pt)
1369205607Ssyrinx{
1370205607Ssyrinx	struct pfioc_table io;
1371205607Ssyrinx	struct pfr_astats *t = NULL;
1372205607Ssyrinx	struct pfa_entry *e;
1373205607Ssyrinx	int i, numaddrs = 1;
1374205607Ssyrinx
1375205607Ssyrinx	if (pt == NULL)
1376205607Ssyrinx		return (-1);
1377205607Ssyrinx
1378205607Ssyrinx	memset(&io, 0, sizeof(io));
1379205607Ssyrinx	strlcpy(io.pfrio_table.pfrt_name, pt->pfrt_name,
1380205607Ssyrinx	    sizeof(io.pfrio_table.pfrt_name));
1381205607Ssyrinx
1382205607Ssyrinx	for (;;) {
1383205607Ssyrinx		t = reallocf(t, numaddrs * sizeof(struct pfr_astats));
1384205607Ssyrinx		if (t == NULL) {
1385205607Ssyrinx			syslog(LOG_ERR, "pfa_table_addrs(): reallocf(): %s",
1386205607Ssyrinx			    strerror(errno));
1387205607Ssyrinx			numaddrs = -1;
1388205607Ssyrinx			goto error;
1389205607Ssyrinx		}
1390205607Ssyrinx
1391205607Ssyrinx		memset(t, 0, sizeof(*t));
1392205607Ssyrinx		io.pfrio_size = numaddrs;
1393205607Ssyrinx		io.pfrio_buffer = t;
1394205607Ssyrinx		io.pfrio_esize = sizeof(struct pfr_astats);
1395205607Ssyrinx
1396205607Ssyrinx		if (ioctl(dev, DIOCRGETASTATS, &io)) {
1397205607Ssyrinx			syslog(LOG_ERR, "pfa_table_addrs(): ioctl() on %s: %s",
1398205607Ssyrinx			    pt->pfrt_name, strerror(errno));
1399205607Ssyrinx			numaddrs = -1;
1400205607Ssyrinx			break;
1401205607Ssyrinx		}
1402205607Ssyrinx
1403205607Ssyrinx		if (numaddrs >= io.pfrio_size)
1404205607Ssyrinx			break;
1405205607Ssyrinx
1406205607Ssyrinx		numaddrs = io.pfrio_size;
1407205607Ssyrinx	}
1408205607Ssyrinx
1409205607Ssyrinx	for (i = 0; i < numaddrs; i++) {
1410205607Ssyrinx		if ((t + i)->pfras_a.pfra_af != AF_INET &&
1411205607Ssyrinx		    (t + i)->pfras_a.pfra_af != AF_INET6) {
1412205607Ssyrinx			numaddrs = i;
1413205607Ssyrinx			break;
1414205607Ssyrinx		}
1415205607Ssyrinx
1416205607Ssyrinx		e = (struct pfa_entry *)malloc(sizeof(struct pfa_entry));
1417205607Ssyrinx		if (e == NULL) {
1418205607Ssyrinx			syslog(LOG_ERR, "pfa_table_addrs(): malloc(): %s",
1419205607Ssyrinx			    strerror(errno));
1420205607Ssyrinx			numaddrs = -1;
1421205607Ssyrinx			break;
1422205607Ssyrinx		}
1423205607Ssyrinx		e->index = sidx + i;
1424205607Ssyrinx		memcpy(&e->pfas, t + i, sizeof(struct pfr_astats));
1425205607Ssyrinx		TAILQ_INSERT_TAIL(&pfa_table, e, link);
1426205607Ssyrinx	}
1427205607Ssyrinx
1428205607Ssyrinx	free(t);
1429205607Ssyrinxerror:
1430205607Ssyrinx	return (numaddrs);
1431205607Ssyrinx}
1432205607Ssyrinx
1433205607Ssyrinxstatic int
1434205607Ssyrinxpfa_refresh(void)
1435205607Ssyrinx{
1436205607Ssyrinx	struct pfioc_table io;
1437205607Ssyrinx	struct pfr_table *pt = NULL, *it = NULL;
1438205607Ssyrinx	struct pfa_entry *e;
1439205607Ssyrinx	int i, numtbls = 1, cidx, naddrs;
1440205607Ssyrinx
1441205607Ssyrinx	if (started && this_tick <= pf_tick)
1442205607Ssyrinx		return (0);
1443205607Ssyrinx
1444205607Ssyrinx	while (!TAILQ_EMPTY(&pfa_table)) {
1445205607Ssyrinx		e = TAILQ_FIRST(&pfa_table);
1446205607Ssyrinx		TAILQ_REMOVE(&pfa_table, e, link);
1447205607Ssyrinx		free(e);
1448205607Ssyrinx	}
1449205607Ssyrinx
1450205607Ssyrinx	memset(&io, 0, sizeof(io));
1451205607Ssyrinx	io.pfrio_esize = sizeof(struct pfr_table);
1452205607Ssyrinx
1453205607Ssyrinx	for (;;) {
1454205607Ssyrinx		pt = reallocf(pt, numtbls * sizeof(struct pfr_table));
1455205607Ssyrinx		if (pt == NULL) {
1456205607Ssyrinx			syslog(LOG_ERR, "pfa_refresh(): reallocf() %s",
1457205607Ssyrinx			    strerror(errno));
1458205607Ssyrinx			return (-1);
1459205607Ssyrinx		}
1460205607Ssyrinx		memset(pt, 0, sizeof(*pt));
1461205607Ssyrinx		io.pfrio_size = numtbls;
1462205607Ssyrinx		io.pfrio_buffer = pt;
1463205607Ssyrinx
1464205607Ssyrinx		if (ioctl(dev, DIOCRGETTABLES, &io)) {
1465205607Ssyrinx			syslog(LOG_ERR, "pfa_refresh(): ioctl(): %s",
1466205607Ssyrinx			    strerror(errno));
1467205607Ssyrinx			goto err2;
1468205607Ssyrinx		}
1469205607Ssyrinx
1470205607Ssyrinx		if (numtbls >= io.pfrio_size)
1471205607Ssyrinx			break;
1472205607Ssyrinx
1473205607Ssyrinx		numtbls = io.pfrio_size;
1474205607Ssyrinx	}
1475205607Ssyrinx
1476205607Ssyrinx	cidx = 1;
1477205607Ssyrinx
1478205607Ssyrinx	for (it = pt, i = 0; i < numtbls; it++, i++) {
1479205607Ssyrinx		/*
1480205607Ssyrinx		 * Skip the table if not active - ioctl(DIOCRGETASTATS) will
1481205607Ssyrinx		 * return ESRCH for this entry anyway.
1482205607Ssyrinx		 */
1483205607Ssyrinx		if (!(it->pfrt_flags & PFR_TFLAG_ACTIVE))
1484205607Ssyrinx			continue;
1485205607Ssyrinx
1486205607Ssyrinx		if ((naddrs = pfa_table_addrs(cidx, it)) < 0)
1487205607Ssyrinx			goto err1;
1488205607Ssyrinx
1489205607Ssyrinx		cidx += naddrs;
1490205607Ssyrinx	}
1491205607Ssyrinx
1492205607Ssyrinx	pfa_table_age = time(NULL);
1493205607Ssyrinx	pfa_table_count = cidx;
1494205607Ssyrinx	pf_tick = this_tick;
1495205607Ssyrinx
1496205607Ssyrinx	free(pt);
1497205607Ssyrinx	return (0);
1498205607Ssyrinxerr1:
1499205607Ssyrinx	while (!TAILQ_EMPTY(&pfa_table)) {
1500205607Ssyrinx		e = TAILQ_FIRST(&pfa_table);
1501205607Ssyrinx		TAILQ_REMOVE(&pfa_table, e, link);
1502205607Ssyrinx		free(e);
1503205607Ssyrinx	}
1504205607Ssyrinx
1505205607Ssyrinxerr2:
1506205607Ssyrinx	free(pt);
1507205607Ssyrinx	return (-1);
1508205607Ssyrinx}
1509205607Ssyrinx
1510205607Ssyrinxstatic int
1511205280Ssyrinxpfl_scan_ruleset(const char *path)
1512205280Ssyrinx{
1513205280Ssyrinx	struct pfioc_rule pr;
1514205280Ssyrinx	struct pfl_entry *e;
1515205280Ssyrinx	u_int32_t nr, i;
1516205280Ssyrinx
1517205280Ssyrinx	bzero(&pr, sizeof(pr));
1518205280Ssyrinx	strlcpy(pr.anchor, path, sizeof(pr.anchor));
1519205280Ssyrinx	pr.rule.action = PF_PASS;
1520205280Ssyrinx	if (ioctl(dev, DIOCGETRULES, &pr)) {
1521205280Ssyrinx		syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULES): %s",
1522205280Ssyrinx		    strerror(errno));
1523205280Ssyrinx		goto err;
1524205280Ssyrinx	}
1525205280Ssyrinx
1526205280Ssyrinx	for (nr = pr.nr, i = 0; i < nr; i++) {
1527205280Ssyrinx		pr.nr = i;
1528205280Ssyrinx		if (ioctl(dev, DIOCGETRULE, &pr)) {
1529205280Ssyrinx			syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULE):"
1530205280Ssyrinx			    " %s", strerror(errno));
1531205280Ssyrinx			goto err;
1532205280Ssyrinx		}
1533205280Ssyrinx
1534205280Ssyrinx		if (pr.rule.label[0]) {
1535205280Ssyrinx			e = (struct pfl_entry *)malloc(sizeof(*e));
1536205280Ssyrinx			if (e == NULL)
1537205280Ssyrinx				goto err;
1538205280Ssyrinx
1539205280Ssyrinx			strlcpy(e->name, path, sizeof(e->name));
1540205280Ssyrinx			if (path[0])
1541205280Ssyrinx				strlcat(e->name, "/", sizeof(e->name));
1542205280Ssyrinx			strlcat(e->name, pr.rule.label, sizeof(e->name));
1543205280Ssyrinx
1544205280Ssyrinx			e->evals = pr.rule.evaluations;
1545205280Ssyrinx			e->bytes[IN] = pr.rule.bytes[IN];
1546205280Ssyrinx			e->bytes[OUT] = pr.rule.bytes[OUT];
1547205280Ssyrinx			e->pkts[IN] = pr.rule.packets[IN];
1548205280Ssyrinx			e->pkts[OUT] = pr.rule.packets[OUT];
1549205280Ssyrinx			e->index = ++pfl_table_count;
1550205280Ssyrinx
1551205280Ssyrinx			TAILQ_INSERT_TAIL(&pfl_table, e, link);
1552205280Ssyrinx		}
1553205280Ssyrinx	}
1554205280Ssyrinx
1555205280Ssyrinx	return (0);
1556205280Ssyrinx
1557205280Ssyrinxerr:
1558205280Ssyrinx	return (-1);
1559205280Ssyrinx}
1560205280Ssyrinx
1561205280Ssyrinxstatic int
1562205280Ssyrinxpfl_walk_rulesets(const char *path)
1563205280Ssyrinx{
1564205280Ssyrinx	struct pfioc_ruleset prs;
1565205280Ssyrinx	char newpath[MAXPATHLEN];
1566205280Ssyrinx	u_int32_t nr, i;
1567205280Ssyrinx
1568205280Ssyrinx	if (pfl_scan_ruleset(path))
1569205280Ssyrinx		goto err;
1570205280Ssyrinx
1571205280Ssyrinx	bzero(&prs, sizeof(prs));
1572205280Ssyrinx	strlcpy(prs.path, path, sizeof(prs.path));
1573205280Ssyrinx	if (ioctl(dev, DIOCGETRULESETS, &prs)) {
1574205280Ssyrinx		syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESETS): %s",
1575205280Ssyrinx		    strerror(errno));
1576205280Ssyrinx		goto err;
1577205280Ssyrinx	}
1578205280Ssyrinx
1579205280Ssyrinx	for (nr = prs.nr, i = 0; i < nr; i++) {
1580205280Ssyrinx		prs.nr = i;
1581205280Ssyrinx		if (ioctl(dev, DIOCGETRULESET, &prs)) {
1582205280Ssyrinx			syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESET):"
1583205280Ssyrinx			    " %s", strerror(errno));
1584205280Ssyrinx			goto err;
1585205280Ssyrinx		}
1586205280Ssyrinx
1587205280Ssyrinx		if (strcmp(prs.name, PF_RESERVED_ANCHOR) == 0)
1588205280Ssyrinx			continue;
1589205280Ssyrinx
1590205280Ssyrinx		strlcpy(newpath, path, sizeof(newpath));
1591205280Ssyrinx		if (path[0])
1592205280Ssyrinx			strlcat(newpath, "/", sizeof(newpath));
1593205280Ssyrinx
1594205280Ssyrinx		strlcat(newpath, prs.name, sizeof(newpath));
1595205280Ssyrinx		if (pfl_walk_rulesets(newpath))
1596205280Ssyrinx			goto err;
1597205280Ssyrinx	}
1598205280Ssyrinx
1599205280Ssyrinx	return (0);
1600205280Ssyrinx
1601205280Ssyrinxerr:
1602205280Ssyrinx	return (-1);
1603205280Ssyrinx}
1604205280Ssyrinx
1605205280Ssyrinxstatic int
1606205280Ssyrinxpfl_refresh(void)
1607205280Ssyrinx{
1608205280Ssyrinx	struct pfl_entry *e;
1609205280Ssyrinx
1610205280Ssyrinx	if (started && this_tick <= pf_tick)
1611205280Ssyrinx		return (0);
1612205280Ssyrinx
1613205280Ssyrinx	while (!TAILQ_EMPTY(&pfl_table)) {
1614205280Ssyrinx		e = TAILQ_FIRST(&pfl_table);
1615205280Ssyrinx		TAILQ_REMOVE(&pfl_table, e, link);
1616205280Ssyrinx		free(e);
1617205280Ssyrinx	}
1618205280Ssyrinx	pfl_table_count = 0;
1619205280Ssyrinx
1620205280Ssyrinx	if (pfl_walk_rulesets(""))
1621205280Ssyrinx		goto err;
1622205280Ssyrinx
1623205280Ssyrinx	pfl_table_age = time(NULL);
1624205280Ssyrinx	pf_tick = this_tick;
1625205280Ssyrinx
1626205280Ssyrinx	return (0);
1627205280Ssyrinx
1628205280Ssyrinxerr:
1629205280Ssyrinx	while (!TAILQ_EMPTY(&pfl_table)) {
1630205280Ssyrinx		e = TAILQ_FIRST(&pfl_table);
1631205280Ssyrinx		TAILQ_REMOVE(&pfl_table, e, link);
1632205280Ssyrinx		free(e);
1633205280Ssyrinx	}
1634205280Ssyrinx	pfl_table_count = 0;
1635205280Ssyrinx
1636205280Ssyrinx	return (-1);
1637205280Ssyrinx}
1638205280Ssyrinx
1639143611Sphilip/*
1640152970Sphilip * check whether altq support is enabled in kernel
1641152970Sphilip */
1642152970Sphilip
1643152970Sphilipstatic int
1644152970Sphilipaltq_is_enabled(int pfdev)
1645152970Sphilip{
1646152970Sphilip        struct pfioc_altq pa;
1647152970Sphilip
1648152970Sphilip	errno = 0;
1649152970Sphilip        if (ioctl(pfdev, DIOCGETALTQS, &pa)) {
1650152970Sphilip                if (errno == ENODEV) {
1651152970Sphilip			syslog(LOG_INFO, "No ALTQ support in kernel\n"
1652152970Sphilip			    "ALTQ related functions disabled\n");
1653152970Sphilip                        return (0);
1654152970Sphilip                } else
1655152970Sphilip                        syslog(LOG_ERR, "DIOCGETALTQS returned an error: %s",
1656152970Sphilip			    strerror(errno));
1657152970Sphilip			return (-1);
1658152970Sphilip        }
1659152970Sphilip        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	}
1680152970Sphilip
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);
1771143611Sphilip
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