pf_snmp.c revision 310901
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: stable/11/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c 310901 2016-12-31 10:32:49Z ngie $
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_pfInterfacesIfRefsRule:
590240233Sglebius			val->v.uint32 = e->pfi.pfik_rulerefs;
591143611Sphilip			break;
592143611Sphilip		case LEAF_pfInterfacesIf4BytesInPass:
593143611Sphilip			val->v.counter64 =
594171173Smlaier			    e->pfi.pfik_bytes[IPV4][IN][PASS];
595143611Sphilip			break;
596143611Sphilip		case LEAF_pfInterfacesIf4BytesInBlock:
597143611Sphilip			val->v.counter64 =
598171173Smlaier			    e->pfi.pfik_bytes[IPV4][IN][BLOCK];
599143611Sphilip			break;
600143611Sphilip		case LEAF_pfInterfacesIf4BytesOutPass:
601143611Sphilip			val->v.counter64 =
602171173Smlaier			    e->pfi.pfik_bytes[IPV4][OUT][PASS];
603143611Sphilip			break;
604143611Sphilip		case LEAF_pfInterfacesIf4BytesOutBlock:
605143611Sphilip			val->v.counter64 =
606171173Smlaier			    e->pfi.pfik_bytes[IPV4][OUT][BLOCK];
607143611Sphilip			break;
608143611Sphilip		case LEAF_pfInterfacesIf4PktsInPass:
609143611Sphilip			val->v.counter64 =
610171173Smlaier			    e->pfi.pfik_packets[IPV4][IN][PASS];
611143611Sphilip			break;
612143611Sphilip		case LEAF_pfInterfacesIf4PktsInBlock:
613143611Sphilip			val->v.counter64 =
614171173Smlaier			    e->pfi.pfik_packets[IPV4][IN][BLOCK];
615143611Sphilip			break;
616143611Sphilip		case LEAF_pfInterfacesIf4PktsOutPass:
617143611Sphilip			val->v.counter64 =
618171173Smlaier			    e->pfi.pfik_packets[IPV4][OUT][PASS];
619143611Sphilip			break;
620143611Sphilip		case LEAF_pfInterfacesIf4PktsOutBlock:
621143611Sphilip			val->v.counter64 =
622171173Smlaier			    e->pfi.pfik_packets[IPV4][OUT][BLOCK];
623143611Sphilip			break;
624143611Sphilip		case LEAF_pfInterfacesIf6BytesInPass:
625143611Sphilip			val->v.counter64 =
626171173Smlaier			    e->pfi.pfik_bytes[IPV6][IN][PASS];
627143611Sphilip			break;
628143611Sphilip		case LEAF_pfInterfacesIf6BytesInBlock:
629143611Sphilip			val->v.counter64 =
630171173Smlaier			    e->pfi.pfik_bytes[IPV6][IN][BLOCK];
631143611Sphilip			break;
632143611Sphilip		case LEAF_pfInterfacesIf6BytesOutPass:
633143611Sphilip			val->v.counter64 =
634171173Smlaier			    e->pfi.pfik_bytes[IPV6][OUT][PASS];
635143611Sphilip			break;
636143611Sphilip		case LEAF_pfInterfacesIf6BytesOutBlock:
637143611Sphilip			val->v.counter64 =
638171173Smlaier			    e->pfi.pfik_bytes[IPV6][OUT][BLOCK];
639143611Sphilip			break;
640143611Sphilip		case LEAF_pfInterfacesIf6PktsInPass:
641143611Sphilip			val->v.counter64 =
642171173Smlaier			    e->pfi.pfik_packets[IPV6][IN][PASS];
643143611Sphilip			break;
644143611Sphilip		case LEAF_pfInterfacesIf6PktsInBlock:
645143611Sphilip			val->v.counter64 =
646171173Smlaier			    e->pfi.pfik_packets[IPV6][IN][BLOCK];
647143611Sphilip			break;
648143611Sphilip		case LEAF_pfInterfacesIf6PktsOutPass:
649143611Sphilip			val->v.counter64 =
650171173Smlaier			    e->pfi.pfik_packets[IPV6][OUT][PASS];
651143611Sphilip			break;
652143611Sphilip		case LEAF_pfInterfacesIf6PktsOutBlock:
653310901Sngie			val->v.counter64 =
654171173Smlaier			    e->pfi.pfik_packets[IPV6][OUT][BLOCK];
655143611Sphilip			break;
656143611Sphilip
657143611Sphilip		default:
658143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
659143611Sphilip	}
660143611Sphilip
661143611Sphilip	return (SNMP_ERR_NOERROR);
662143611Sphilip}
663143611Sphilip
664143611Sphilipint
665143611Sphilippf_tables(struct snmp_context __unused *ctx, struct snmp_value *val,
666143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
667143611Sphilip{
668143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
669143611Sphilip
670143611Sphilip	if (op == SNMP_OP_SET)
671143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
672143611Sphilip
673143611Sphilip	if (op == SNMP_OP_GET) {
674143611Sphilip		if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
675143611Sphilip			if (pft_refresh() == -1)
676143611Sphilip			    return (SNMP_ERR_GENERR);
677143611Sphilip
678143611Sphilip		switch (which) {
679143611Sphilip			case LEAF_pfTablesTblNumber:
680143611Sphilip				val->v.uint32 = pft_table_count;
681143611Sphilip				break;
682143611Sphilip
683143611Sphilip			default:
684143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
685143611Sphilip		}
686143611Sphilip
687143611Sphilip		return (SNMP_ERR_NOERROR);
688143611Sphilip	}
689143611Sphilip
690143611Sphilip	abort();
691143611Sphilip}
692143611Sphilip
693143611Sphilipint
694143611Sphilippf_tbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
695143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
696143611Sphilip{
697143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
698143611Sphilip	struct pft_entry *e = NULL;
699143611Sphilip
700205312Ssyrinx	if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE)
701205312Ssyrinx		pft_refresh();
702205312Ssyrinx
703143611Sphilip	switch (op) {
704143611Sphilip		case SNMP_OP_SET:
705143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
706143611Sphilip		case SNMP_OP_GETNEXT:
707143611Sphilip			if ((e = NEXT_OBJECT_INT(&pft_table,
708143611Sphilip			    &val->var, sub)) == NULL)
709143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
710143611Sphilip			val->var.len = sub + 1;
711143611Sphilip			val->var.subs[sub] = e->index;
712143611Sphilip			break;
713143611Sphilip		case SNMP_OP_GET:
714143611Sphilip			if (val->var.len - sub != 1)
715143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
716143611Sphilip			if ((e = pft_table_find(val->var.subs[sub])) == NULL)
717143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
718143611Sphilip			break;
719143611Sphilip
720143611Sphilip		case SNMP_OP_COMMIT:
721143611Sphilip		case SNMP_OP_ROLLBACK:
722143611Sphilip		default:
723143611Sphilip			abort();
724143611Sphilip	}
725143611Sphilip
726143611Sphilip	switch (which) {
727143611Sphilip		case LEAF_pfTablesTblDescr:
728143611Sphilip			return (string_get(val, e->pft.pfrts_name, -1));
729143611Sphilip		case LEAF_pfTablesTblCount:
730143611Sphilip			val->v.integer = e->pft.pfrts_cnt;
731143611Sphilip			break;
732143611Sphilip		case LEAF_pfTablesTblTZero:
733143611Sphilip			val->v.uint32 =
734143611Sphilip			    (time(NULL) - e->pft.pfrts_tzero) * 100;
735143611Sphilip			break;
736143611Sphilip		case LEAF_pfTablesTblRefsAnchor:
737143611Sphilip			val->v.integer =
738143611Sphilip			    e->pft.pfrts_refcnt[PFR_REFCNT_ANCHOR];
739143611Sphilip			break;
740143611Sphilip		case LEAF_pfTablesTblRefsRule:
741143611Sphilip			val->v.integer =
742143611Sphilip			    e->pft.pfrts_refcnt[PFR_REFCNT_RULE];
743143611Sphilip			break;
744143611Sphilip		case LEAF_pfTablesTblEvalMatch:
745143611Sphilip			val->v.counter64 = e->pft.pfrts_match;
746143611Sphilip			break;
747143611Sphilip		case LEAF_pfTablesTblEvalNoMatch:
748143611Sphilip			val->v.counter64 = e->pft.pfrts_nomatch;
749143611Sphilip			break;
750143611Sphilip		case LEAF_pfTablesTblBytesInPass:
751143611Sphilip			val->v.counter64 =
752143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_PASS];
753143611Sphilip			break;
754143611Sphilip		case LEAF_pfTablesTblBytesInBlock:
755143611Sphilip			val->v.counter64 =
756143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_BLOCK];
757143611Sphilip			break;
758143611Sphilip		case LEAF_pfTablesTblBytesInXPass:
759143611Sphilip			val->v.counter64 =
760143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_XPASS];
761143611Sphilip			break;
762143611Sphilip		case LEAF_pfTablesTblBytesOutPass:
763143611Sphilip			val->v.counter64 =
764143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_PASS];
765143611Sphilip			break;
766143611Sphilip		case LEAF_pfTablesTblBytesOutBlock:
767143611Sphilip			val->v.counter64 =
768143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_BLOCK];
769143611Sphilip			break;
770143611Sphilip		case LEAF_pfTablesTblBytesOutXPass:
771143611Sphilip			val->v.counter64 =
772143611Sphilip			    e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_XPASS];
773143611Sphilip			break;
774143611Sphilip		case LEAF_pfTablesTblPktsInPass:
775143611Sphilip			val->v.counter64 =
776143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_PASS];
777143611Sphilip			break;
778143611Sphilip		case LEAF_pfTablesTblPktsInBlock:
779143611Sphilip			val->v.counter64 =
780143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_BLOCK];
781143611Sphilip			break;
782143611Sphilip		case LEAF_pfTablesTblPktsInXPass:
783143611Sphilip			val->v.counter64 =
784143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_XPASS];
785143611Sphilip			break;
786143611Sphilip		case LEAF_pfTablesTblPktsOutPass:
787143611Sphilip			val->v.counter64 =
788143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_PASS];
789143611Sphilip			break;
790143611Sphilip		case LEAF_pfTablesTblPktsOutBlock:
791143611Sphilip			val->v.counter64 =
792143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_BLOCK];
793143611Sphilip			break;
794143611Sphilip		case LEAF_pfTablesTblPktsOutXPass:
795143611Sphilip			val->v.counter64 =
796143611Sphilip			    e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_XPASS];
797143611Sphilip			break;
798143611Sphilip
799143611Sphilip		default:
800143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
801143611Sphilip	}
802143611Sphilip
803143611Sphilip	return (SNMP_ERR_NOERROR);
804143611Sphilip}
805143611Sphilip
806143611Sphilipint
807143611Sphilippf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val,
808143611Sphilip	u_int __unused sub, u_int __unused vindex, enum snmp_op __unused op)
809143611Sphilip{
810205607Ssyrinx	asn_subid_t	which = val->var.subs[sub - 1];
811205607Ssyrinx	struct pfa_entry *e = NULL;
812205607Ssyrinx
813205607Ssyrinx	if ((time(NULL) - pfa_table_age) > PFA_TABLE_MAXAGE)
814205607Ssyrinx		pfa_refresh();
815205607Ssyrinx
816205607Ssyrinx	switch (op) {
817205607Ssyrinx		case SNMP_OP_SET:
818205607Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
819205607Ssyrinx		case SNMP_OP_GETNEXT:
820205607Ssyrinx			if ((e = NEXT_OBJECT_INT(&pfa_table,
821205607Ssyrinx			    &val->var, sub)) == NULL)
822205607Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
823205607Ssyrinx			val->var.len = sub + 1;
824205607Ssyrinx			val->var.subs[sub] = e->index;
825205607Ssyrinx			break;
826205607Ssyrinx		case SNMP_OP_GET:
827205607Ssyrinx			if (val->var.len - sub != 1)
828205607Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
829205607Ssyrinx			if ((e = pfa_table_find(val->var.subs[sub])) == NULL)
830205607Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
831205607Ssyrinx			break;
832205607Ssyrinx
833205607Ssyrinx		case SNMP_OP_COMMIT:
834205607Ssyrinx		case SNMP_OP_ROLLBACK:
835205607Ssyrinx		default:
836205607Ssyrinx			abort();
837205607Ssyrinx	}
838205607Ssyrinx
839205607Ssyrinx	switch (which) {
840205607Ssyrinx		case LEAF_pfTablesAddrNetType:
841205607Ssyrinx			if (e->pfas.pfras_a.pfra_af == AF_INET)
842205607Ssyrinx				val->v.integer = pfTablesAddrNetType_ipv4;
843205607Ssyrinx			else if (e->pfas.pfras_a.pfra_af == AF_INET6)
844205607Ssyrinx				val->v.integer = pfTablesAddrNetType_ipv6;
845205607Ssyrinx			else
846205607Ssyrinx				return (SNMP_ERR_GENERR);
847205607Ssyrinx			break;
848205607Ssyrinx		case LEAF_pfTablesAddrNet:
849205607Ssyrinx			if (e->pfas.pfras_a.pfra_af == AF_INET) {
850205607Ssyrinx				return (string_get(val,
851205607Ssyrinx				    (u_char *)&e->pfas.pfras_a.pfra_ip4addr, 4));
852205607Ssyrinx			} else if (e->pfas.pfras_a.pfra_af == AF_INET6)
853205607Ssyrinx				return (string_get(val,
854205607Ssyrinx				    (u_char *)&e->pfas.pfras_a.pfra_ip6addr, 16));
855205607Ssyrinx			else
856205607Ssyrinx				return (SNMP_ERR_GENERR);
857205607Ssyrinx			break;
858205607Ssyrinx		case LEAF_pfTablesAddrPrefix:
859205607Ssyrinx			val->v.integer = (int32_t) e->pfas.pfras_a.pfra_net;
860205607Ssyrinx			break;
861205607Ssyrinx		case LEAF_pfTablesAddrTZero:
862205607Ssyrinx			val->v.uint32 =
863205607Ssyrinx			    (time(NULL) - e->pfas.pfras_tzero) * 100;
864205607Ssyrinx			break;
865205607Ssyrinx		case LEAF_pfTablesAddrBytesInPass:
866205607Ssyrinx			val->v.counter64 =
867205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_IN][PFR_OP_PASS];
868205607Ssyrinx			break;
869205607Ssyrinx		case LEAF_pfTablesAddrBytesInBlock:
870205607Ssyrinx			val->v.counter64 =
871205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_IN][PFR_OP_BLOCK];
872205607Ssyrinx			break;
873205607Ssyrinx		case LEAF_pfTablesAddrBytesOutPass:
874205607Ssyrinx			val->v.counter64 =
875205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_OUT][PFR_OP_PASS];
876205607Ssyrinx			break;
877205607Ssyrinx		case LEAF_pfTablesAddrBytesOutBlock:
878205607Ssyrinx			val->v.counter64 =
879205607Ssyrinx			    e->pfas.pfras_bytes[PFR_DIR_OUT][PFR_OP_BLOCK];
880205607Ssyrinx			break;
881205607Ssyrinx		case LEAF_pfTablesAddrPktsInPass:
882205607Ssyrinx			val->v.counter64 =
883205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_IN][PFR_OP_PASS];
884205607Ssyrinx			break;
885205607Ssyrinx		case LEAF_pfTablesAddrPktsInBlock:
886205607Ssyrinx			val->v.counter64 =
887205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_IN][PFR_OP_BLOCK];
888205607Ssyrinx			break;
889205607Ssyrinx		case LEAF_pfTablesAddrPktsOutPass:
890205607Ssyrinx			val->v.counter64 =
891205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_OUT][PFR_OP_PASS];
892205607Ssyrinx			break;
893205607Ssyrinx		case LEAF_pfTablesAddrPktsOutBlock:
894205607Ssyrinx			val->v.counter64 =
895205607Ssyrinx			    e->pfas.pfras_packets[PFR_DIR_OUT][PFR_OP_BLOCK];
896205607Ssyrinx			break;
897205607Ssyrinx		default:
898205607Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
899205607Ssyrinx	}
900205607Ssyrinx
901205607Ssyrinx	return (SNMP_ERR_NOERROR);
902143611Sphilip}
903143611Sphilip
904143611Sphilipint
905143611Sphilippf_altq(struct snmp_context __unused *ctx, struct snmp_value *val,
906143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
907143611Sphilip{
908143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
909143611Sphilip
910205607Ssyrinx	if (!altq_enabled)
911205607Ssyrinx	   return (SNMP_ERR_NOSUCHNAME);
912152970Sphilip
913143611Sphilip	if (op == SNMP_OP_SET)
914143611Sphilip		return (SNMP_ERR_NOT_WRITEABLE);
915143611Sphilip
916143611Sphilip	if (op == SNMP_OP_GET) {
917143611Sphilip		if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
918143611Sphilip			if (pfq_refresh() == -1)
919143611Sphilip			    return (SNMP_ERR_GENERR);
920143611Sphilip
921143611Sphilip		switch (which) {
922143611Sphilip			case LEAF_pfAltqQueueNumber:
923143611Sphilip				val->v.uint32 = pfq_table_count;
924143611Sphilip				break;
925143611Sphilip
926143611Sphilip			default:
927143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
928143611Sphilip		}
929143611Sphilip
930143611Sphilip		return (SNMP_ERR_NOERROR);
931143611Sphilip	}
932143611Sphilip
933143611Sphilip	abort();
934143611Sphilip	return (SNMP_ERR_GENERR);
935310901Sngie}
936143611Sphilip
937143611Sphilipint
938143611Sphilippf_altqq(struct snmp_context __unused *ctx, struct snmp_value *val,
939143611Sphilip	u_int sub, u_int __unused vindex, enum snmp_op op)
940143611Sphilip{
941143611Sphilip	asn_subid_t	which = val->var.subs[sub - 1];
942143611Sphilip	struct pfq_entry *e = NULL;
943143611Sphilip
944205607Ssyrinx	if (!altq_enabled)
945205607Ssyrinx	   return (SNMP_ERR_NOSUCHNAME);
946152970Sphilip
947205312Ssyrinx	if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE)
948205312Ssyrinx		pfq_refresh();
949205312Ssyrinx
950143611Sphilip	switch (op) {
951143611Sphilip		case SNMP_OP_SET:
952143611Sphilip			return (SNMP_ERR_NOT_WRITEABLE);
953143611Sphilip		case SNMP_OP_GETNEXT:
954143611Sphilip			if ((e = NEXT_OBJECT_INT(&pfq_table,
955143611Sphilip			    &val->var, sub)) == NULL)
956143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
957143611Sphilip			val->var.len = sub + 1;
958143611Sphilip			val->var.subs[sub] = e->index;
959143611Sphilip			break;
960143611Sphilip		case SNMP_OP_GET:
961143611Sphilip			if (val->var.len - sub != 1)
962143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
963143611Sphilip			if ((e = pfq_table_find(val->var.subs[sub])) == NULL)
964143611Sphilip				return (SNMP_ERR_NOSUCHNAME);
965143611Sphilip			break;
966143611Sphilip
967143611Sphilip		case SNMP_OP_COMMIT:
968143611Sphilip		case SNMP_OP_ROLLBACK:
969143611Sphilip		default:
970143611Sphilip			abort();
971143611Sphilip	}
972143611Sphilip
973143611Sphilip	switch (which) {
974143611Sphilip		case LEAF_pfAltqQueueDescr:
975143611Sphilip			return (string_get(val, e->altq.qname, -1));
976143611Sphilip		case LEAF_pfAltqQueueParent:
977143611Sphilip			return (string_get(val, e->altq.parent, -1));
978143611Sphilip		case LEAF_pfAltqQueueScheduler:
979143611Sphilip			val->v.integer = e->altq.scheduler;
980143611Sphilip			break;
981143611Sphilip		case LEAF_pfAltqQueueBandwidth:
982143611Sphilip			val->v.uint32 = e->altq.bandwidth;
983143611Sphilip			break;
984143611Sphilip		case LEAF_pfAltqQueuePriority:
985143611Sphilip			val->v.integer = e->altq.priority;
986143611Sphilip			break;
987143611Sphilip		case LEAF_pfAltqQueueLimit:
988143611Sphilip			val->v.integer = e->altq.qlimit;
989143611Sphilip			break;
990310901Sngie
991143611Sphilip		default:
992143611Sphilip			return (SNMP_ERR_NOSUCHNAME);
993143611Sphilip	}
994143611Sphilip
995143611Sphilip	return (SNMP_ERR_NOERROR);
996205280Ssyrinx}
997143611Sphilip
998205280Ssyrinxint
999205280Ssyrinxpf_labels(struct snmp_context __unused *ctx, struct snmp_value *val,
1000205280Ssyrinx	u_int sub, u_int __unused vindex, enum snmp_op op)
1001205280Ssyrinx{
1002205280Ssyrinx	asn_subid_t	which = val->var.subs[sub - 1];
1003205280Ssyrinx
1004205280Ssyrinx	if (op == SNMP_OP_SET)
1005205280Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
1006205280Ssyrinx
1007205280Ssyrinx	if (op == SNMP_OP_GET) {
1008205280Ssyrinx		if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
1009205280Ssyrinx			if (pfl_refresh() == -1)
1010205280Ssyrinx				return (SNMP_ERR_GENERR);
1011205280Ssyrinx
1012205280Ssyrinx		switch (which) {
1013205280Ssyrinx			case LEAF_pfLabelsLblNumber:
1014205280Ssyrinx				val->v.uint32 = pfl_table_count;
1015205280Ssyrinx				break;
1016205280Ssyrinx
1017205280Ssyrinx			default:
1018205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1019205280Ssyrinx		}
1020205280Ssyrinx
1021205280Ssyrinx		return (SNMP_ERR_NOERROR);
1022205280Ssyrinx	}
1023205280Ssyrinx
1024205280Ssyrinx	abort();
1025205280Ssyrinx	return (SNMP_ERR_GENERR);
1026205280Ssyrinx}
1027205280Ssyrinx
1028205280Ssyrinxint
1029205280Ssyrinxpf_lbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
1030205280Ssyrinx	u_int sub, u_int __unused vindex, enum snmp_op op)
1031205280Ssyrinx{
1032205280Ssyrinx	asn_subid_t	which = val->var.subs[sub - 1];
1033205280Ssyrinx	struct pfl_entry *e = NULL;
1034205280Ssyrinx
1035205312Ssyrinx	if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
1036205312Ssyrinx		pfl_refresh();
1037205312Ssyrinx
1038205280Ssyrinx	switch (op) {
1039205280Ssyrinx		case SNMP_OP_SET:
1040205280Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
1041205280Ssyrinx		case SNMP_OP_GETNEXT:
1042205280Ssyrinx			if ((e = NEXT_OBJECT_INT(&pfl_table,
1043205280Ssyrinx			    &val->var, sub)) == NULL)
1044205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1045205280Ssyrinx			val->var.len = sub + 1;
1046205280Ssyrinx			val->var.subs[sub] = e->index;
1047205280Ssyrinx			break;
1048205280Ssyrinx		case SNMP_OP_GET:
1049205280Ssyrinx			if (val->var.len - sub != 1)
1050205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1051205280Ssyrinx			if ((e = pfl_table_find(val->var.subs[sub])) == NULL)
1052205280Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
1053205280Ssyrinx			break;
1054205280Ssyrinx
1055205280Ssyrinx		case SNMP_OP_COMMIT:
1056205280Ssyrinx		case SNMP_OP_ROLLBACK:
1057205280Ssyrinx		default:
1058205280Ssyrinx			abort();
1059205280Ssyrinx	}
1060205280Ssyrinx
1061205280Ssyrinx	switch (which) {
1062205280Ssyrinx		case LEAF_pfLabelsLblName:
1063205280Ssyrinx			return (string_get(val, e->name, -1));
1064205280Ssyrinx		case LEAF_pfLabelsLblEvals:
1065205280Ssyrinx			val->v.counter64 = e->evals;
1066205280Ssyrinx			break;
1067205280Ssyrinx		case LEAF_pfLabelsLblBytesIn:
1068205280Ssyrinx			val->v.counter64 = e->bytes[IN];
1069205280Ssyrinx			break;
1070205280Ssyrinx		case LEAF_pfLabelsLblBytesOut:
1071205280Ssyrinx			val->v.counter64 = e->bytes[OUT];
1072205280Ssyrinx			break;
1073205280Ssyrinx		case LEAF_pfLabelsLblPktsIn:
1074205280Ssyrinx			val->v.counter64 = e->pkts[IN];
1075205280Ssyrinx			break;
1076205280Ssyrinx		case LEAF_pfLabelsLblPktsOut:
1077205280Ssyrinx			val->v.counter64 = e->pkts[OUT];
1078205280Ssyrinx			break;
1079205280Ssyrinx		default:
1080205280Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1081205280Ssyrinx	}
1082205280Ssyrinx
1083205280Ssyrinx	return (SNMP_ERR_NOERROR);
1084205280Ssyrinx}
1085205280Ssyrinx
1086143611Sphilipstatic struct pfi_entry *
1087143611Sphilippfi_table_find(u_int idx)
1088143611Sphilip{
1089143611Sphilip	struct pfi_entry *e;
1090143611Sphilip
1091143611Sphilip	TAILQ_FOREACH(e, &pfi_table, link)
1092143611Sphilip		if (e->index == idx)
1093143611Sphilip			return (e);
1094143611Sphilip	return (NULL);
1095143611Sphilip}
1096143611Sphilip
1097143611Sphilipstatic struct pfq_entry *
1098143611Sphilippfq_table_find(u_int idx)
1099143611Sphilip{
1100143611Sphilip	struct pfq_entry *e;
1101205280Ssyrinx
1102143611Sphilip	TAILQ_FOREACH(e, &pfq_table, link)
1103143611Sphilip		if (e->index == idx)
1104143611Sphilip			return (e);
1105143611Sphilip	return (NULL);
1106143611Sphilip}
1107143611Sphilip
1108143611Sphilipstatic struct pft_entry *
1109143611Sphilippft_table_find(u_int idx)
1110143611Sphilip{
1111143611Sphilip	struct pft_entry *e;
1112143611Sphilip
1113143611Sphilip	TAILQ_FOREACH(e, &pft_table, link)
1114143611Sphilip		if (e->index == idx)
1115143611Sphilip			return (e);
1116143611Sphilip	return (NULL);
1117143611Sphilip}
1118143611Sphilip
1119205607Ssyrinxstatic struct pfa_entry *
1120205607Ssyrinxpfa_table_find(u_int idx)
1121205607Ssyrinx{
1122205607Ssyrinx	struct pfa_entry *e;
1123205607Ssyrinx
1124205607Ssyrinx	TAILQ_FOREACH(e, &pfa_table, link)
1125205607Ssyrinx		if (e->index == idx)
1126205607Ssyrinx			return (e);
1127205607Ssyrinx	return (NULL);
1128205607Ssyrinx}
1129205607Ssyrinx
1130205280Ssyrinxstatic struct pfl_entry *
1131205280Ssyrinxpfl_table_find(u_int idx)
1132205280Ssyrinx{
1133205280Ssyrinx	struct pfl_entry *e;
1134205280Ssyrinx
1135205280Ssyrinx	TAILQ_FOREACH(e, &pfl_table, link)
1136205280Ssyrinx		if (e->index == idx)
1137205280Ssyrinx			return (e);
1138205280Ssyrinx
1139205280Ssyrinx	return (NULL);
1140205280Ssyrinx}
1141205280Ssyrinx
1142143611Sphilipstatic int
1143143611Sphilippfi_refresh(void)
1144143611Sphilip{
1145143611Sphilip	struct pfioc_iface io;
1146171173Smlaier	struct pfi_kif *p = NULL;
1147143611Sphilip	struct pfi_entry *e;
1148143611Sphilip	int i, numifs = 1;
1149143611Sphilip
1150143611Sphilip	if (started && this_tick <= pf_tick)
1151143611Sphilip		return (0);
1152143611Sphilip
1153143611Sphilip	while (!TAILQ_EMPTY(&pfi_table)) {
1154143611Sphilip		e = TAILQ_FIRST(&pfi_table);
1155143611Sphilip		TAILQ_REMOVE(&pfi_table, e, link);
1156143611Sphilip		free(e);
1157143611Sphilip	}
1158143611Sphilip
1159143611Sphilip	bzero(&io, sizeof(io));
1160171173Smlaier	io.pfiio_esize = sizeof(struct pfi_kif);
1161143611Sphilip
1162143611Sphilip	for (;;) {
1163171173Smlaier		p = reallocf(p, numifs * sizeof(struct pfi_kif));
1164149571Sphilip		if (p == NULL) {
1165149571Sphilip			syslog(LOG_ERR, "pfi_refresh(): reallocf() numifs=%d: %s",
1166149571Sphilip			    numifs, strerror(errno));
1167149571Sphilip			goto err2;
1168149571Sphilip		}
1169143611Sphilip		io.pfiio_size = numifs;
1170143611Sphilip		io.pfiio_buffer = p;
1171143611Sphilip
1172143611Sphilip		if (ioctl(dev, DIOCIGETIFACES, &io)) {
1173143611Sphilip			syslog(LOG_ERR, "pfi_refresh(): ioctl(): %s",
1174143611Sphilip			    strerror(errno));
1175149571Sphilip			goto err2;
1176143611Sphilip		}
1177143611Sphilip
1178143611Sphilip		if (numifs >= io.pfiio_size)
1179143611Sphilip			break;
1180143611Sphilip
1181143611Sphilip		numifs = io.pfiio_size;
1182143611Sphilip	}
1183143611Sphilip
1184143611Sphilip	for (i = 0; i < numifs; i++) {
1185143611Sphilip		e = malloc(sizeof(struct pfi_entry));
1186149571Sphilip		if (e == NULL)
1187149571Sphilip			goto err1;
1188143611Sphilip		e->index = i + 1;
1189171173Smlaier		memcpy(&e->pfi, p+i, sizeof(struct pfi_kif));
1190143611Sphilip		TAILQ_INSERT_TAIL(&pfi_table, e, link);
1191143611Sphilip	}
1192143611Sphilip
1193143611Sphilip	pfi_table_age = time(NULL);
1194143611Sphilip	pfi_table_count = numifs;
1195143611Sphilip	pf_tick = this_tick;
1196143611Sphilip
1197143611Sphilip	free(p);
1198143611Sphilip	return (0);
1199149571Sphilip
1200149571Sphiliperr1:
1201149571Sphilip	while (!TAILQ_EMPTY(&pfi_table)) {
1202149571Sphilip		e = TAILQ_FIRST(&pfi_table);
1203149571Sphilip		TAILQ_REMOVE(&pfi_table, e, link);
1204149571Sphilip		free(e);
1205149571Sphilip	}
1206149571Sphiliperr2:
1207149571Sphilip	free(p);
1208149571Sphilip	return(-1);
1209143611Sphilip}
1210143611Sphilip
1211143611Sphilipstatic int
1212143611Sphilippfq_refresh(void)
1213143611Sphilip{
1214143611Sphilip	struct pfioc_altq pa;
1215143611Sphilip	struct pfq_entry *e;
1216143611Sphilip	int i, numqs, ticket;
1217143611Sphilip
1218143611Sphilip	if (started && this_tick <= pf_tick)
1219143611Sphilip		return (0);
1220143611Sphilip
1221143611Sphilip	while (!TAILQ_EMPTY(&pfq_table)) {
1222143611Sphilip		e = TAILQ_FIRST(&pfq_table);
1223143611Sphilip		TAILQ_REMOVE(&pfq_table, e, link);
1224143611Sphilip		free(e);
1225143611Sphilip	}
1226143611Sphilip
1227143611Sphilip	bzero(&pa, sizeof(pa));
1228310901Sngie
1229143611Sphilip	if (ioctl(dev, DIOCGETALTQS, &pa)) {
1230143611Sphilip		syslog(LOG_ERR, "pfq_refresh: ioctl(DIOCGETALTQS): %s",
1231143611Sphilip		    strerror(errno));
1232143611Sphilip		return (-1);
1233143611Sphilip	}
1234143611Sphilip
1235143611Sphilip	numqs = pa.nr;
1236143611Sphilip	ticket = pa.ticket;
1237143611Sphilip
1238143611Sphilip	for (i = 0; i < numqs; i++) {
1239143611Sphilip		e = malloc(sizeof(struct pfq_entry));
1240149571Sphilip		if (e == NULL) {
1241149571Sphilip			syslog(LOG_ERR, "pfq_refresh(): "
1242149571Sphilip			    "malloc(): %s",
1243149571Sphilip			    strerror(errno));
1244149571Sphilip			goto err;
1245149571Sphilip		}
1246143611Sphilip		pa.ticket = ticket;
1247143611Sphilip		pa.nr = i;
1248143611Sphilip
1249143611Sphilip		if (ioctl(dev, DIOCGETALTQ, &pa)) {
1250143611Sphilip			syslog(LOG_ERR, "pfq_refresh(): "
1251143611Sphilip			    "ioctl(DIOCGETALTQ): %s",
1252143611Sphilip			    strerror(errno));
1253149571Sphilip			goto err;
1254143611Sphilip		}
1255143611Sphilip
1256143611Sphilip		if (pa.altq.qid > 0) {
1257143611Sphilip			memcpy(&e->altq, &pa.altq, sizeof(struct pf_altq));
1258143611Sphilip			e->index = pa.altq.qid;
1259143611Sphilip			pfq_table_count = i;
1260179476Sphilip			INSERT_OBJECT_INT_LINK_INDEX(e, &pfq_table, link, index);
1261143611Sphilip		}
1262143611Sphilip	}
1263310901Sngie
1264143611Sphilip	pfq_table_age = time(NULL);
1265143611Sphilip	pf_tick = this_tick;
1266143611Sphilip
1267143611Sphilip	return (0);
1268149571Sphiliperr:
1269149571Sphilip	free(e);
1270149571Sphilip	while (!TAILQ_EMPTY(&pfq_table)) {
1271149571Sphilip		e = TAILQ_FIRST(&pfq_table);
1272149571Sphilip		TAILQ_REMOVE(&pfq_table, e, link);
1273149571Sphilip		free(e);
1274149571Sphilip	}
1275149571Sphilip	return(-1);
1276143611Sphilip}
1277143611Sphilip
1278143611Sphilipstatic int
1279143611Sphilippfs_refresh(void)
1280143611Sphilip{
1281143611Sphilip	if (started && this_tick <= pf_tick)
1282143611Sphilip		return (0);
1283143611Sphilip
1284143611Sphilip	bzero(&pfs, sizeof(struct pf_status));
1285143611Sphilip
1286143611Sphilip	if (ioctl(dev, DIOCGETSTATUS, &pfs)) {
1287143611Sphilip		syslog(LOG_ERR, "pfs_refresh(): ioctl(): %s",
1288143611Sphilip		    strerror(errno));
1289143611Sphilip		return (-1);
1290143611Sphilip	}
1291143611Sphilip
1292143611Sphilip	pf_tick = this_tick;
1293143611Sphilip	return (0);
1294143611Sphilip}
1295143611Sphilip
1296143611Sphilipstatic int
1297143611Sphilippft_refresh(void)
1298143611Sphilip{
1299143611Sphilip	struct pfioc_table io;
1300149571Sphilip	struct pfr_tstats *t = NULL;
1301143611Sphilip	struct pft_entry *e;
1302143611Sphilip	int i, numtbls = 1;
1303143611Sphilip
1304143611Sphilip	if (started && this_tick <= pf_tick)
1305143611Sphilip		return (0);
1306143611Sphilip
1307143611Sphilip	while (!TAILQ_EMPTY(&pft_table)) {
1308143611Sphilip		e = TAILQ_FIRST(&pft_table);
1309143611Sphilip		TAILQ_REMOVE(&pft_table, e, link);
1310143611Sphilip		free(e);
1311143611Sphilip	}
1312143611Sphilip
1313143611Sphilip	bzero(&io, sizeof(io));
1314143611Sphilip	io.pfrio_esize = sizeof(struct pfr_tstats);
1315143611Sphilip
1316143611Sphilip	for (;;) {
1317149571Sphilip		t = reallocf(t, numtbls * sizeof(struct pfr_tstats));
1318149571Sphilip		if (t == NULL) {
1319149571Sphilip			syslog(LOG_ERR, "pft_refresh(): reallocf() numtbls=%d: %s",
1320149571Sphilip			    numtbls, strerror(errno));
1321149571Sphilip			goto err2;
1322149571Sphilip		}
1323143611Sphilip		io.pfrio_size = numtbls;
1324143611Sphilip		io.pfrio_buffer = t;
1325143611Sphilip
1326143611Sphilip		if (ioctl(dev, DIOCRGETTSTATS, &io)) {
1327143611Sphilip			syslog(LOG_ERR, "pft_refresh(): ioctl(): %s",
1328143611Sphilip			    strerror(errno));
1329149571Sphilip			goto err2;
1330143611Sphilip		}
1331143611Sphilip
1332143611Sphilip		if (numtbls >= io.pfrio_size)
1333143611Sphilip			break;
1334143611Sphilip
1335143611Sphilip		numtbls = io.pfrio_size;
1336143611Sphilip	}
1337143611Sphilip
1338143611Sphilip	for (i = 0; i < numtbls; i++) {
1339200122Ssyrinx		e = malloc(sizeof(struct pft_entry));
1340149571Sphilip		if (e == NULL)
1341149571Sphilip			goto err1;
1342143611Sphilip		e->index = i + 1;
1343143611Sphilip		memcpy(&e->pft, t+i, sizeof(struct pfr_tstats));
1344143611Sphilip		TAILQ_INSERT_TAIL(&pft_table, e, link);
1345143611Sphilip	}
1346143611Sphilip
1347143611Sphilip	pft_table_age = time(NULL);
1348143611Sphilip	pft_table_count = numtbls;
1349143611Sphilip	pf_tick = this_tick;
1350143611Sphilip
1351143611Sphilip	free(t);
1352143611Sphilip	return (0);
1353149571Sphiliperr1:
1354149571Sphilip	while (!TAILQ_EMPTY(&pft_table)) {
1355149571Sphilip		e = TAILQ_FIRST(&pft_table);
1356149571Sphilip		TAILQ_REMOVE(&pft_table, e, link);
1357149571Sphilip		free(e);
1358149571Sphilip	}
1359149571Sphiliperr2:
1360149571Sphilip	free(t);
1361149571Sphilip	return(-1);
1362143611Sphilip}
1363143611Sphilip
1364205280Ssyrinxstatic int
1365205607Ssyrinxpfa_table_addrs(u_int sidx, struct pfr_table *pt)
1366205607Ssyrinx{
1367205607Ssyrinx	struct pfioc_table io;
1368205607Ssyrinx	struct pfr_astats *t = NULL;
1369205607Ssyrinx	struct pfa_entry *e;
1370205607Ssyrinx	int i, numaddrs = 1;
1371205607Ssyrinx
1372205607Ssyrinx	if (pt == NULL)
1373205607Ssyrinx		return (-1);
1374205607Ssyrinx
1375205607Ssyrinx	memset(&io, 0, sizeof(io));
1376205607Ssyrinx	strlcpy(io.pfrio_table.pfrt_name, pt->pfrt_name,
1377205607Ssyrinx	    sizeof(io.pfrio_table.pfrt_name));
1378205607Ssyrinx
1379205607Ssyrinx	for (;;) {
1380205607Ssyrinx		t = reallocf(t, numaddrs * sizeof(struct pfr_astats));
1381205607Ssyrinx		if (t == NULL) {
1382205607Ssyrinx			syslog(LOG_ERR, "pfa_table_addrs(): reallocf(): %s",
1383205607Ssyrinx			    strerror(errno));
1384205607Ssyrinx			numaddrs = -1;
1385205607Ssyrinx			goto error;
1386205607Ssyrinx		}
1387205607Ssyrinx
1388205607Ssyrinx		memset(t, 0, sizeof(*t));
1389205607Ssyrinx		io.pfrio_size = numaddrs;
1390205607Ssyrinx		io.pfrio_buffer = t;
1391205607Ssyrinx		io.pfrio_esize = sizeof(struct pfr_astats);
1392205607Ssyrinx
1393205607Ssyrinx		if (ioctl(dev, DIOCRGETASTATS, &io)) {
1394205607Ssyrinx			syslog(LOG_ERR, "pfa_table_addrs(): ioctl() on %s: %s",
1395205607Ssyrinx			    pt->pfrt_name, strerror(errno));
1396205607Ssyrinx			numaddrs = -1;
1397205607Ssyrinx			break;
1398205607Ssyrinx		}
1399205607Ssyrinx
1400205607Ssyrinx		if (numaddrs >= io.pfrio_size)
1401205607Ssyrinx			break;
1402205607Ssyrinx
1403205607Ssyrinx		numaddrs = io.pfrio_size;
1404205607Ssyrinx	}
1405205607Ssyrinx
1406205607Ssyrinx	for (i = 0; i < numaddrs; i++) {
1407205607Ssyrinx		if ((t + i)->pfras_a.pfra_af != AF_INET &&
1408205607Ssyrinx		    (t + i)->pfras_a.pfra_af != AF_INET6) {
1409205607Ssyrinx			numaddrs = i;
1410205607Ssyrinx			break;
1411205607Ssyrinx		}
1412205607Ssyrinx
1413205607Ssyrinx		e = (struct pfa_entry *)malloc(sizeof(struct pfa_entry));
1414205607Ssyrinx		if (e == NULL) {
1415205607Ssyrinx			syslog(LOG_ERR, "pfa_table_addrs(): malloc(): %s",
1416205607Ssyrinx			    strerror(errno));
1417205607Ssyrinx			numaddrs = -1;
1418205607Ssyrinx			break;
1419205607Ssyrinx		}
1420205607Ssyrinx		e->index = sidx + i;
1421205607Ssyrinx		memcpy(&e->pfas, t + i, sizeof(struct pfr_astats));
1422205607Ssyrinx		TAILQ_INSERT_TAIL(&pfa_table, e, link);
1423205607Ssyrinx	}
1424205607Ssyrinx
1425205607Ssyrinx	free(t);
1426205607Ssyrinxerror:
1427205607Ssyrinx	return (numaddrs);
1428205607Ssyrinx}
1429205607Ssyrinx
1430205607Ssyrinxstatic int
1431205607Ssyrinxpfa_refresh(void)
1432205607Ssyrinx{
1433205607Ssyrinx	struct pfioc_table io;
1434205607Ssyrinx	struct pfr_table *pt = NULL, *it = NULL;
1435205607Ssyrinx	struct pfa_entry *e;
1436205607Ssyrinx	int i, numtbls = 1, cidx, naddrs;
1437205607Ssyrinx
1438205607Ssyrinx	if (started && this_tick <= pf_tick)
1439205607Ssyrinx		return (0);
1440205607Ssyrinx
1441205607Ssyrinx	while (!TAILQ_EMPTY(&pfa_table)) {
1442205607Ssyrinx		e = TAILQ_FIRST(&pfa_table);
1443205607Ssyrinx		TAILQ_REMOVE(&pfa_table, e, link);
1444205607Ssyrinx		free(e);
1445205607Ssyrinx	}
1446205607Ssyrinx
1447205607Ssyrinx	memset(&io, 0, sizeof(io));
1448205607Ssyrinx	io.pfrio_esize = sizeof(struct pfr_table);
1449205607Ssyrinx
1450205607Ssyrinx	for (;;) {
1451205607Ssyrinx		pt = reallocf(pt, numtbls * sizeof(struct pfr_table));
1452205607Ssyrinx		if (pt == NULL) {
1453205607Ssyrinx			syslog(LOG_ERR, "pfa_refresh(): reallocf() %s",
1454205607Ssyrinx			    strerror(errno));
1455205607Ssyrinx			return (-1);
1456205607Ssyrinx		}
1457205607Ssyrinx		memset(pt, 0, sizeof(*pt));
1458205607Ssyrinx		io.pfrio_size = numtbls;
1459205607Ssyrinx		io.pfrio_buffer = pt;
1460205607Ssyrinx
1461205607Ssyrinx		if (ioctl(dev, DIOCRGETTABLES, &io)) {
1462205607Ssyrinx			syslog(LOG_ERR, "pfa_refresh(): ioctl(): %s",
1463205607Ssyrinx			    strerror(errno));
1464205607Ssyrinx			goto err2;
1465205607Ssyrinx		}
1466205607Ssyrinx
1467205607Ssyrinx		if (numtbls >= io.pfrio_size)
1468205607Ssyrinx			break;
1469205607Ssyrinx
1470205607Ssyrinx		numtbls = io.pfrio_size;
1471205607Ssyrinx	}
1472205607Ssyrinx
1473205607Ssyrinx	cidx = 1;
1474205607Ssyrinx
1475205607Ssyrinx	for (it = pt, i = 0; i < numtbls; it++, i++) {
1476205607Ssyrinx		/*
1477205607Ssyrinx		 * Skip the table if not active - ioctl(DIOCRGETASTATS) will
1478205607Ssyrinx		 * return ESRCH for this entry anyway.
1479205607Ssyrinx		 */
1480205607Ssyrinx		if (!(it->pfrt_flags & PFR_TFLAG_ACTIVE))
1481205607Ssyrinx			continue;
1482205607Ssyrinx
1483205607Ssyrinx		if ((naddrs = pfa_table_addrs(cidx, it)) < 0)
1484205607Ssyrinx			goto err1;
1485205607Ssyrinx
1486205607Ssyrinx		cidx += naddrs;
1487205607Ssyrinx	}
1488205607Ssyrinx
1489205607Ssyrinx	pfa_table_age = time(NULL);
1490205607Ssyrinx	pfa_table_count = cidx;
1491205607Ssyrinx	pf_tick = this_tick;
1492205607Ssyrinx
1493205607Ssyrinx	free(pt);
1494205607Ssyrinx	return (0);
1495205607Ssyrinxerr1:
1496205607Ssyrinx	while (!TAILQ_EMPTY(&pfa_table)) {
1497205607Ssyrinx		e = TAILQ_FIRST(&pfa_table);
1498205607Ssyrinx		TAILQ_REMOVE(&pfa_table, e, link);
1499205607Ssyrinx		free(e);
1500205607Ssyrinx	}
1501205607Ssyrinx
1502205607Ssyrinxerr2:
1503205607Ssyrinx	free(pt);
1504205607Ssyrinx	return (-1);
1505205607Ssyrinx}
1506205607Ssyrinx
1507205607Ssyrinxstatic int
1508205280Ssyrinxpfl_scan_ruleset(const char *path)
1509205280Ssyrinx{
1510205280Ssyrinx	struct pfioc_rule pr;
1511205280Ssyrinx	struct pfl_entry *e;
1512205280Ssyrinx	u_int32_t nr, i;
1513205280Ssyrinx
1514205280Ssyrinx	bzero(&pr, sizeof(pr));
1515205280Ssyrinx	strlcpy(pr.anchor, path, sizeof(pr.anchor));
1516205280Ssyrinx	pr.rule.action = PF_PASS;
1517205280Ssyrinx	if (ioctl(dev, DIOCGETRULES, &pr)) {
1518205280Ssyrinx		syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULES): %s",
1519205280Ssyrinx		    strerror(errno));
1520205280Ssyrinx		goto err;
1521205280Ssyrinx	}
1522205280Ssyrinx
1523205280Ssyrinx	for (nr = pr.nr, i = 0; i < nr; i++) {
1524205280Ssyrinx		pr.nr = i;
1525205280Ssyrinx		if (ioctl(dev, DIOCGETRULE, &pr)) {
1526205280Ssyrinx			syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULE):"
1527205280Ssyrinx			    " %s", strerror(errno));
1528205280Ssyrinx			goto err;
1529205280Ssyrinx		}
1530205280Ssyrinx
1531205280Ssyrinx		if (pr.rule.label[0]) {
1532205280Ssyrinx			e = (struct pfl_entry *)malloc(sizeof(*e));
1533205280Ssyrinx			if (e == NULL)
1534205280Ssyrinx				goto err;
1535205280Ssyrinx
1536205280Ssyrinx			strlcpy(e->name, path, sizeof(e->name));
1537205280Ssyrinx			if (path[0])
1538205280Ssyrinx				strlcat(e->name, "/", sizeof(e->name));
1539205280Ssyrinx			strlcat(e->name, pr.rule.label, sizeof(e->name));
1540205280Ssyrinx
1541205280Ssyrinx			e->evals = pr.rule.evaluations;
1542205280Ssyrinx			e->bytes[IN] = pr.rule.bytes[IN];
1543205280Ssyrinx			e->bytes[OUT] = pr.rule.bytes[OUT];
1544205280Ssyrinx			e->pkts[IN] = pr.rule.packets[IN];
1545205280Ssyrinx			e->pkts[OUT] = pr.rule.packets[OUT];
1546205280Ssyrinx			e->index = ++pfl_table_count;
1547205280Ssyrinx
1548205280Ssyrinx			TAILQ_INSERT_TAIL(&pfl_table, e, link);
1549205280Ssyrinx		}
1550205280Ssyrinx	}
1551205280Ssyrinx
1552205280Ssyrinx	return (0);
1553205280Ssyrinx
1554205280Ssyrinxerr:
1555205280Ssyrinx	return (-1);
1556205280Ssyrinx}
1557205280Ssyrinx
1558205280Ssyrinxstatic int
1559205280Ssyrinxpfl_walk_rulesets(const char *path)
1560205280Ssyrinx{
1561205280Ssyrinx	struct pfioc_ruleset prs;
1562205280Ssyrinx	char newpath[MAXPATHLEN];
1563205280Ssyrinx	u_int32_t nr, i;
1564205280Ssyrinx
1565205280Ssyrinx	if (pfl_scan_ruleset(path))
1566205280Ssyrinx		goto err;
1567205280Ssyrinx
1568205280Ssyrinx	bzero(&prs, sizeof(prs));
1569205280Ssyrinx	strlcpy(prs.path, path, sizeof(prs.path));
1570205280Ssyrinx	if (ioctl(dev, DIOCGETRULESETS, &prs)) {
1571205280Ssyrinx		syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESETS): %s",
1572205280Ssyrinx		    strerror(errno));
1573205280Ssyrinx		goto err;
1574205280Ssyrinx	}
1575205280Ssyrinx
1576205280Ssyrinx	for (nr = prs.nr, i = 0; i < nr; i++) {
1577205280Ssyrinx		prs.nr = i;
1578205280Ssyrinx		if (ioctl(dev, DIOCGETRULESET, &prs)) {
1579205280Ssyrinx			syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESET):"
1580205280Ssyrinx			    " %s", strerror(errno));
1581205280Ssyrinx			goto err;
1582205280Ssyrinx		}
1583205280Ssyrinx
1584205280Ssyrinx		if (strcmp(prs.name, PF_RESERVED_ANCHOR) == 0)
1585205280Ssyrinx			continue;
1586205280Ssyrinx
1587205280Ssyrinx		strlcpy(newpath, path, sizeof(newpath));
1588205280Ssyrinx		if (path[0])
1589205280Ssyrinx			strlcat(newpath, "/", sizeof(newpath));
1590205280Ssyrinx
1591205280Ssyrinx		strlcat(newpath, prs.name, sizeof(newpath));
1592205280Ssyrinx		if (pfl_walk_rulesets(newpath))
1593205280Ssyrinx			goto err;
1594205280Ssyrinx	}
1595205280Ssyrinx
1596205280Ssyrinx	return (0);
1597205280Ssyrinx
1598205280Ssyrinxerr:
1599205280Ssyrinx	return (-1);
1600205280Ssyrinx}
1601205280Ssyrinx
1602205280Ssyrinxstatic int
1603205280Ssyrinxpfl_refresh(void)
1604205280Ssyrinx{
1605205280Ssyrinx	struct pfl_entry *e;
1606205280Ssyrinx
1607205280Ssyrinx	if (started && this_tick <= pf_tick)
1608205280Ssyrinx		return (0);
1609205280Ssyrinx
1610205280Ssyrinx	while (!TAILQ_EMPTY(&pfl_table)) {
1611205280Ssyrinx		e = TAILQ_FIRST(&pfl_table);
1612205280Ssyrinx		TAILQ_REMOVE(&pfl_table, e, link);
1613205280Ssyrinx		free(e);
1614205280Ssyrinx	}
1615205280Ssyrinx	pfl_table_count = 0;
1616205280Ssyrinx
1617205280Ssyrinx	if (pfl_walk_rulesets(""))
1618205280Ssyrinx		goto err;
1619205280Ssyrinx
1620205280Ssyrinx	pfl_table_age = time(NULL);
1621205280Ssyrinx	pf_tick = this_tick;
1622205280Ssyrinx
1623205280Ssyrinx	return (0);
1624205280Ssyrinx
1625205280Ssyrinxerr:
1626205280Ssyrinx	while (!TAILQ_EMPTY(&pfl_table)) {
1627205280Ssyrinx		e = TAILQ_FIRST(&pfl_table);
1628205280Ssyrinx		TAILQ_REMOVE(&pfl_table, e, link);
1629205280Ssyrinx		free(e);
1630205280Ssyrinx	}
1631205280Ssyrinx	pfl_table_count = 0;
1632205280Ssyrinx
1633205280Ssyrinx	return (-1);
1634205280Ssyrinx}
1635205280Ssyrinx
1636143611Sphilip/*
1637152970Sphilip * check whether altq support is enabled in kernel
1638152970Sphilip */
1639152970Sphilip
1640152970Sphilipstatic int
1641152970Sphilipaltq_is_enabled(int pfdev)
1642152970Sphilip{
1643152970Sphilip        struct pfioc_altq pa;
1644152970Sphilip
1645152970Sphilip	errno = 0;
1646152970Sphilip        if (ioctl(pfdev, DIOCGETALTQS, &pa)) {
1647152970Sphilip                if (errno == ENODEV) {
1648152970Sphilip			syslog(LOG_INFO, "No ALTQ support in kernel\n"
1649152970Sphilip			    "ALTQ related functions disabled\n");
1650152970Sphilip                        return (0);
1651310901Sngie                } else
1652152970Sphilip                        syslog(LOG_ERR, "DIOCGETALTQS returned an error: %s",
1653152970Sphilip			    strerror(errno));
1654152970Sphilip			return (-1);
1655152970Sphilip        }
1656152970Sphilip        return (1);
1657152970Sphilip}
1658152970Sphilip
1659152970Sphilip/*
1660143611Sphilip * Implement the bsnmpd module interface
1661143611Sphilip */
1662143611Sphilipstatic int
1663143611Sphilippf_init(struct lmodule *mod, int __unused argc, char __unused *argv[])
1664143611Sphilip{
1665143611Sphilip	module = mod;
1666143611Sphilip
1667143611Sphilip	if ((dev = open("/dev/pf", O_RDONLY)) == -1) {
1668143611Sphilip		syslog(LOG_ERR, "pf_init(): open(): %s\n",
1669143611Sphilip		    strerror(errno));
1670143611Sphilip		return (-1);
1671143611Sphilip	}
1672143611Sphilip
1673152970Sphilip	if ((altq_enabled = altq_is_enabled(dev)) == -1) {
1674152970Sphilip		syslog(LOG_ERR, "pf_init(): altq test failed");
1675152970Sphilip		return (-1);
1676152970Sphilip	}
1677310901Sngie
1678143611Sphilip	/* Prepare internal state */
1679143611Sphilip	TAILQ_INIT(&pfi_table);
1680143611Sphilip	TAILQ_INIT(&pfq_table);
1681143611Sphilip	TAILQ_INIT(&pft_table);
1682205607Ssyrinx	TAILQ_INIT(&pfa_table);
1683205280Ssyrinx	TAILQ_INIT(&pfl_table);
1684143611Sphilip
1685143611Sphilip	pfi_refresh();
1686152970Sphilip	if (altq_enabled) {
1687152970Sphilip		pfq_refresh();
1688152970Sphilip	}
1689152970Sphilip
1690143611Sphilip	pfs_refresh();
1691143611Sphilip	pft_refresh();
1692205607Ssyrinx	pfa_refresh();
1693205280Ssyrinx	pfl_refresh();
1694143611Sphilip
1695143611Sphilip	started = 1;
1696143611Sphilip
1697143611Sphilip	return (0);
1698143611Sphilip}
1699143611Sphilip
1700143611Sphilipstatic int
1701143611Sphilippf_fini(void)
1702143611Sphilip{
1703143611Sphilip	struct pfi_entry *i1, *i2;
1704143611Sphilip	struct pfq_entry *q1, *q2;
1705143611Sphilip	struct pft_entry *t1, *t2;
1706205607Ssyrinx	struct pfa_entry *a1, *a2;
1707205280Ssyrinx	struct pfl_entry *l1, *l2;
1708143611Sphilip
1709143611Sphilip	/* Empty the list of interfaces */
1710143611Sphilip	i1 = TAILQ_FIRST(&pfi_table);
1711143611Sphilip	while (i1 != NULL) {
1712143611Sphilip		i2 = TAILQ_NEXT(i1, link);
1713143611Sphilip		free(i1);
1714143611Sphilip		i1 = i2;
1715143611Sphilip	}
1716143611Sphilip
1717143611Sphilip	/* List of queues */
1718143611Sphilip	q1 = TAILQ_FIRST(&pfq_table);
1719143611Sphilip	while (q1 != NULL) {
1720143611Sphilip		q2 = TAILQ_NEXT(q1, link);
1721143611Sphilip		free(q1);
1722143611Sphilip		q1 = q2;
1723143611Sphilip	}
1724143611Sphilip
1725205280Ssyrinx	/* List of tables */
1726143611Sphilip	t1 = TAILQ_FIRST(&pft_table);
1727143611Sphilip	while (t1 != NULL) {
1728143611Sphilip		t2 = TAILQ_NEXT(t1, link);
1729143611Sphilip		free(t1);
1730143611Sphilip		t1 = t2;
1731143611Sphilip	}
1732143611Sphilip
1733205607Ssyrinx	/* List of table addresses */
1734205607Ssyrinx	a1 = TAILQ_FIRST(&pfa_table);
1735205607Ssyrinx	while (a1 != NULL) {
1736205607Ssyrinx		a2 = TAILQ_NEXT(a1, link);
1737205607Ssyrinx		free(a1);
1738205607Ssyrinx		a1 = a2;
1739205607Ssyrinx	}
1740205607Ssyrinx
1741205280Ssyrinx	/* And the list of labeled filter rules */
1742205280Ssyrinx	l1 = TAILQ_FIRST(&pfl_table);
1743205280Ssyrinx	while (l1 != NULL) {
1744205280Ssyrinx		l2 = TAILQ_NEXT(l1, link);
1745205280Ssyrinx		free(l1);
1746205280Ssyrinx		l1 = l2;
1747205280Ssyrinx	}
1748205280Ssyrinx
1749143611Sphilip	close(dev);
1750143611Sphilip	return (0);
1751143611Sphilip}
1752143611Sphilip
1753143611Sphilipstatic void
1754143611Sphilippf_dump(void)
1755143611Sphilip{
1756143611Sphilip	pfi_refresh();
1757152970Sphilip	if (altq_enabled) {
1758152970Sphilip		pfq_refresh();
1759152970Sphilip	}
1760143611Sphilip	pft_refresh();
1761205607Ssyrinx	pfa_refresh();
1762205280Ssyrinx	pfl_refresh();
1763143611Sphilip
1764143654Sphilip	syslog(LOG_ERR, "Dump: pfi_table_age = %jd",
1765143654Sphilip	    (intmax_t)pfi_table_age);
1766143611Sphilip	syslog(LOG_ERR, "Dump: pfi_table_count = %d",
1767143611Sphilip	    pfi_table_count);
1768310901Sngie
1769143654Sphilip	syslog(LOG_ERR, "Dump: pfq_table_age = %jd",
1770143654Sphilip	    (intmax_t)pfq_table_age);
1771143611Sphilip	syslog(LOG_ERR, "Dump: pfq_table_count = %d",
1772143611Sphilip	    pfq_table_count);
1773143611Sphilip
1774143654Sphilip	syslog(LOG_ERR, "Dump: pft_table_age = %jd",
1775143654Sphilip	    (intmax_t)pft_table_age);
1776143611Sphilip	syslog(LOG_ERR, "Dump: pft_table_count = %d",
1777143611Sphilip	    pft_table_count);
1778205280Ssyrinx
1779205607Ssyrinx	syslog(LOG_ERR, "Dump: pfa_table_age = %jd",
1780205607Ssyrinx	    (intmax_t)pfa_table_age);
1781205607Ssyrinx	syslog(LOG_ERR, "Dump: pfa_table_count = %d",
1782205607Ssyrinx	    pfa_table_count);
1783205607Ssyrinx
1784205280Ssyrinx	syslog(LOG_ERR, "Dump: pfl_table_age = %jd",
1785205280Ssyrinx	    (intmax_t)pfl_table_age);
1786205280Ssyrinx	syslog(LOG_ERR, "Dump: pfl_table_count = %d",
1787205280Ssyrinx	    pfl_table_count);
1788143611Sphilip}
1789143611Sphilip
1790143611Sphilipconst struct snmp_module config = {
1791143611Sphilip	.comment = "This module implements a MIB for the pf packet filter.",
1792143611Sphilip	.init =		pf_init,
1793143611Sphilip	.fini =		pf_fini,
1794143611Sphilip	.tree =		pf_ctree,
1795143611Sphilip	.dump =		pf_dump,
1796143611Sphilip	.tree_size =	pf_CTREE_SIZE,
1797143611Sphilip};
1798