GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/snmpd/mib.c Lines: 11 1716 0.6 %
Date: 2017-11-13 Branches: 0 692 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: mib.c,v 1.84 2017/06/01 14:38:28 patrick Exp $	*/
2
3
/*
4
 * Copyright (c) 2012 Joel Knight <joel@openbsd.org>
5
 * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/param.h>	/* MAXCOMLEN */
21
#include <sys/queue.h>
22
#include <sys/proc.h>
23
#include <sys/stat.h>
24
#include <sys/socket.h>
25
#include <sys/un.h>
26
#include <sys/time.h>
27
#include <sys/tree.h>
28
#include <sys/utsname.h>
29
#include <sys/sysctl.h>
30
#include <sys/sensors.h>
31
#include <sys/sched.h>
32
#include <sys/mount.h>
33
#include <sys/ioctl.h>
34
#include <sys/disk.h>
35
36
#include <netinet/in.h>
37
#include <netinet/ip.h>
38
#include <netinet/ip_carp.h>
39
#include <netinet/ip_var.h>
40
#include <arpa/inet.h>
41
#include <net/if.h>
42
#include <net/if_types.h>
43
#include <net/pfvar.h>
44
#include <netinet/ip_ipsp.h>
45
#include <net/if_pfsync.h>
46
47
#include <stdlib.h>
48
#include <stdio.h>
49
#include <errno.h>
50
#include <event.h>
51
#include <fcntl.h>
52
#include <string.h>
53
#include <time.h>
54
#include <unistd.h>
55
#include <pwd.h>
56
#include <limits.h>
57
#include <kvm.h>
58
59
#include "snmpd.h"
60
#include "mib.h"
61
62
/*
63
 * Defined in SNMPv2-MIB.txt (RFC 3418)
64
 */
65
66
int	 mib_getsys(struct oid *, struct ber_oid *, struct ber_element **);
67
int	 mib_getsnmp(struct oid *, struct ber_oid *, struct ber_element **);
68
int	 mib_sysor(struct oid *, struct ber_oid *, struct ber_element **);
69
int	 mib_setsnmp(struct oid *, struct ber_oid *, struct ber_element **);
70
71
static struct oid mib_tree[] = MIB_TREE;
72
static struct ber_oid zerodotzero = { { 0, 0 }, 2 };
73
74
#define sizeofa(_a) (sizeof(_a) / sizeof((_a)[0]))
75
76
/* base MIB tree */
77
static struct oid base_mib[] = {
78
	{ MIB(mib_2),			OID_MIB },
79
	{ MIB(sysDescr),		OID_RD, mib_getsys },
80
	{ MIB(sysOID),			OID_RD, mib_getsys },
81
	{ MIB(sysUpTime),		OID_RD, mib_getsys },
82
	{ MIB(sysContact),		OID_RW, mib_getsys, mps_setstr },
83
	{ MIB(sysName),			OID_RW, mib_getsys, mps_setstr },
84
	{ MIB(sysLocation),		OID_RW, mib_getsys, mps_setstr },
85
	{ MIB(sysServices),		OID_RS, mib_getsys },
86
	{ MIB(sysORLastChange),		OID_RD, mps_getts },
87
	{ MIB(sysORIndex),		OID_TRD, mib_sysor },
88
	{ MIB(sysORID),			OID_TRD, mib_sysor },
89
	{ MIB(sysORDescr),		OID_TRD, mib_sysor },
90
	{ MIB(sysORUpTime),		OID_TRD, mib_sysor },
91
	{ MIB(snmp),			OID_MIB },
92
	{ MIB(snmpInPkts),		OID_RD, mib_getsnmp },
93
	{ MIB(snmpOutPkts),		OID_RD, mib_getsnmp },
94
	{ MIB(snmpInBadVersions),	OID_RD, mib_getsnmp },
95
	{ MIB(snmpInBadCommunityNames),	OID_RD, mib_getsnmp },
96
	{ MIB(snmpInBadCommunityUses),	OID_RD, mib_getsnmp },
97
	{ MIB(snmpInASNParseErrs),	OID_RD, mib_getsnmp },
98
	{ MIB(snmpInTooBigs),		OID_RD,	mib_getsnmp },
99
	{ MIB(snmpInNoSuchNames),	OID_RD, mib_getsnmp },
100
	{ MIB(snmpInBadValues),		OID_RD, mib_getsnmp },
101
	{ MIB(snmpInReadOnlys),		OID_RD, mib_getsnmp },
102
	{ MIB(snmpInGenErrs),		OID_RD, mib_getsnmp },
103
	{ MIB(snmpInTotalReqVars),	OID_RD, mib_getsnmp },
104
	{ MIB(snmpInTotalSetVars),	OID_RD, mib_getsnmp },
105
	{ MIB(snmpInGetRequests),	OID_RD, mib_getsnmp },
106
	{ MIB(snmpInGetNexts),		OID_RD, mib_getsnmp },
107
	{ MIB(snmpInSetRequests),	OID_RD, mib_getsnmp },
108
	{ MIB(snmpInGetResponses),	OID_RD, mib_getsnmp },
109
	{ MIB(snmpInTraps),		OID_RD, mib_getsnmp },
110
	{ MIB(snmpOutTooBigs),		OID_RD, mib_getsnmp },
111
	{ MIB(snmpOutNoSuchNames),	OID_RD, mib_getsnmp },
112
	{ MIB(snmpOutBadValues),	OID_RD, mib_getsnmp },
113
	{ MIB(snmpOutGenErrs),		OID_RD, mib_getsnmp },
114
	{ MIB(snmpOutGetRequests),	OID_RD, mib_getsnmp },
115
	{ MIB(snmpOutGetNexts),		OID_RD, mib_getsnmp },
116
	{ MIB(snmpOutSetRequests),	OID_RD, mib_getsnmp },
117
	{ MIB(snmpOutGetResponses),	OID_RD, mib_getsnmp },
118
	{ MIB(snmpOutTraps),		OID_RD, mib_getsnmp },
119
	{ MIB(snmpEnableAuthenTraps),	OID_RW, mib_getsnmp, mib_setsnmp },
120
	{ MIB(snmpSilentDrops),		OID_RD, mib_getsnmp },
121
	{ MIB(snmpProxyDrops),		OID_RD, mib_getsnmp },
122
	{ MIBEND }
123
};
124
125
int
126
mib_getsys(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
127
{
128
	struct ber_oid		 sysoid = OID(MIB_SYSOID_DEFAULT);
129
	char			*s = oid->o_data;
130
	struct ber_oid		*so = oid->o_data;
131
	struct utsname		 u;
132
	long long		 ticks;
133
134
	if (uname(&u) == -1)
135
		return (-1);
136
137
	switch (oid->o_oid[OIDIDX_system]) {
138
	case 1:
139
		if (s == NULL) {
140
			if (asprintf(&s, "%s %s %s %s %s",
141
			    u.sysname, u.nodename, u.release,
142
			    u.version, u.machine) == -1)
143
				return (-1);
144
			oid->o_data = s;
145
			oid->o_val = strlen(s);
146
		}
147
		*elm = ber_add_string(*elm, s);
148
		break;
149
	case 2:
150
		if (so == NULL)
151
			so = &sysoid;
152
		smi_oidlen(so);
153
		*elm = ber_add_oid(*elm, so);
154
		break;
155
	case 3:
156
		ticks = smi_getticks();
157
		*elm = ber_add_integer(*elm, ticks);
158
		ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
159
		break;
160
	case 4:
161
		if (s == NULL) {
162
			if (asprintf(&s, "root@%s", u.nodename) == -1)
163
				return (-1);
164
			oid->o_data = s;
165
			oid->o_val = strlen(s);
166
		}
167
		*elm = ber_add_string(*elm, s);
168
		break;
169
	case 5:
170
		if (s == NULL) {
171
			if ((s = strdup(u.nodename)) == NULL)
172
				return (-1);
173
			oid->o_data = s;
174
			oid->o_val = strlen(s);
175
		}
176
		*elm = ber_add_string(*elm, s);
177
		break;
178
	case 6:
179
		if (s == NULL)
180
			s = "";
181
		*elm = ber_add_string(*elm, s);
182
		break;
183
	case 7:
184
		*elm = ber_add_integer(*elm, oid->o_val);
185
		break;
186
	default:
187
		return (-1);
188
	}
189
	return (0);
190
}
191
192
int
193
mib_sysor(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
194
{
195
	struct ber_element	*ber = *elm;
196
	u_int32_t		 idx = 1, nmib = 0;
197
	struct oid		*next, *miboid;
198
	char			 buf[SNMPD_MAXSTRLEN];
199
200
	/* Count MIB root OIDs in the tree */
201
	for (next = NULL;
202
	    (next = smi_foreach(next, OID_MIB)) != NULL; nmib++);
203
204
	/* Get and verify the current row index */
205
	idx = o->bo_id[OIDIDX_sysOREntry];
206
	if (idx > nmib)
207
		return (1);
208
209
	/* Find the MIB root element for this Id */
210
	for (next = miboid = NULL, nmib = 1;
211
	    (next = smi_foreach(next, OID_MIB)) != NULL; nmib++) {
212
		if (nmib == idx)
213
			miboid = next;
214
	}
215
	if (miboid == NULL)
216
		return (-1);
217
218
	/* Tables need to prepend the OID on their own */
219
	ber = ber_add_oid(ber, o);
220
221
	switch (o->bo_id[OIDIDX_sysOR]) {
222
	case 1:
223
		ber = ber_add_integer(ber, idx);
224
		break;
225
	case 2:
226
		ber = ber_add_oid(ber, &miboid->o_id);
227
		break;
228
	case 3:
229
		/*
230
		 * This should be a description of the MIB.
231
		 * But we use the symbolic OID string for now, it may
232
		 * help to display names of internal OIDs.
233
		 */
234
		smi_oid2string(&miboid->o_id, buf, sizeof(buf), 0);
235
		ber = ber_add_string(ber, buf);
236
		break;
237
	case 4:
238
		/*
239
		 * We do not support dynamic loading of MIB at runtime,
240
		 * the sysORUpTime value of 0 will indicate "loaded at
241
		 * startup".
242
		 */
243
		ber = ber_add_integer(ber, 0);
244
		ber_set_header(ber,
245
		    BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
246
		break;
247
	default:
248
		return (-1);
249
	}
250
251
	return (0);
252
}
253
254
int
255
mib_getsnmp(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
256
{
257
	struct snmp_stats	*stats = &snmpd_env->sc_stats;
258
	long long		 i;
259
	struct statsmap {
260
		u_int8_t	 m_id;
261
		u_int32_t	*m_ptr;
262
	}			 mapping[] = {
263
		{ 1, &stats->snmp_inpkts },
264
		{ 2, &stats->snmp_outpkts },
265
		{ 3, &stats->snmp_inbadversions },
266
		{ 4, &stats->snmp_inbadcommunitynames },
267
		{ 5, &stats->snmp_inbadcommunityuses },
268
		{ 6, &stats->snmp_inasnparseerrs },
269
		{ 8, &stats->snmp_intoobigs },
270
		{ 9, &stats->snmp_innosuchnames },
271
		{ 10, &stats->snmp_inbadvalues },
272
		{ 11, &stats->snmp_inreadonlys },
273
		{ 12, &stats->snmp_ingenerrs },
274
		{ 13, &stats->snmp_intotalreqvars },
275
		{ 14, &stats->snmp_intotalsetvars },
276
		{ 15, &stats->snmp_ingetrequests },
277
		{ 16, &stats->snmp_ingetnexts },
278
		{ 17, &stats->snmp_insetrequests },
279
		{ 18, &stats->snmp_ingetresponses },
280
		{ 19, &stats->snmp_intraps },
281
		{ 20, &stats->snmp_outtoobigs },
282
		{ 21, &stats->snmp_outnosuchnames },
283
		{ 22, &stats->snmp_outbadvalues },
284
		{ 24, &stats->snmp_outgenerrs },
285
		{ 25, &stats->snmp_outgetrequests },
286
		{ 26, &stats->snmp_outgetnexts },
287
		{ 27, &stats->snmp_outsetrequests },
288
		{ 28, &stats->snmp_outgetresponses },
289
		{ 29, &stats->snmp_outtraps },
290
		{ 31, &stats->snmp_silentdrops },
291
		{ 32, &stats->snmp_proxydrops }
292
	};
293
294
	switch (oid->o_oid[OIDIDX_snmp]) {
295
	case 30:
296
		i = stats->snmp_enableauthentraps == 1 ? 1 : 2;
297
		*elm = ber_add_integer(*elm, i);
298
		break;
299
	default:
300
		for (i = 0;
301
		    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
302
			if (oid->o_oid[OIDIDX_snmp] == mapping[i].m_id) {
303
				*elm = ber_add_integer(*elm, *mapping[i].m_ptr);
304
				ber_set_header(*elm,
305
				    BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
306
				return (0);
307
			}
308
		}
309
		return (-1);
310
	}
311
312
	return (0);
313
}
314
315
int
316
mib_setsnmp(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
317
{
318
	struct snmp_stats	*stats = &snmpd_env->sc_stats;
319
	long long		 i;
320
321
	if (ber_get_integer(*elm, &i) == -1)
322
		return (-1);
323
324
	stats->snmp_enableauthentraps = i == 1 ? 1 : 0;
325
326
	return (0);
327
}
328
329
/*
330
 * Defined in SNMP-USER-BASED-SM-MIB.txt (RFC 3414)
331
 */
332
int	 mib_engine(struct oid *, struct ber_oid *, struct ber_element **);
333
int	 mib_usmstats(struct oid *, struct ber_oid *, struct ber_element **);
334
335
static struct oid usm_mib[] = {
336
	{ MIB(snmpEngine),			OID_MIB },
337
	{ MIB(snmpEngineID),			OID_RD, mib_engine },
338
	{ MIB(snmpEngineBoots),			OID_RD, mib_engine },
339
	{ MIB(snmpEngineTime),			OID_RD, mib_engine },
340
	{ MIB(snmpEngineMaxMsgSize),		OID_RD, mib_engine },
341
	{ MIB(usmStats),			OID_MIB },
342
	{ MIB(usmStatsUnsupportedSecLevels),	OID_RD, mib_usmstats },
343
	{ MIB(usmStatsNotInTimeWindow),		OID_RD, mib_usmstats },
344
	{ MIB(usmStatsUnknownUserNames),	OID_RD, mib_usmstats },
345
	{ MIB(usmStatsUnknownEngineId),		OID_RD, mib_usmstats },
346
	{ MIB(usmStatsWrongDigests),		OID_RD, mib_usmstats },
347
	{ MIB(usmStatsDecryptionErrors),	OID_RD, mib_usmstats },
348
	{ MIBEND }
349
};
350
351
int
352
mib_engine(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
353
{
354
	switch (oid->o_oid[OIDIDX_snmpEngine]) {
355
	case 1:
356
		*elm = ber_add_nstring(*elm, snmpd_env->sc_engineid,
357
		    snmpd_env->sc_engineid_len);
358
		break;
359
	case 2:
360
		*elm = ber_add_integer(*elm, snmpd_env->sc_engine_boots);
361
		break;
362
	case 3:
363
		*elm = ber_add_integer(*elm, snmpd_engine_time());
364
		break;
365
	case 4:
366
		*elm = ber_add_integer(*elm, READ_BUF_SIZE);
367
		break;
368
	default:
369
		return -1;
370
	}
371
	return 0;
372
}
373
374
int
375
mib_usmstats(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
376
{
377
	struct snmp_stats	*stats = &snmpd_env->sc_stats;
378
	long long		 i;
379
	struct statsmap {
380
		u_int8_t	 m_id;
381
		u_int32_t	*m_ptr;
382
	}			 mapping[] = {
383
		{ OIDVAL_usmErrSecLevel,	&stats->snmp_usmbadseclevel },
384
		{ OIDVAL_usmErrTimeWindow,	&stats->snmp_usmtimewindow },
385
		{ OIDVAL_usmErrUserName,	&stats->snmp_usmnosuchuser },
386
		{ OIDVAL_usmErrEngineId,	&stats->snmp_usmnosuchengine },
387
		{ OIDVAL_usmErrDigest,		&stats->snmp_usmwrongdigest },
388
		{ OIDVAL_usmErrDecrypt,		&stats->snmp_usmdecrypterr },
389
	};
390
391
	for (i = 0; (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
392
		if (oid->o_oid[OIDIDX_usmStats] == mapping[i].m_id) {
393
			*elm = ber_add_integer(*elm, *mapping[i].m_ptr);
394
			ber_set_header(*elm, BER_CLASS_APPLICATION,
395
			    SNMP_T_COUNTER32);
396
			return (0);
397
		}
398
	}
399
	return (-1);
400
}
401
402
/*
403
 * Defined in HOST-RESOURCES-MIB.txt (RFC 2790)
404
 */
405
406
int	 mib_hrsystemuptime(struct oid *, struct ber_oid *, struct ber_element **);
407
int	 mib_hrsystemdate(struct oid *, struct ber_oid *, struct ber_element **);
408
int	 mib_hrsystemprocs(struct oid *, struct ber_oid *, struct ber_element **);
409
int	 mib_hrmemory(struct oid *, struct ber_oid *, struct ber_element **);
410
int	 mib_hrstorage(struct oid *, struct ber_oid *, struct ber_element **);
411
int	 mib_hrdevice(struct oid *, struct ber_oid *, struct ber_element **);
412
int	 mib_hrprocessor(struct oid *, struct ber_oid *, struct ber_element **);
413
int	 mib_hrswrun(struct oid *, struct ber_oid *, struct ber_element **);
414
415
int	 kinfo_proc_comp(const void *, const void *);
416
int	 kinfo_proc(u_int32_t, struct kinfo_proc **);
417
int	 kinfo_args(struct kinfo_proc *, char **);
418
419
static struct oid hr_mib[] = {
420
	{ MIB(host),				OID_MIB },
421
	{ MIB(hrSystemUptime),			OID_RD, mib_hrsystemuptime },
422
	{ MIB(hrSystemDate),			OID_RD, mib_hrsystemdate },
423
	{ MIB(hrSystemProcesses),		OID_RD, mib_hrsystemprocs },
424
	{ MIB(hrSystemMaxProcesses),		OID_RD, mib_hrsystemprocs },
425
	{ MIB(hrMemorySize),			OID_RD,	mib_hrmemory },
426
	{ MIB(hrStorageIndex),			OID_TRD, mib_hrstorage },
427
	{ MIB(hrStorageType),			OID_TRD, mib_hrstorage },
428
	{ MIB(hrStorageDescr),			OID_TRD, mib_hrstorage },
429
	{ MIB(hrStorageAllocationUnits),	OID_TRD, mib_hrstorage },
430
	{ MIB(hrStorageSize),			OID_TRD, mib_hrstorage },
431
	{ MIB(hrStorageUsed),			OID_TRD, mib_hrstorage },
432
	{ MIB(hrStorageAllocationFailures),	OID_TRD, mib_hrstorage },
433
	{ MIB(hrDeviceIndex),			OID_TRD, mib_hrdevice },
434
	{ MIB(hrDeviceType),			OID_TRD, mib_hrdevice },
435
	{ MIB(hrDeviceDescr),			OID_TRD, mib_hrdevice },
436
	{ MIB(hrDeviceID),			OID_TRD, mib_hrdevice },
437
	{ MIB(hrDeviceStatus),			OID_TRD, mib_hrdevice },
438
	{ MIB(hrDeviceErrors),			OID_TRD, mib_hrdevice },
439
	{ MIB(hrProcessorFrwID),		OID_TRD, mib_hrprocessor },
440
	{ MIB(hrProcessorLoad),			OID_TRD, mib_hrprocessor },
441
	{ MIB(hrSWRunIndex),			OID_TRD, mib_hrswrun },
442
	{ MIB(hrSWRunName),			OID_TRD, mib_hrswrun },
443
	{ MIB(hrSWRunID),			OID_TRD, mib_hrswrun },
444
	{ MIB(hrSWRunPath),			OID_TRD, mib_hrswrun },
445
	{ MIB(hrSWRunParameters),		OID_TRD, mib_hrswrun },
446
	{ MIB(hrSWRunType),			OID_TRD, mib_hrswrun },
447
	{ MIB(hrSWRunStatus),			OID_TRD, mib_hrswrun },
448
	{ MIBEND }
449
};
450
451
int
452
mib_hrsystemuptime(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
453
{
454
	struct timeval   boottime;
455
	int		 mib[] = { CTL_KERN, KERN_BOOTTIME };
456
	time_t		 now;
457
	size_t		 len;
458
459
	(void)time(&now);
460
	len = sizeof(boottime);
461
462
	if (sysctl(mib, 2, &boottime, &len, NULL, 0) == -1)
463
		return (-1);
464
465
	*elm = ber_add_integer(*elm, (now - boottime.tv_sec) * 100);
466
	ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
467
468
	return (0);
469
}
470
471
int
472
mib_hrsystemdate(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
473
{
474
	struct tm	*ptm;
475
	u_char		 s[11];
476
	time_t		 now;
477
	int		 tzoffset;
478
	unsigned short	 year;
479
480
	(void)time(&now);
481
	ptm = localtime(&now);
482
483
	year = htons(ptm->tm_year + 1900);
484
	memcpy(s, &year, 2);
485
	s[2] = ptm->tm_mon + 1;
486
	s[3] = ptm->tm_mday;
487
	s[4] = ptm->tm_hour;
488
	s[5] = ptm->tm_min;
489
	s[6] = ptm->tm_sec;
490
	s[7] = 0;
491
492
	tzoffset = ptm->tm_gmtoff;
493
	if (tzoffset < 0)
494
		s[8] = '-';
495
	else
496
		s[8] = '+';
497
498
	s[9] = abs(tzoffset) / 3600;
499
	s[10] = (abs(tzoffset) - (s[9] * 3600)) / 60;
500
501
	*elm = ber_add_nstring(*elm, s, sizeof(s));
502
503
	return (0);
504
}
505
506
int
507
mib_hrsystemprocs(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
508
{
509
	char		 errbuf[_POSIX2_LINE_MAX];
510
	int		 val;
511
	int		 mib[] = { CTL_KERN, KERN_MAXPROC };
512
	kvm_t		*kd;
513
	size_t		 len;
514
515
	switch (oid->o_oid[OIDIDX_hrsystem]) {
516
	case 6:
517
		if ((kd = kvm_openfiles(NULL, NULL, NULL,
518
		    KVM_NO_FILES, errbuf)) == NULL)
519
			return (-1);
520
521
		if (kvm_getprocs(kd, KERN_PROC_ALL, 0,
522
		    sizeof(struct kinfo_proc), &val) == NULL)
523
			return (-1);
524
525
		*elm = ber_add_integer(*elm, val);
526
		ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_GAUGE32);
527
528
		kvm_close(kd);
529
		break;
530
	case 7:
531
		len = sizeof(val);
532
		if (sysctl(mib, 2, &val, &len, NULL, 0) == -1)
533
			return (-1);
534
535
		*elm = ber_add_integer(*elm, val);
536
		break;
537
	default:
538
		return (-1);
539
	}
540
541
	return (0);
542
}
543
544
int
545
mib_hrmemory(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
546
{
547
	struct ber_element	*ber = *elm;
548
	int			 mib[] = { CTL_HW, HW_PHYSMEM64 };
549
	u_int64_t		 physmem;
550
	size_t			 len = sizeof(physmem);
551
552
	if (sysctl(mib, sizeofa(mib), &physmem, &len, NULL, 0) == -1)
553
		return (-1);
554
555
	ber = ber_add_integer(ber, physmem / 1024);
556
557
	return (0);
558
}
559
560
int
561
mib_hrstorage(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
562
{
563
	struct ber_element	*ber = *elm;
564
	u_int32_t		 idx;
565
	struct statfs		*mntbuf, *mnt;
566
	int			 mntsize, maxsize;
567
	u_int32_t		 units, size, used, fail = 0;
568
	const char		*descr = NULL;
569
	int			 mib[] = { CTL_HW, 0 };
570
	u_int64_t		 physmem, realmem;
571
	struct uvmexp		 uvm;
572
	size_t			 len;
573
	static struct ber_oid	*sop, so[] = {
574
		{ { MIB_hrStorageOther } },
575
		{ { MIB_hrStorageRam } },
576
		{ { MIB_hrStorageVirtualMemory } },
577
		{ { MIB_hrStorageFixedDisk } }
578
	};
579
580
	/* Physical memory, real memory, swap */
581
	mib[1] = HW_PHYSMEM64;
582
	len = sizeof(physmem);
583
	if (sysctl(mib, sizeofa(mib), &physmem, &len, NULL, 0) == -1)
584
		return (-1);
585
	mib[1] = HW_USERMEM64;
586
	len = sizeof(realmem);
587
	if (sysctl(mib, sizeofa(mib), &realmem, &len, NULL, 0) == -1)
588
		return (-1);
589
	mib[0] = CTL_VM;
590
	mib[1] = VM_UVMEXP;
591
	len = sizeof(uvm);
592
	if (sysctl(mib, sizeofa(mib), &uvm, &len, NULL, 0) == -1)
593
		return (-1);
594
	maxsize = 10;
595
596
	/* Disks */
597
	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
598
	if (mntsize)
599
		maxsize = 30 + mntsize;
600
601
	/*
602
	 * Get and verify the current row index.
603
	 *
604
	 * We use a special mapping here that is inspired by other SNMP
605
	 * agents: index 1 + 2 for RAM, index 10 for swap, index 31 and
606
	 * higher for disk storage.
607
	 */
608
	idx = o->bo_id[OIDIDX_hrStorageEntry];
609
	if (idx > (u_int)maxsize)
610
		return (1);
611
	else if (idx > 2 && idx < 10)
612
		idx = 10;
613
	else if (idx > 10 && idx < 31)
614
		idx = 31;
615
616
	sop = &so[0];
617
	switch (idx) {
618
	case 1:
619
		descr = "Physical memory";
620
		units = uvm.pagesize;
621
		size = physmem / uvm.pagesize;
622
		used = size - uvm.free;
623
		sop = &so[1];
624
		break;
625
	case 2:
626
		descr = "Real memory";
627
		units = uvm.pagesize;
628
		size = realmem / uvm.pagesize;
629
		used = size - uvm.free;
630
		sop = &so[1];
631
		break;
632
	case 10:
633
		descr = "Swap space";
634
		units = uvm.pagesize;
635
		size = uvm.swpages;
636
		used = uvm.swpginuse;
637
		sop = &so[2];
638
		break;
639
	default:
640
		mnt = &mntbuf[idx - 31];
641
		descr = mnt->f_mntonname;
642
		units = mnt->f_bsize;
643
		size = mnt->f_blocks;
644
		used = mnt->f_blocks - mnt->f_bfree;
645
		sop = &so[3];
646
		break;
647
	}
648
649
	/* Tables need to prepend the OID on their own */
650
	o->bo_id[OIDIDX_hrStorageEntry] = idx;
651
	ber = ber_add_oid(ber, o);
652
653
	switch (o->bo_id[OIDIDX_hrStorage]) {
654
	case 1: /* hrStorageIndex */
655
		ber = ber_add_integer(ber, idx);
656
		break;
657
	case 2: /* hrStorageType */
658
		smi_oidlen(sop);
659
		ber = ber_add_oid(ber, sop);
660
		break;
661
	case 3: /* hrStorageDescr */
662
		ber = ber_add_string(ber, descr);
663
		break;
664
	case 4: /* hrStorageAllocationUnits */
665
		ber = ber_add_integer(ber, units);
666
		break;
667
	case 5: /* hrStorageSize */
668
		ber = ber_add_integer(ber, size);
669
		break;
670
	case 6: /* hrStorageUsed */
671
		ber = ber_add_integer(ber, used);
672
		break;
673
	case 7: /* hrStorageAllocationFailures */
674
		ber = ber_add_integer(ber, fail);
675
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
676
		break;
677
	default:
678
		return (-1);
679
	}
680
681
	return (0);
682
}
683
684
int
685
mib_hrdevice(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
686
{
687
	struct ber_element	*ber = *elm;
688
	u_int32_t		 idx, fail = 0;
689
	int			 status;
690
	int			 mib[] = { CTL_HW, HW_MODEL };
691
	size_t			 len;
692
	char			 descr[BUFSIZ];
693
	static struct ber_oid	*sop, so[] = {
694
		{ { MIB_hrDeviceProcessor } },
695
	};
696
697
	/* Get and verify the current row index */
698
	idx = o->bo_id[OIDIDX_hrDeviceEntry];
699
	if (idx > (u_int)snmpd_env->sc_ncpu)
700
		return (1);
701
702
	/* Tables need to prepend the OID on their own */
703
	o->bo_id[OIDIDX_hrDeviceEntry] = idx;
704
	ber = ber_add_oid(ber, o);
705
706
	len = sizeof(descr);
707
	if (sysctl(mib, sizeofa(mib), &descr, &len, NULL, 0) == -1)
708
		return (-1);
709
	/* unknown(1), running(2), warning(3), testing(4), down(5) */
710
	status = 2;
711
	sop = &so[0];
712
713
	switch (o->bo_id[OIDIDX_hrDevice]) {
714
	case 1: /* hrDeviceIndex */
715
		ber = ber_add_integer(ber, idx);
716
		break;
717
	case 2: /* hrDeviceType */
718
		smi_oidlen(sop);
719
		ber = ber_add_oid(ber, sop);
720
		break;
721
	case 3: /* hrDeviceDescr */
722
		ber = ber_add_string(ber, descr);
723
		break;
724
	case 4: /* hrDeviceID */
725
		ber = ber_add_oid(ber, &zerodotzero);
726
		break;
727
	case 5: /* hrDeviceStatus */
728
		ber = ber_add_integer(ber, status);
729
		break;
730
	case 6: /* hrDeviceErrors */
731
		ber = ber_add_integer(ber, fail);
732
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
733
		break;
734
	default:
735
		return (-1);
736
	}
737
738
	return (0);
739
}
740
741
int
742
mib_hrprocessor(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
743
{
744
	struct ber_element	*ber = *elm;
745
	u_int32_t		 idx;
746
	int64_t			*cptime2, val;
747
748
	/* Get and verify the current row index */
749
	idx = o->bo_id[OIDIDX_hrDeviceEntry];
750
	if (idx > (u_int)snmpd_env->sc_ncpu)
751
		return (1);
752
	else if (idx < 1)
753
		idx = 1;
754
755
	/* Tables need to prepend the OID on their own */
756
	o->bo_id[OIDIDX_hrDeviceEntry] = idx;
757
	ber = ber_add_oid(ber, o);
758
759
	switch (o->bo_id[OIDIDX_hrDevice]) {
760
	case 1: /* hrProcessorFrwID */
761
		ber = ber_add_oid(ber, &zerodotzero);
762
		break;
763
	case 2: /* hrProcessorLoad */
764
		/*
765
		 * The percentage of time that the system was not
766
		 * idle during the last minute.
767
		 */
768
		if (snmpd_env->sc_cpustates == NULL)
769
			return (-1);
770
		cptime2 = snmpd_env->sc_cpustates + (CPUSTATES * (idx - 1));
771
		val = 100 -
772
		    (cptime2[CP_IDLE] > 1000 ? 1000 : (cptime2[CP_IDLE] / 10));
773
		ber = ber_add_integer(ber, val);
774
		break;
775
	default:
776
		return (-1);
777
	}
778
779
	return (0);
780
}
781
782
int
783
mib_hrswrun(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
784
{
785
	struct ber_element	*ber = *elm;
786
	struct kinfo_proc	*kinfo;
787
	char			*s;
788
789
	/* Get and verify the current row index */
790
	if (kinfo_proc(o->bo_id[OIDIDX_hrSWRunEntry], &kinfo) == -1)
791
		return (1);
792
793
	if (kinfo == NULL)
794
		return (1);
795
796
	/* Tables need to prepend the OID on their own */
797
	o->bo_id[OIDIDX_hrSWRunEntry] = kinfo->p_pid;
798
	ber = ber_add_oid(ber, o);
799
800
	switch (o->bo_id[OIDIDX_hrSWRun]) {
801
	case 1: /* hrSWRunIndex */
802
		ber = ber_add_integer(ber, kinfo->p_pid);
803
		break;
804
	case 2: /* hrSWRunName */
805
	case 4: /* hrSWRunPath */
806
		ber = ber_add_string(ber, kinfo->p_comm);
807
		break;
808
	case 3: /* hrSWRunID */
809
		ber = ber_add_oid(ber, &zerodotzero);
810
		break;
811
	case 5: /* hrSWRunParameters */
812
		if (kinfo_args(kinfo, &s) == -1)
813
			return (-1);
814
815
		ber = ber_add_string(ber, s);
816
		break;
817
	case 6: /* hrSWRunType */
818
		if (kinfo->p_flag & P_SYSTEM) {
819
			/* operatingSystem(2) */
820
			ber = ber_add_integer(ber, 2);
821
		} else {
822
			/* application(4) */
823
			ber = ber_add_integer(ber, 4);
824
		}
825
		break;
826
	case 7: /* hrSWRunStatus */
827
		switch (kinfo->p_stat) {
828
		case SONPROC:
829
			/* running(1) */
830
			ber = ber_add_integer(ber, 1);
831
			break;
832
		case SIDL:
833
		case SRUN:
834
		case SSLEEP:
835
			/* runnable(2) */
836
			ber = ber_add_integer(ber, 2);
837
			break;
838
		case SSTOP:
839
			/* notRunnable(3) */
840
			ber = ber_add_integer(ber, 3);
841
			break;
842
		case SDEAD:
843
		default:
844
			/* invalid(4) */
845
			ber = ber_add_integer(ber, 4);
846
			break;
847
		}
848
		break;
849
	default:
850
		return (-1);
851
	}
852
853
	return (0);
854
}
855
856
int
857
kinfo_proc_comp(const void *a, const void *b)
858
{
859
	struct kinfo_proc * const *k1 = a;
860
	struct kinfo_proc * const *k2 = b;
861
862
	return (((*k1)->p_pid > (*k2)->p_pid) ? 1 : -1);
863
}
864
865
int
866
kinfo_proc(u_int32_t idx, struct kinfo_proc **kinfo)
867
{
868
	static struct kinfo_proc *kp = NULL;
869
	static size_t		 nkp = 0;
870
	int			 mib[] = { CTL_KERN, KERN_PROC,
871
				    KERN_PROC_ALL, 0, sizeof(*kp), 0 };
872
	struct kinfo_proc	**klist;
873
	size_t			 size, count, i;
874
875
	for (;;) {
876
		size = nkp * sizeof(*kp);
877
		mib[5] = nkp;
878
		if (sysctl(mib, sizeofa(mib), kp, &size, NULL, 0) == -1) {
879
			if (errno == ENOMEM) {
880
				free(kp);
881
				kp = NULL;
882
				nkp = 0;
883
				continue;
884
			}
885
886
			return (-1);
887
		}
888
889
		count = size / sizeof(*kp);
890
		if (count <= nkp)
891
			break;
892
893
		kp = malloc(size);
894
		if (kp == NULL) {
895
			nkp = 0;
896
			return (-1);
897
		}
898
		nkp = count;
899
	}
900
901
	klist = calloc(count, sizeof(*klist));
902
	if (klist == NULL)
903
		return (-1);
904
905
	for (i = 0; i < count; i++)
906
		klist[i] = &kp[i];
907
	qsort(klist, count, sizeof(*klist), kinfo_proc_comp);
908
909
	*kinfo = NULL;
910
	for (i = 0; i < count; i++) {
911
		if (klist[i]->p_pid >= (int32_t)idx) {
912
			*kinfo = klist[i];
913
			break;
914
		}
915
	}
916
	free(klist);
917
918
	return (0);
919
}
920
921
int
922
kinfo_args(struct kinfo_proc *kinfo, char **s)
923
{
924
	static char		 str[128];
925
	static char		*buf = NULL;
926
	static size_t		 buflen = 128;
927
928
	int			 mib[] = { CTL_KERN, KERN_PROC_ARGS,
929
				    kinfo->p_pid, KERN_PROC_ARGV };
930
	char			*nbuf, **argv;
931
932
	if (buf == NULL) {
933
		buf = malloc(buflen);
934
		if (buf == NULL)
935
			return (-1);
936
	}
937
938
	str[0] = '\0';
939
	*s = str;
940
941
	while (sysctl(mib, sizeofa(mib), buf, &buflen, NULL, 0) == -1) {
942
		if (errno != ENOMEM) {
943
			/* some errors are expected, dont get too upset */
944
			return (0);
945
		}
946
947
		nbuf = realloc(buf, buflen + 128);
948
		if (nbuf == NULL)
949
			return (-1);
950
951
		buf = nbuf;
952
		buflen += 128;
953
	}
954
955
	argv = (char **)buf;
956
	if (argv[0] == NULL)
957
		return (0);
958
959
	argv++;
960
	while (*argv != NULL) {
961
		strlcat(str, *argv, sizeof(str));
962
		argv++;
963
		if (*argv != NULL)
964
			strlcat(str, " ", sizeof(str));
965
	}
966
967
	return (0);
968
}
969
970
/*
971
 * Defined in IF-MIB.txt (RFCs 1229, 1573, 2233, 2863)
972
 */
973
974
int	 mib_ifnumber(struct oid *, struct ber_oid *, struct ber_element **);
975
struct kif
976
	*mib_ifget(u_int);
977
int	 mib_iftable(struct oid *, struct ber_oid *, struct ber_element **);
978
int	 mib_ifxtable(struct oid *, struct ber_oid *, struct ber_element **);
979
int	 mib_ifstacklast(struct oid *, struct ber_oid *, struct ber_element **);
980
int	 mib_ifrcvtable(struct oid *, struct ber_oid *, struct ber_element **);
981
982
static u_int8_t ether_zeroaddr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
983
984
static struct oid if_mib[] = {
985
	{ MIB(ifMIB),			OID_MIB },
986
	{ MIB(ifName),			OID_TRD, mib_ifxtable },
987
	{ MIB(ifInMulticastPkts),	OID_TRD, mib_ifxtable },
988
	{ MIB(ifInBroadcastPkts),	OID_TRD, mib_ifxtable },
989
	{ MIB(ifOutMulticastPkts),	OID_TRD, mib_ifxtable },
990
	{ MIB(ifOutBroadcastPkts),	OID_TRD, mib_ifxtable },
991
	{ MIB(ifHCInOctets),		OID_TRD, mib_ifxtable },
992
	{ MIB(ifHCInUcastPkts),		OID_TRD, mib_ifxtable },
993
	{ MIB(ifHCInMulticastPkts),	OID_TRD, mib_ifxtable },
994
	{ MIB(ifHCInBroadcastPkts),	OID_TRD, mib_ifxtable },
995
	{ MIB(ifHCOutOctets),		OID_TRD, mib_ifxtable },
996
	{ MIB(ifHCOutUcastPkts),	OID_TRD, mib_ifxtable },
997
	{ MIB(ifHCOutMulticastPkts),	OID_TRD, mib_ifxtable },
998
	{ MIB(ifHCOutBroadcastPkts),	OID_TRD, mib_ifxtable },
999
	{ MIB(ifLinkUpDownTrapEnable),	OID_TRD, mib_ifxtable },
1000
	{ MIB(ifHighSpeed),		OID_TRD, mib_ifxtable },
1001
	{ MIB(ifPromiscuousMode),	OID_TRD, mib_ifxtable },
1002
	{ MIB(ifConnectorPresent),	OID_TRD, mib_ifxtable },
1003
	{ MIB(ifAlias),			OID_TRD, mib_ifxtable },
1004
	{ MIB(ifCounterDiscontinuityTime), OID_TRD, mib_ifxtable },
1005
	{ MIB(ifRcvAddressStatus),	OID_TRD, mib_ifrcvtable },
1006
	{ MIB(ifRcvAddressType),	OID_TRD, mib_ifrcvtable },
1007
	{ MIB(ifStackLastChange),	OID_RD, mib_ifstacklast },
1008
	{ MIB(ifNumber),		OID_RD, mib_ifnumber },
1009
	{ MIB(ifIndex),			OID_TRD, mib_iftable },
1010
	{ MIB(ifDescr),			OID_TRD, mib_iftable },
1011
	{ MIB(ifType),			OID_TRD, mib_iftable },
1012
	{ MIB(ifMtu),			OID_TRD, mib_iftable },
1013
	{ MIB(ifSpeed),			OID_TRD, mib_iftable },
1014
	{ MIB(ifPhysAddress),		OID_TRD, mib_iftable },
1015
	{ MIB(ifAdminStatus),		OID_TRD, mib_iftable },
1016
	{ MIB(ifOperStatus),		OID_TRD, mib_iftable },
1017
	{ MIB(ifLastChange),		OID_TRD, mib_iftable },
1018
	{ MIB(ifInOctets),		OID_TRD, mib_iftable },
1019
	{ MIB(ifInUcastPkts),		OID_TRD, mib_iftable },
1020
	{ MIB(ifInNUcastPkts),		OID_TRD, mib_iftable },
1021
	{ MIB(ifInDiscards),		OID_TRD, mib_iftable },
1022
	{ MIB(ifInErrors),		OID_TRD, mib_iftable },
1023
	{ MIB(ifInUnknownProtos),	OID_TRD, mib_iftable },
1024
	{ MIB(ifOutOctets),		OID_TRD, mib_iftable },
1025
	{ MIB(ifOutUcastPkts),		OID_TRD, mib_iftable },
1026
	{ MIB(ifOutNUcastPkts),		OID_TRD, mib_iftable },
1027
	{ MIB(ifOutDiscards),		OID_TRD, mib_iftable },
1028
	{ MIB(ifOutErrors),		OID_TRD, mib_iftable },
1029
	{ MIB(ifOutQLen),		OID_TRD, mib_iftable },
1030
	{ MIB(ifSpecific),		OID_TRD, mib_iftable },
1031
	{ MIBEND }
1032
};
1033
1034
int
1035
mib_ifnumber(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1036
{
1037
	*elm = ber_add_integer(*elm, kr_ifnumber());
1038
	return (0);
1039
}
1040
1041
struct kif *
1042
mib_ifget(u_int idx)
1043
{
1044
	struct kif	*kif;
1045
1046
	if ((kif = kr_getif(idx)) == NULL) {
1047
		/*
1048
		 * It may happen that an interface with a specific index
1049
		 * does not exist or has been removed. Jump to the next
1050
		 * available interface index.
1051
		 */
1052
		for (kif = kr_getif(0); kif != NULL;
1053
		    kif = kr_getnextif(kif->if_index))
1054
			if (kif->if_index > idx)
1055
				break;
1056
		if (kif == NULL)
1057
			return (NULL);
1058
	}
1059
	idx = kif->if_index;
1060
1061
	/* Update interface information */
1062
	kr_updateif(idx);
1063
	if ((kif = kr_getif(idx)) == NULL) {
1064
		log_debug("mib_ifxtable: interface %d disappeared?", idx);
1065
		return (NULL);
1066
	}
1067
1068
	return (kif);
1069
}
1070
1071
int
1072
mib_iftable(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1073
{
1074
	struct ber_element	*ber = *elm;
1075
	u_int32_t		 idx = 0;
1076
	struct kif		*kif;
1077
	long long		 i;
1078
	size_t			 len;
1079
	int			 ifq;
1080
	int			 mib[] = { CTL_NET, PF_INET, IPPROTO_IP, 0, 0 };
1081
1082
	/* Get and verify the current row index */
1083
	idx = o->bo_id[OIDIDX_ifEntry];
1084
	if ((kif = mib_ifget(idx)) == NULL)
1085
		return (1);
1086
1087
	/* Tables need to prepend the OID on their own */
1088
	o->bo_id[OIDIDX_ifEntry] = kif->if_index;
1089
	ber = ber_add_oid(ber, o);
1090
1091
	switch (o->bo_id[OIDIDX_if]) {
1092
	case 1:
1093
		ber = ber_add_integer(ber, kif->if_index);
1094
		break;
1095
	case 2:
1096
		/*
1097
		 * The ifDescr should contain a vendor, product, etc.
1098
		 * but we just use the interface name (like ifName).
1099
		 * The interface name includes the driver name on OpenBSD.
1100
		 */
1101
		ber = ber_add_string(ber, kif->if_name);
1102
		break;
1103
	case 3:
1104
		if (kif->if_type >= 0xf0) {
1105
			/*
1106
			 * It does not make sense to announce the private
1107
			 * interface types for CARP, ENC, PFSYNC, etc.
1108
			 */
1109
			ber = ber_add_integer(ber, IFT_OTHER);
1110
		} else
1111
			ber = ber_add_integer(ber, kif->if_type);
1112
		break;
1113
	case 4:
1114
		ber = ber_add_integer(ber, kif->if_mtu);
1115
		break;
1116
	case 5:
1117
		ber = ber_add_integer(ber, kif->if_baudrate);
1118
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_GAUGE32);
1119
		break;
1120
	case 6:
1121
		if (bcmp(kif->if_lladdr, ether_zeroaddr,
1122
		    sizeof(kif->if_lladdr)) == 0) {
1123
			ber = ber_add_string(ber, "");
1124
		} else {
1125
			ber = ber_add_nstring(ber, kif->if_lladdr,
1126
			    sizeof(kif->if_lladdr));
1127
		}
1128
		break;
1129
	case 7:
1130
		/* ifAdminStatus up(1), down(2), testing(3) */
1131
		i = (kif->if_flags & IFF_UP) ? 1 : 2;
1132
		ber = ber_add_integer(ber, i);
1133
		break;
1134
	case 8:
1135
		/* ifOperStatus */
1136
		if ((kif->if_flags & IFF_UP) == 0)
1137
			i = 2;	/* down(2) */
1138
		else if (kif->if_link_state == LINK_STATE_UNKNOWN)
1139
			i = 4;	/* unknown(4) */
1140
		else if (LINK_STATE_IS_UP(kif->if_link_state))
1141
			i = 1;	/* up(1) */
1142
		else
1143
			i = 7;	/* lowerLayerDown(7) or dormant(5)? */
1144
		ber = ber_add_integer(ber, i);
1145
		break;
1146
	case 9:
1147
		ber = ber_add_integer(ber, kif->if_ticks);
1148
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
1149
		break;
1150
	case 10:
1151
		ber = ber_add_integer(ber, (u_int32_t)kif->if_ibytes);
1152
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1153
		break;
1154
	case 11:
1155
		ber = ber_add_integer(ber, (u_int32_t)kif->if_ipackets);
1156
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1157
		break;
1158
	case 12:
1159
		ber = ber_add_integer(ber, (u_int32_t)kif->if_imcasts);
1160
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1161
		break;
1162
	case 13:
1163
		mib[3] = IPCTL_IFQUEUE;
1164
		mib[4] = IFQCTL_DROPS;
1165
		len = sizeof(ifq);
1166
		if (sysctl(mib, sizeofa(mib), &ifq, &len, 0, 0) == -1) {
1167
			log_info("mib_iftable: %s: invalid ifq: %s",
1168
			    kif->if_name, strerror(errno));
1169
			return (-1);
1170
		}
1171
		ber = ber_add_integer(ber, ifq);
1172
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1173
		break;
1174
	case 14:
1175
		ber = ber_add_integer(ber, (u_int32_t)kif->if_ierrors);
1176
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1177
		break;
1178
	case 15:
1179
		ber = ber_add_integer(ber, (u_int32_t)kif->if_noproto);
1180
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1181
		break;
1182
	case 16:
1183
		ber = ber_add_integer(ber, (u_int32_t)kif->if_obytes);
1184
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1185
		break;
1186
	case 17:
1187
		ber = ber_add_integer(ber, (u_int32_t)kif->if_opackets);
1188
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1189
		break;
1190
	case 18:
1191
		ber = ber_add_integer(ber, (u_int32_t)kif->if_omcasts);
1192
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1193
		break;
1194
	case 19:
1195
		ber = ber_add_integer(ber, (u_int32_t)kif->if_oqdrops);
1196
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1197
		break;
1198
	case 20:
1199
		ber = ber_add_integer(ber, (u_int32_t)kif->if_oerrors);
1200
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1201
		break;
1202
	case 21:
1203
		mib[3] = IPCTL_IFQUEUE;
1204
		mib[4] = IFQCTL_LEN;
1205
		len = sizeof(ifq);
1206
		if (sysctl(mib, sizeofa(mib), &ifq, &len, 0, 0) == -1) {
1207
			log_info("mib_iftable: %s: invalid ifq: %s",
1208
			    kif->if_name, strerror(errno));
1209
			return (-1);
1210
		}
1211
		ber = ber_add_integer(ber, ifq);
1212
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_GAUGE32);
1213
		break;
1214
	case 22:
1215
		ber = ber_add_oid(ber, &zerodotzero);
1216
		break;
1217
	default:
1218
		return (-1);
1219
	}
1220
1221
	return (0);
1222
}
1223
1224
int
1225
mib_ifxtable(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1226
{
1227
	struct ber_element	*ber = *elm;
1228
	u_int32_t		 idx = 0;
1229
	struct kif		*kif;
1230
	int			 i = 0;
1231
1232
	/* Get and verify the current row index */
1233
	idx = o->bo_id[OIDIDX_ifXEntry];
1234
	if ((kif = mib_ifget(idx)) == NULL)
1235
		return (1);
1236
1237
	/* Tables need to prepend the OID on their own */
1238
	o->bo_id[OIDIDX_ifXEntry] = kif->if_index;
1239
	ber = ber_add_oid(ber, o);
1240
1241
	switch (o->bo_id[OIDIDX_ifX]) {
1242
	case 1:
1243
		ber = ber_add_string(ber, kif->if_name);
1244
		break;
1245
	case 2:
1246
		ber = ber_add_integer(ber, (u_int32_t)kif->if_imcasts);
1247
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1248
		break;
1249
	case 3:
1250
		ber = ber_add_integer(ber, 0);
1251
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1252
		break;
1253
	case 4:
1254
		ber = ber_add_integer(ber, (u_int32_t)kif->if_omcasts);
1255
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1256
		break;
1257
	case 5:
1258
		ber = ber_add_integer(ber, 0);
1259
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
1260
		break;
1261
	case 6:
1262
		ber = ber_add_integer(ber, (u_int64_t)kif->if_ibytes);
1263
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
1264
		break;
1265
	case 7:
1266
		ber = ber_add_integer(ber, (u_int64_t)kif->if_ipackets);
1267
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
1268
		break;
1269
	case 8:
1270
		ber = ber_add_integer(ber, (u_int64_t)kif->if_imcasts);
1271
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
1272
		break;
1273
	case 9:
1274
		ber = ber_add_integer(ber, 0);
1275
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
1276
		break;
1277
	case 10:
1278
		ber = ber_add_integer(ber, (u_int64_t)kif->if_obytes);
1279
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
1280
		break;
1281
	case 11:
1282
		ber = ber_add_integer(ber, (u_int64_t)kif->if_opackets);
1283
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
1284
		break;
1285
	case 12:
1286
		ber = ber_add_integer(ber, (u_int64_t)kif->if_omcasts);
1287
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
1288
		break;
1289
	case 13:
1290
		ber = ber_add_integer(ber, 0);
1291
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
1292
		break;
1293
	case 14:
1294
		ber = ber_add_integer(ber, 0);	/* enabled(1), disabled(2) */
1295
		break;
1296
	case 15:
1297
		i = kif->if_baudrate >= 1000000 ?
1298
		    kif->if_baudrate / 1000000 : 0;
1299
		ber = ber_add_integer(ber, i);
1300
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_GAUGE32);
1301
		break;
1302
	case 16:
1303
		/* ifPromiscuousMode: true(1), false(2) */
1304
		i = kif->if_flags & IFF_PROMISC ? 1 : 2;
1305
		ber = ber_add_integer(ber, i);
1306
		break;
1307
	case 17:
1308
		/* ifConnectorPresent: false(2), true(1) */
1309
		i = kif->if_type == IFT_ETHER ? 1 : 2;
1310
		ber = ber_add_integer(ber, i);
1311
		break;
1312
	case 18:
1313
		ber = ber_add_string(ber, kif->if_descr);
1314
		break;
1315
	case 19:
1316
		ber = ber_add_integer(ber, 0);
1317
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
1318
		break;
1319
	default:
1320
		return (-1);
1321
	}
1322
1323
	return (0);
1324
}
1325
1326
int
1327
mib_ifstacklast(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1328
{
1329
	struct ber_element	*ber = *elm;
1330
	ber = ber_add_integer(ber, kr_iflastchange());
1331
	ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
1332
	return (0);
1333
}
1334
1335
int
1336
mib_ifrcvtable(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1337
{
1338
	struct ber_element	*ber = *elm;
1339
	u_int32_t		 idx = 0;
1340
	struct kif		*kif;
1341
	u_int			 i = 0;
1342
1343
	/* Get and verify the current row index */
1344
	idx = o->bo_id[OIDIDX_ifRcvAddressEntry];
1345
	if ((kif = mib_ifget(idx)) == NULL)
1346
		return (1);
1347
1348
	/*
1349
	 * The lladdr of the interface will be encoded in the returned OID
1350
	 * ifRcvAddressX.ifindex.6.x.x.x.x.x.x = val
1351
	 * Thanks to the virtual cloner interfaces, it is an easy 1:1
1352
	 * mapping in OpenBSD; only one lladdr (MAC) address per interface.
1353
	 */
1354
1355
	/* first set the base OID and caluculate the length */
1356
	idx = 0;
1357
	o->bo_id[OIDIDX_ifRcvAddressEntry + idx++] = kif->if_index;
1358
	o->bo_id[OIDIDX_ifRcvAddressEntry + idx] = 0;
1359
	smi_oidlen(o);
1360
1361
	/* extend the OID with the lladdr length and octets */
1362
	o->bo_id[OIDIDX_ifRcvAddressEntry + idx++] = sizeof(kif->if_lladdr);
1363
	o->bo_n++;
1364
	for (i = 0; i < sizeof(kif->if_lladdr); i++, o->bo_n++)
1365
		o->bo_id[OIDIDX_ifRcvAddressEntry + idx++] = kif->if_lladdr[i];
1366
1367
	/* write OID */
1368
	ber = ber_add_oid(ber, o);
1369
1370
	switch (o->bo_id[OIDIDX_ifRcvAddress]) {
1371
	case 2:
1372
		/* ifRcvAddressStatus: RowStatus active(1), notInService(2) */
1373
		i = kif->if_flags & IFF_UP ? 1 : 2;
1374
		ber = ber_add_integer(ber, i);
1375
		break;
1376
	case 3:
1377
		/* ifRcvAddressType: other(1), volatile(2), nonVolatile(3) */
1378
		ber = ber_add_integer(ber, 1);
1379
		break;
1380
	default:
1381
		return (-1);
1382
	}
1383
1384
	return (0);
1385
}
1386
1387
/*
1388
 * Defined in
1389
 * - OPENBSD-PF-MIB.txt
1390
 * - OPENBSD-SENSORS-MIB.txt
1391
 * - OPENBSD-CARP-MIB.txt
1392
 * (http://www.packetmischief.ca/openbsd-snmp-mibs/)
1393
 */
1394
1395
struct carpif {
1396
	struct carpreq	 carpr;
1397
	struct kif	 kif;
1398
};
1399
1400
int	 mib_pfinfo(struct oid *, struct ber_oid *, struct ber_element **);
1401
int	 mib_pfcounters(struct oid *, struct ber_oid *, struct ber_element **);
1402
int	 mib_pfscounters(struct oid *, struct ber_oid *, struct ber_element **);
1403
int	 mib_pflogif(struct oid *, struct ber_oid *, struct ber_element **);
1404
int	 mib_pfsrctrack(struct oid *, struct ber_oid *, struct ber_element **);
1405
int	 mib_pflimits(struct oid *, struct ber_oid *, struct ber_element **);
1406
int	 mib_pftimeouts(struct oid *, struct ber_oid *, struct ber_element **);
1407
int	 mib_pfifnum(struct oid *, struct ber_oid *, struct ber_element **);
1408
int	 mib_pfiftable(struct oid *, struct ber_oid *, struct ber_element **);
1409
int	 mib_pftablenum(struct oid *, struct ber_oid *, struct ber_element **);
1410
int	 mib_pftables(struct oid *, struct ber_oid *, struct ber_element **);
1411
int	 mib_pftableaddrs(struct oid *, struct ber_oid *, struct ber_element **);
1412
struct ber_oid *
1413
	 mib_pftableaddrstable(struct oid *, struct ber_oid *, struct ber_oid *);
1414
int	 mib_pflabelnum(struct oid *, struct ber_oid *, struct ber_element **);
1415
int	 mib_pflabels(struct oid *, struct ber_oid *, struct ber_element **);
1416
int	 mib_pfsyncstats(struct oid *, struct ber_oid *, struct ber_element **);
1417
1418
int	 mib_sensornum(struct oid *, struct ber_oid *, struct ber_element **);
1419
int	 mib_sensors(struct oid *, struct ber_oid *, struct ber_element **);
1420
const char *mib_sensorunit(struct sensor *);
1421
char	*mib_sensorvalue(struct sensor *);
1422
1423
int	 mib_carpsysctl(struct oid *, struct ber_oid *, struct ber_element **);
1424
int	 mib_carpstats(struct oid *, struct ber_oid *, struct ber_element **);
1425
int	 mib_carpiftable(struct oid *, struct ber_oid *, struct ber_element **);
1426
int	 mib_carpifnum(struct oid *, struct ber_oid *, struct ber_element **);
1427
struct carpif
1428
	*mib_carpifget(u_int);
1429
int	 mib_memiftable(struct oid *, struct ber_oid *, struct ber_element **);
1430
1431
static struct oid openbsd_mib[] = {
1432
	{ MIB(pfMIBObjects),		OID_MIB },
1433
	{ MIB(pfRunning),		OID_RD, mib_pfinfo },
1434
	{ MIB(pfRuntime),		OID_RD, mib_pfinfo },
1435
	{ MIB(pfDebug),			OID_RD, mib_pfinfo },
1436
	{ MIB(pfHostid),		OID_RD, mib_pfinfo },
1437
	{ MIB(pfCntMatch),		OID_RD, mib_pfcounters },
1438
	{ MIB(pfCntBadOffset),		OID_RD, mib_pfcounters },
1439
	{ MIB(pfCntFragment),		OID_RD, mib_pfcounters },
1440
	{ MIB(pfCntShort),		OID_RD, mib_pfcounters },
1441
	{ MIB(pfCntNormalize),		OID_RD, mib_pfcounters },
1442
	{ MIB(pfCntMemory),		OID_RD, mib_pfcounters },
1443
	{ MIB(pfCntTimestamp),		OID_RD, mib_pfcounters },
1444
	{ MIB(pfCntCongestion),		OID_RD, mib_pfcounters },
1445
	{ MIB(pfCntIpOptions),		OID_RD, mib_pfcounters },
1446
	{ MIB(pfCntProtoCksum),		OID_RD, mib_pfcounters },
1447
	{ MIB(pfCntStateMismatch),	OID_RD, mib_pfcounters },
1448
	{ MIB(pfCntStateInsert),	OID_RD, mib_pfcounters },
1449
	{ MIB(pfCntStateLimit),		OID_RD, mib_pfcounters },
1450
	{ MIB(pfCntSrcLimit),		OID_RD, mib_pfcounters },
1451
	{ MIB(pfCntSynproxy),		OID_RD, mib_pfcounters },
1452
	{ MIB(pfCntTranslate),		OID_RD, mib_pfcounters },
1453
	{ MIB(pfCntNoRoute),		OID_RD, mib_pfcounters },
1454
	{ MIB(pfStateCount),		OID_RD, mib_pfscounters },
1455
	{ MIB(pfStateSearches),		OID_RD, mib_pfscounters },
1456
	{ MIB(pfStateInserts),		OID_RD, mib_pfscounters },
1457
	{ MIB(pfStateRemovals),		OID_RD, mib_pfscounters },
1458
	{ MIB(pfLogIfName),		OID_RD, mib_pflogif },
1459
	{ MIB(pfLogIfIpBytesIn),	OID_RD, mib_pflogif },
1460
	{ MIB(pfLogIfIpBytesOut),	OID_RD, mib_pflogif },
1461
	{ MIB(pfLogIfIpPktsInPass),	OID_RD, mib_pflogif },
1462
	{ MIB(pfLogIfIpPktsInDrop),	OID_RD, mib_pflogif },
1463
	{ MIB(pfLogIfIpPktsOutPass),	OID_RD, mib_pflogif },
1464
	{ MIB(pfLogIfIpPktsOutDrop),	OID_RD, mib_pflogif },
1465
	{ MIB(pfLogIfIp6BytesIn),	OID_RD, mib_pflogif },
1466
	{ MIB(pfLogIfIp6BytesOut),	OID_RD, mib_pflogif },
1467
	{ MIB(pfLogIfIp6PktsInPass),	OID_RD, mib_pflogif },
1468
	{ MIB(pfLogIfIp6PktsInDrop),	OID_RD, mib_pflogif },
1469
	{ MIB(pfLogIfIp6PktsOutPass),	OID_RD, mib_pflogif },
1470
	{ MIB(pfLogIfIp6PktsOutDrop),	OID_RD, mib_pflogif },
1471
	{ MIB(pfSrcTrackCount),		OID_RD, mib_pfsrctrack },
1472
	{ MIB(pfSrcTrackSearches),	OID_RD, mib_pfsrctrack },
1473
	{ MIB(pfSrcTrackInserts),	OID_RD, mib_pfsrctrack },
1474
	{ MIB(pfSrcTrackRemovals),	OID_RD, mib_pfsrctrack },
1475
	{ MIB(pfLimitStates),		OID_RD, mib_pflimits },
1476
	{ MIB(pfLimitSourceNodes),	OID_RD, mib_pflimits },
1477
	{ MIB(pfLimitFragments),	OID_RD, mib_pflimits },
1478
	{ MIB(pfLimitMaxTables),	OID_RD, mib_pflimits },
1479
	{ MIB(pfLimitMaxTableEntries),	OID_RD, mib_pflimits },
1480
	{ MIB(pfTimeoutTcpFirst),	OID_RD, mib_pftimeouts },
1481
	{ MIB(pfTimeoutTcpOpening),	OID_RD, mib_pftimeouts },
1482
	{ MIB(pfTimeoutTcpEstablished),	OID_RD, mib_pftimeouts },
1483
	{ MIB(pfTimeoutTcpClosing),	OID_RD, mib_pftimeouts },
1484
	{ MIB(pfTimeoutTcpFinWait),	OID_RD, mib_pftimeouts },
1485
	{ MIB(pfTimeoutTcpClosed),	OID_RD, mib_pftimeouts },
1486
	{ MIB(pfTimeoutUdpFirst),	OID_RD, mib_pftimeouts },
1487
	{ MIB(pfTimeoutUdpSingle),	OID_RD, mib_pftimeouts },
1488
	{ MIB(pfTimeoutUdpMultiple),	OID_RD, mib_pftimeouts },
1489
	{ MIB(pfTimeoutIcmpFirst),	OID_RD, mib_pftimeouts },
1490
	{ MIB(pfTimeoutIcmpError),	OID_RD, mib_pftimeouts },
1491
	{ MIB(pfTimeoutOtherFirst),	OID_RD, mib_pftimeouts },
1492
	{ MIB(pfTimeoutOtherSingle),	OID_RD, mib_pftimeouts },
1493
	{ MIB(pfTimeoutOtherMultiple),	OID_RD, mib_pftimeouts },
1494
	{ MIB(pfTimeoutFragment),	OID_RD, mib_pftimeouts },
1495
	{ MIB(pfTimeoutInterval),	OID_RD, mib_pftimeouts },
1496
	{ MIB(pfTimeoutAdaptiveStart),	OID_RD, mib_pftimeouts },
1497
	{ MIB(pfTimeoutAdaptiveEnd),	OID_RD, mib_pftimeouts },
1498
	{ MIB(pfTimeoutSrcTrack),	OID_RD, mib_pftimeouts },
1499
	{ MIB(pfIfNumber),		OID_RD, mib_pfifnum },
1500
	{ MIB(pfIfIndex),		OID_TRD, mib_pfiftable },
1501
	{ MIB(pfIfDescr),		OID_TRD, mib_pfiftable },
1502
	{ MIB(pfIfType),		OID_TRD, mib_pfiftable },
1503
	{ MIB(pfIfRefs),		OID_TRD, mib_pfiftable },
1504
	{ MIB(pfIfRules),		OID_TRD, mib_pfiftable },
1505
	{ MIB(pfIfIn4PassPkts),		OID_TRD, mib_pfiftable },
1506
	{ MIB(pfIfIn4PassBytes),	OID_TRD, mib_pfiftable },
1507
	{ MIB(pfIfIn4BlockPkts),	OID_TRD, mib_pfiftable },
1508
	{ MIB(pfIfIn4BlockBytes),	OID_TRD, mib_pfiftable },
1509
	{ MIB(pfIfOut4PassPkts),	OID_TRD, mib_pfiftable },
1510
	{ MIB(pfIfOut4PassBytes),	OID_TRD, mib_pfiftable },
1511
	{ MIB(pfIfOut4BlockPkts),	OID_TRD, mib_pfiftable },
1512
	{ MIB(pfIfOut4BlockBytes),	OID_TRD, mib_pfiftable },
1513
	{ MIB(pfIfIn6PassPkts),		OID_TRD, mib_pfiftable },
1514
	{ MIB(pfIfIn6PassBytes),	OID_TRD, mib_pfiftable },
1515
	{ MIB(pfIfIn6BlockPkts),	OID_TRD, mib_pfiftable },
1516
	{ MIB(pfIfIn6BlockBytes),	OID_TRD, mib_pfiftable },
1517
	{ MIB(pfIfOut6PassPkts),	OID_TRD, mib_pfiftable },
1518
	{ MIB(pfIfOut6PassBytes),	OID_TRD, mib_pfiftable },
1519
	{ MIB(pfIfOut6BlockPkts),	OID_TRD, mib_pfiftable },
1520
	{ MIB(pfIfOut6BlockBytes),	OID_TRD, mib_pfiftable },
1521
	{ MIB(pfTblNumber),		OID_RD, mib_pftablenum },
1522
	{ MIB(pfTblIndex),		OID_TRD, mib_pftables },
1523
	{ MIB(pfTblName),		OID_TRD, mib_pftables },
1524
	{ MIB(pfTblAddresses),		OID_TRD, mib_pftables },
1525
	{ MIB(pfTblAnchorRefs),		OID_TRD, mib_pftables },
1526
	{ MIB(pfTblRuleRefs),		OID_TRD, mib_pftables },
1527
	{ MIB(pfTblEvalsMatch),		OID_TRD, mib_pftables },
1528
	{ MIB(pfTblEvalsNoMatch),	OID_TRD, mib_pftables },
1529
	{ MIB(pfTblInPassPkts),		OID_TRD, mib_pftables },
1530
	{ MIB(pfTblInPassBytes),	OID_TRD, mib_pftables },
1531
	{ MIB(pfTblInBlockPkts),	OID_TRD, mib_pftables },
1532
	{ MIB(pfTblInBlockBytes),	OID_TRD, mib_pftables },
1533
	{ MIB(pfTblInXPassPkts),	OID_TRD, mib_pftables },
1534
	{ MIB(pfTblInXPassBytes),	OID_TRD, mib_pftables },
1535
	{ MIB(pfTblOutPassPkts),	OID_TRD, mib_pftables },
1536
	{ MIB(pfTblOutPassBytes),	OID_TRD, mib_pftables },
1537
	{ MIB(pfTblOutBlockPkts),	OID_TRD, mib_pftables },
1538
	{ MIB(pfTblOutBlockBytes),	OID_TRD, mib_pftables },
1539
	{ MIB(pfTblOutXPassPkts),	OID_TRD, mib_pftables },
1540
	{ MIB(pfTblOutXPassBytes),	OID_TRD, mib_pftables },
1541
	{ MIB(pfTblStatsCleared),	OID_TRD, mib_pftables },
1542
	{ MIB(pfTblInMatchPkts),	OID_TRD, mib_pftables },
1543
	{ MIB(pfTblInMatchBytes),	OID_TRD, mib_pftables },
1544
	{ MIB(pfTblOutMatchPkts),	OID_TRD, mib_pftables },
1545
	{ MIB(pfTblOutMatchBytes),	OID_TRD, mib_pftables },
1546
	{ MIB(pfTblAddrTblIndex),	OID_TRD, mib_pftableaddrs,
1547
	    NULL, mib_pftableaddrstable },
1548
	{ MIB(pfTblAddrNet),		OID_TRD, mib_pftableaddrs,
1549
	    NULL, mib_pftableaddrstable },
1550
	{ MIB(pfTblAddrMask),		OID_TRD, mib_pftableaddrs,
1551
	    NULL, mib_pftableaddrstable },
1552
	{ MIB(pfTblAddrCleared),	OID_TRD, mib_pftableaddrs,
1553
	    NULL, mib_pftableaddrstable },
1554
	{ MIB(pfTblAddrInBlockPkts),	OID_TRD, mib_pftableaddrs,
1555
	    NULL, mib_pftableaddrstable },
1556
	{ MIB(pfTblAddrInBlockBytes),	OID_TRD, mib_pftableaddrs,
1557
	    NULL, mib_pftableaddrstable },
1558
	{ MIB(pfTblAddrInPassPkts),	OID_TRD, mib_pftableaddrs,
1559
	    NULL, mib_pftableaddrstable },
1560
	{ MIB(pfTblAddrInPassBytes),	OID_TRD, mib_pftableaddrs,
1561
	    NULL, mib_pftableaddrstable },
1562
	{ MIB(pfTblAddrOutBlockPkts),	OID_TRD, mib_pftableaddrs,
1563
	    NULL, mib_pftableaddrstable },
1564
	{ MIB(pfTblAddrOutBlockBytes),	OID_TRD, mib_pftableaddrs,
1565
	    NULL, mib_pftableaddrstable },
1566
	{ MIB(pfTblAddrOutPassPkts),	OID_TRD, mib_pftableaddrs,
1567
	    NULL, mib_pftableaddrstable },
1568
	{ MIB(pfTblAddrOutPassBytes),	OID_TRD, mib_pftableaddrs,
1569
	    NULL, mib_pftableaddrstable },
1570
	{ MIB(pfTblAddrInMatchPkts),	OID_TRD, mib_pftableaddrs,
1571
	    NULL, mib_pftableaddrstable },
1572
	{ MIB(pfTblAddrInMatchBytes),	OID_TRD, mib_pftableaddrs,
1573
	    NULL, mib_pftableaddrstable },
1574
	{ MIB(pfTblAddrOutMatchPkts),	OID_TRD, mib_pftableaddrs,
1575
	    NULL, mib_pftableaddrstable },
1576
	{ MIB(pfTblAddrOutMatchBytes),	OID_TRD, mib_pftableaddrs,
1577
	    NULL, mib_pftableaddrstable },
1578
	{ MIB(pfLabelNumber),		OID_RD, mib_pflabelnum },
1579
	{ MIB(pfLabelIndex),		OID_TRD, mib_pflabels },
1580
	{ MIB(pfLabelName),		OID_TRD, mib_pflabels },
1581
	{ MIB(pfLabelEvals),		OID_TRD, mib_pflabels },
1582
	{ MIB(pfLabelPkts),		OID_TRD, mib_pflabels },
1583
	{ MIB(pfLabelBytes),		OID_TRD, mib_pflabels },
1584
	{ MIB(pfLabelInPkts),		OID_TRD, mib_pflabels },
1585
	{ MIB(pfLabelInBytes),		OID_TRD, mib_pflabels },
1586
	{ MIB(pfLabelOutPkts),		OID_TRD, mib_pflabels },
1587
	{ MIB(pfLabelOutBytes),		OID_TRD, mib_pflabels },
1588
	{ MIB(pfLabelTotalStates),	OID_TRD, mib_pflabels },
1589
	{ MIB(pfsyncIpPktsRecv),	OID_RD, mib_pfsyncstats },
1590
	{ MIB(pfsyncIp6PktsRecv),	OID_RD, mib_pfsyncstats },
1591
	{ MIB(pfsyncPktDiscardsForBadInterface), OID_RD, mib_pfsyncstats },
1592
	{ MIB(pfsyncPktDiscardsForBadTtl), OID_RD, mib_pfsyncstats },
1593
	{ MIB(pfsyncPktShorterThanHeader), OID_RD, mib_pfsyncstats },
1594
	{ MIB(pfsyncPktDiscardsForBadVersion), OID_RD, mib_pfsyncstats },
1595
	{ MIB(pfsyncPktDiscardsForBadAction), OID_RD, mib_pfsyncstats },
1596
	{ MIB(pfsyncPktDiscardsForBadLength), OID_RD, mib_pfsyncstats },
1597
	{ MIB(pfsyncPktDiscardsForBadAuth), OID_RD, mib_pfsyncstats },
1598
	{ MIB(pfsyncPktDiscardsForStaleState), OID_RD, mib_pfsyncstats },
1599
	{ MIB(pfsyncPktDiscardsForBadValues), OID_RD, mib_pfsyncstats },
1600
	{ MIB(pfsyncPktDiscardsForBadState), OID_RD, mib_pfsyncstats },
1601
	{ MIB(pfsyncIpPktsSent),	OID_RD, mib_pfsyncstats },
1602
	{ MIB(pfsyncIp6PktsSent),	OID_RD, mib_pfsyncstats },
1603
	{ MIB(pfsyncNoMemory),		OID_RD, mib_pfsyncstats },
1604
	{ MIB(pfsyncOutputErrors),	OID_RD, mib_pfsyncstats },
1605
	{ MIB(sensorsMIBObjects),	OID_MIB },
1606
	{ MIB(sensorNumber),		OID_RD,	mib_sensornum },
1607
	{ MIB(sensorIndex),		OID_TRD, mib_sensors },
1608
	{ MIB(sensorDescr),		OID_TRD, mib_sensors },
1609
	{ MIB(sensorType),		OID_TRD, mib_sensors },
1610
	{ MIB(sensorDevice),		OID_TRD, mib_sensors },
1611
	{ MIB(sensorValue),		OID_TRD, mib_sensors },
1612
	{ MIB(sensorUnits),		OID_TRD, mib_sensors },
1613
	{ MIB(sensorStatus),		OID_TRD, mib_sensors },
1614
	{ MIB(carpMIBObjects),		OID_MIB },
1615
	{ MIB(carpAllow),		OID_RD, mib_carpsysctl },
1616
	{ MIB(carpPreempt),		OID_RD, mib_carpsysctl },
1617
	{ MIB(carpLog),			OID_RD, mib_carpsysctl },
1618
	{ MIB(carpIpPktsRecv),		OID_RD, mib_carpstats },
1619
	{ MIB(carpIp6PktsRecv),		OID_RD, mib_carpstats },
1620
	{ MIB(carpPktDiscardsBadIface),	OID_RD, mib_carpstats },
1621
	{ MIB(carpPktDiscardsBadTtl),	OID_RD, mib_carpstats },
1622
	{ MIB(carpPktShorterThanHdr),	OID_RD, mib_carpstats },
1623
	{ MIB(carpDiscardsBadCksum),	OID_RD, mib_carpstats },
1624
	{ MIB(carpDiscardsBadVersion),	OID_RD, mib_carpstats },
1625
	{ MIB(carpDiscardsTooShort),	OID_RD, mib_carpstats },
1626
	{ MIB(carpDiscardsBadAuth),	OID_RD, mib_carpstats },
1627
	{ MIB(carpDiscardsBadVhid),	OID_RD, mib_carpstats },
1628
	{ MIB(carpDiscardsBadAddrList),	OID_RD, mib_carpstats },
1629
	{ MIB(carpIpPktsSent),		OID_RD, mib_carpstats },
1630
	{ MIB(carpIp6PktsSent),		OID_RD, mib_carpstats },
1631
	{ MIB(carpNoMemory),		OID_RD, mib_carpstats },
1632
	{ MIB(carpTransitionsToMaster),	OID_RD, mib_carpstats },
1633
	{ MIB(carpIfNumber),		OID_RD, mib_carpifnum },
1634
	{ MIB(carpIfIndex),		OID_TRD, mib_carpiftable },
1635
	{ MIB(carpIfDescr),		OID_TRD, mib_carpiftable },
1636
	{ MIB(carpIfVhid),		OID_TRD, mib_carpiftable },
1637
	{ MIB(carpIfDev	),		OID_TRD, mib_carpiftable },
1638
	{ MIB(carpIfAdvbase),		OID_TRD, mib_carpiftable },
1639
	{ MIB(carpIfAdvskew),		OID_TRD, mib_carpiftable },
1640
	{ MIB(carpIfState),		OID_TRD, mib_carpiftable },
1641
	{ MIB(memMIBObjects),		OID_MIB },
1642
	{ MIB(memMIBVersion),		OID_RD, mps_getint, NULL, NULL,
1643
	    OIDVER_OPENBSD_MEM },
1644
	{ MIB(memIfName),		OID_TRD, mib_memiftable },
1645
	{ MIB(memIfLiveLocks),		OID_TRD, mib_memiftable },
1646
	{ MIBEND }
1647
};
1648
1649
int
1650
mib_pfinfo(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1651
{
1652
	struct pf_status	 s;
1653
	time_t			 runtime = 0;
1654
	struct timespec		 uptime;
1655
	char			 str[11];
1656
1657
	if (pf_get_stats(&s))
1658
		return (-1);
1659
1660
	switch (oid->o_oid[OIDIDX_pfstatus]) {
1661
	case 1:
1662
		*elm = ber_add_integer(*elm, s.running);
1663
		break;
1664
	case 2:
1665
		if (!clock_gettime(CLOCK_UPTIME, &uptime))
1666
			runtime = uptime.tv_sec - s.since;
1667
		runtime *= 100;
1668
		*elm = ber_add_integer(*elm, runtime);
1669
		ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
1670
		break;
1671
	case 3:
1672
		*elm = ber_add_integer(*elm, s.debug);
1673
		break;
1674
	case 4:
1675
		snprintf(str, sizeof(str), "0x%08x", ntohl(s.hostid));
1676
		*elm = ber_add_string(*elm, str);
1677
		break;
1678
	default:
1679
		return (-1);
1680
	}
1681
1682
	return (0);
1683
}
1684
1685
int
1686
mib_pfcounters(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1687
{
1688
	struct pf_status	 s;
1689
	int			 i;
1690
	struct statsmap {
1691
		u_int8_t	 m_id;
1692
		u_int64_t	*m_ptr;
1693
	}			 mapping[] = {
1694
		{ 1, &s.counters[PFRES_MATCH] },
1695
		{ 2, &s.counters[PFRES_BADOFF] },
1696
		{ 3, &s.counters[PFRES_FRAG] },
1697
		{ 4, &s.counters[PFRES_SHORT] },
1698
		{ 5, &s.counters[PFRES_NORM] },
1699
		{ 6, &s.counters[PFRES_MEMORY] },
1700
		{ 7, &s.counters[PFRES_TS] },
1701
		{ 8, &s.counters[PFRES_CONGEST] },
1702
		{ 9, &s.counters[PFRES_IPOPTIONS] },
1703
		{ 10, &s.counters[PFRES_PROTCKSUM] },
1704
		{ 11, &s.counters[PFRES_BADSTATE] },
1705
		{ 12, &s.counters[PFRES_STATEINS] },
1706
		{ 13, &s.counters[PFRES_MAXSTATES] },
1707
		{ 14, &s.counters[PFRES_SRCLIMIT] },
1708
		{ 15, &s.counters[PFRES_SYNPROXY] },
1709
		{ 16, &s.counters[PFRES_TRANSLATE] },
1710
		{ 17, &s.counters[PFRES_NOROUTE] }
1711
	};
1712
1713
	if (pf_get_stats(&s))
1714
		return (-1);
1715
1716
	for (i = 0;
1717
	    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
1718
		if (oid->o_oid[OIDIDX_pfstatus] == mapping[i].m_id) {
1719
			*elm = ber_add_integer(*elm, *mapping[i].m_ptr);
1720
			ber_set_header(*elm, BER_CLASS_APPLICATION,
1721
			    SNMP_T_COUNTER64);
1722
			return (0);
1723
		}
1724
	}
1725
	return (-1);
1726
}
1727
1728
int
1729
mib_pfscounters(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1730
{
1731
	struct pf_status	 s;
1732
	int			 i;
1733
	struct statsmap {
1734
		u_int8_t	 m_id;
1735
		u_int64_t	*m_ptr;
1736
	}			 mapping[] = {
1737
		{ 2, &s.fcounters[FCNT_STATE_SEARCH] },
1738
		{ 3, &s.fcounters[FCNT_STATE_INSERT] },
1739
		{ 4, &s.fcounters[FCNT_STATE_REMOVALS] },
1740
	};
1741
1742
	if (pf_get_stats(&s))
1743
		return (-1);
1744
1745
	switch (oid->o_oid[OIDIDX_pfstatus]) {
1746
	case 1:
1747
		*elm = ber_add_integer(*elm, s.states);
1748
		ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_UNSIGNED32);
1749
		break;
1750
	default:
1751
		for (i = 0;
1752
		    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
1753
			if (oid->o_oid[OIDIDX_pfstatus] == mapping[i].m_id) {
1754
				*elm = ber_add_integer(*elm, *mapping[i].m_ptr);
1755
				ber_set_header(*elm, BER_CLASS_APPLICATION,
1756
				    SNMP_T_COUNTER64);
1757
				return (0);
1758
			}
1759
		}
1760
		return (-1);
1761
	}
1762
1763
	return (0);
1764
}
1765
1766
int
1767
mib_pflogif(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1768
{
1769
	struct pf_status	 s;
1770
	int			 i;
1771
	struct statsmap {
1772
		u_int8_t	 m_id;
1773
		u_int64_t	*m_ptr;
1774
	}			 mapping[] = {
1775
		{ 2, &s.bcounters[IPV4][IN] },
1776
		{ 3, &s.bcounters[IPV4][OUT] },
1777
		{ 4, &s.pcounters[IPV4][IN][PF_PASS] },
1778
		{ 5, &s.pcounters[IPV4][IN][PF_DROP] },
1779
		{ 6, &s.pcounters[IPV4][OUT][PF_PASS] },
1780
		{ 7, &s.pcounters[IPV4][OUT][PF_DROP] },
1781
		{ 8, &s.bcounters[IPV6][IN] },
1782
		{ 9, &s.bcounters[IPV6][OUT] },
1783
		{ 10, &s.pcounters[IPV6][IN][PF_PASS] },
1784
		{ 11, &s.pcounters[IPV6][IN][PF_DROP] },
1785
		{ 12, &s.pcounters[IPV6][OUT][PF_PASS] },
1786
		{ 13, &s.pcounters[IPV6][OUT][PF_DROP] }
1787
	};
1788
1789
	if (pf_get_stats(&s))
1790
		return (-1);
1791
1792
	switch (oid->o_oid[OIDIDX_pfstatus]) {
1793
	case 1:
1794
		*elm = ber_add_string(*elm, s.ifname);
1795
		break;
1796
	default:
1797
		for (i = 0;
1798
		    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
1799
			if (oid->o_oid[OIDIDX_pfstatus] == mapping[i].m_id) {
1800
				*elm = ber_add_integer(*elm, *mapping[i].m_ptr);
1801
				ber_set_header(*elm, BER_CLASS_APPLICATION,
1802
				    SNMP_T_COUNTER64);
1803
				return (0);
1804
			}
1805
		}
1806
		return (-1);
1807
	}
1808
1809
	return (0);
1810
}
1811
1812
int
1813
mib_pfsrctrack(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1814
{
1815
	struct pf_status	 s;
1816
	int			 i;
1817
	struct statsmap {
1818
		u_int8_t	 m_id;
1819
		u_int64_t	*m_ptr;
1820
	}			 mapping[] = {
1821
		{ 2, &s.scounters[SCNT_SRC_NODE_SEARCH] },
1822
		{ 3, &s.scounters[SCNT_SRC_NODE_INSERT] },
1823
		{ 4, &s.scounters[SCNT_SRC_NODE_REMOVALS] }
1824
	};
1825
1826
	if (pf_get_stats(&s))
1827
		return (-1);
1828
1829
	switch (oid->o_oid[OIDIDX_pfstatus]) {
1830
	case 1:
1831
		*elm = ber_add_integer(*elm, s.src_nodes);
1832
		ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_UNSIGNED32);
1833
		break;
1834
	default:
1835
		for (i = 0;
1836
		    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
1837
			if (oid->o_oid[OIDIDX_pfstatus] == mapping[i].m_id) {
1838
				*elm = ber_add_integer(*elm, *mapping[i].m_ptr);
1839
				ber_set_header(*elm, BER_CLASS_APPLICATION,
1840
				    SNMP_T_COUNTER64);
1841
				return (0);
1842
			}
1843
		}
1844
		return (-1);
1845
	}
1846
1847
	return (0);
1848
}
1849
1850
int
1851
mib_pflimits(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1852
{
1853
	struct pfioc_limit	 pl;
1854
	int			 i;
1855
	extern int		 devpf;
1856
	struct statsmap {
1857
		u_int8_t	 m_id;
1858
		u_int8_t	 m_limit;
1859
	}			 mapping[] = {
1860
		{ 1, PF_LIMIT_STATES },
1861
		{ 2, PF_LIMIT_SRC_NODES },
1862
		{ 3, PF_LIMIT_FRAGS },
1863
		{ 4, PF_LIMIT_TABLES },
1864
		{ 5, PF_LIMIT_TABLE_ENTRIES }
1865
	};
1866
1867
	memset(&pl, 0, sizeof(pl));
1868
	pl.index = PF_LIMIT_MAX;
1869
1870
	for (i = 0;
1871
	    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
1872
		if (oid->o_oid[OIDIDX_pfstatus] == mapping[i].m_id) {
1873
			pl.index = mapping[i].m_limit;
1874
			break;
1875
		}
1876
	}
1877
1878
	if (pl.index == PF_LIMIT_MAX)
1879
		return (-1);
1880
1881
	if (ioctl(devpf, DIOCGETLIMIT, &pl)) {
1882
		log_warn("DIOCGETLIMIT");
1883
		return (-1);
1884
	}
1885
1886
	*elm = ber_add_integer(*elm, pl.limit);
1887
	ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_UNSIGNED32);
1888
1889
	return (0);
1890
}
1891
1892
int
1893
mib_pftimeouts(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1894
{
1895
	struct pfioc_tm		 pt;
1896
	int			 i;
1897
	extern int		 devpf;
1898
	struct statsmap {
1899
		u_int8_t	 m_id;
1900
		u_int8_t	 m_tm;
1901
	}			 mapping[] = {
1902
		{ 1, PFTM_TCP_FIRST_PACKET },
1903
		{ 2, PFTM_TCP_OPENING },
1904
		{ 3, PFTM_TCP_ESTABLISHED },
1905
		{ 4, PFTM_TCP_CLOSING },
1906
		{ 5, PFTM_TCP_FIN_WAIT },
1907
		{ 6, PFTM_TCP_CLOSED },
1908
		{ 7, PFTM_UDP_FIRST_PACKET },
1909
		{ 8, PFTM_UDP_SINGLE },
1910
		{ 9, PFTM_UDP_MULTIPLE },
1911
		{ 10, PFTM_ICMP_FIRST_PACKET },
1912
		{ 11, PFTM_ICMP_ERROR_REPLY },
1913
		{ 12, PFTM_OTHER_FIRST_PACKET },
1914
		{ 13, PFTM_OTHER_SINGLE },
1915
		{ 14, PFTM_OTHER_MULTIPLE },
1916
		{ 15, PFTM_FRAG },
1917
		{ 16, PFTM_INTERVAL },
1918
		{ 17, PFTM_ADAPTIVE_START },
1919
		{ 18, PFTM_ADAPTIVE_END },
1920
		{ 19, PFTM_SRC_NODE }
1921
	};
1922
1923
	memset(&pt, 0, sizeof(pt));
1924
	pt.timeout = PFTM_MAX;
1925
1926
	for (i = 0;
1927
	    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
1928
		if (oid->o_oid[OIDIDX_pfstatus] == mapping[i].m_id) {
1929
			pt.timeout = mapping[i].m_tm;
1930
			break;
1931
		}
1932
	}
1933
1934
	if (pt.timeout == PFTM_MAX)
1935
		return (-1);
1936
1937
	if (ioctl(devpf, DIOCGETTIMEOUT, &pt)) {
1938
		log_warn("DIOCGETTIMEOUT");
1939
		return (-1);
1940
	}
1941
1942
	*elm = ber_add_integer(*elm, pt.seconds);
1943
1944
	return (0);
1945
}
1946
1947
int
1948
mib_pfifnum(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1949
{
1950
	int	 c;
1951
1952
	if ((c = pfi_count()) == -1)
1953
		return (-1);
1954
1955
	*elm = ber_add_integer(*elm, c);
1956
1957
	return (0);
1958
}
1959
1960
int
1961
mib_pfiftable(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
1962
{
1963
	struct ber_element	*ber = *elm;
1964
	struct pfi_kif		 pif;
1965
	int			 idx, iftype;
1966
1967
	/* Get and verify the current row index */
1968
	idx = o->bo_id[OIDIDX_pfIfEntry];
1969
1970
	if (pfi_get_if(&pif, idx))
1971
		return (1);
1972
1973
	ber = ber_add_oid(ber, o);
1974
1975
	switch (o->bo_id[OIDIDX_pfInterface]) {
1976
	case 1:
1977
		ber = ber_add_integer(ber, idx);
1978
		break;
1979
	case 2:
1980
		ber = ber_add_string(ber, pif.pfik_name);
1981
		break;
1982
	case 3:
1983
		iftype = (pif.pfik_ifp == NULL ? PFI_IFTYPE_GROUP
1984
		    : PFI_IFTYPE_INSTANCE);
1985
		ber = ber_add_integer(ber, iftype);
1986
		break;
1987
	case 4:
1988
		ber = ber_add_integer(ber, pif.pfik_states);
1989
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_UNSIGNED32);
1990
		break;
1991
	case 5:
1992
		ber = ber_add_integer(ber, pif.pfik_rules);
1993
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_UNSIGNED32);
1994
		break;
1995
	case 6:
1996
		ber = ber_add_integer(ber, pif.pfik_packets[IPV4][IN][PASS]);
1997
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
1998
		break;
1999
	case 7:
2000
		ber = ber_add_integer(ber, pif.pfik_bytes[IPV4][IN][PASS]);
2001
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2002
		break;
2003
	case 8:
2004
		ber = ber_add_integer(ber, pif.pfik_packets[IPV4][IN][BLOCK]);
2005
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2006
		break;
2007
	case 9:
2008
		ber = ber_add_integer(ber, pif.pfik_bytes[IPV4][IN][BLOCK]);
2009
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2010
		break;
2011
	case 10:
2012
		ber = ber_add_integer(ber, pif.pfik_packets[IPV4][OUT][PASS]);
2013
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2014
		break;
2015
	case 11:
2016
		ber = ber_add_integer(ber, pif.pfik_bytes[IPV4][OUT][PASS]);
2017
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2018
		break;
2019
	case 12:
2020
		ber = ber_add_integer(ber, pif.pfik_packets[IPV4][OUT][BLOCK]);
2021
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2022
		break;
2023
	case 13:
2024
		ber = ber_add_integer(ber, pif.pfik_bytes[IPV4][OUT][BLOCK]);
2025
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2026
		break;
2027
	case 14:
2028
		ber = ber_add_integer(ber, pif.pfik_packets[IPV6][IN][PASS]);
2029
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2030
		break;
2031
	case 15:
2032
		ber = ber_add_integer(ber, pif.pfik_bytes[IPV6][IN][PASS]);
2033
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2034
		break;
2035
	case 16:
2036
		ber = ber_add_integer(ber, pif.pfik_packets[IPV6][IN][BLOCK]);
2037
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2038
		break;
2039
	case 17:
2040
		ber = ber_add_integer(ber, pif.pfik_bytes[IPV6][IN][BLOCK]);
2041
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2042
		break;
2043
	case 18:
2044
		ber = ber_add_integer(ber, pif.pfik_packets[IPV6][OUT][PASS]);
2045
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2046
		break;
2047
	case 19:
2048
		ber = ber_add_integer(ber, pif.pfik_bytes[IPV6][OUT][PASS]);
2049
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2050
		break;
2051
	case 20:
2052
		ber = ber_add_integer(ber, pif.pfik_packets[IPV6][OUT][BLOCK]);
2053
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2054
		break;
2055
	case 21:
2056
		ber = ber_add_integer(ber, pif.pfik_bytes[IPV6][OUT][BLOCK]);
2057
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2058
		break;
2059
	default:
2060
		return (1);
2061
	}
2062
2063
	return (0);
2064
}
2065
2066
int
2067
mib_pftablenum(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2068
{
2069
	int	 c;
2070
2071
	if ((c = pft_count()) == -1)
2072
		return (-1);
2073
2074
	*elm = ber_add_integer(*elm, c);
2075
2076
	return (0);
2077
}
2078
2079
int
2080
mib_pftables(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2081
{
2082
	struct ber_element	*ber = *elm;
2083
	struct pfr_tstats	 ts;
2084
	time_t			 tzero;
2085
	int			 idx;
2086
2087
	/* Get and verify the current row index */
2088
	idx = o->bo_id[OIDIDX_pfTableEntry];
2089
2090
	if (pft_get_table(&ts, idx))
2091
		return (1);
2092
2093
	ber = ber_add_oid(ber, o);
2094
2095
	switch (o->bo_id[OIDIDX_pfTable]) {
2096
	case 1:
2097
		ber = ber_add_integer(ber, idx);
2098
		break;
2099
	case 2:
2100
		ber = ber_add_string(ber, ts.pfrts_name);
2101
		break;
2102
	case 3:
2103
		ber = ber_add_integer(ber, ts.pfrts_cnt);
2104
		break;
2105
	case 4:
2106
		ber = ber_add_integer(ber, ts.pfrts_refcnt[PFR_REFCNT_ANCHOR]);
2107
		break;
2108
	case 5:
2109
		ber = ber_add_integer(ber, ts.pfrts_refcnt[PFR_REFCNT_RULE]);
2110
		break;
2111
	case 6:
2112
		ber = ber_add_integer(ber, ts.pfrts_match);
2113
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2114
		break;
2115
	case 7:
2116
		ber = ber_add_integer(ber, ts.pfrts_nomatch);
2117
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2118
		break;
2119
	case 8:
2120
		ber = ber_add_integer(ber, ts.pfrts_packets[IN][PFR_OP_PASS]);
2121
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2122
		break;
2123
	case 9:
2124
		ber = ber_add_integer(ber, ts.pfrts_bytes[IN][PFR_OP_PASS]);
2125
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2126
		break;
2127
	case 10:
2128
		ber = ber_add_integer(ber, ts.pfrts_packets[IN][PFR_OP_BLOCK]);
2129
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2130
		break;
2131
	case 11:
2132
		ber = ber_add_integer(ber, ts.pfrts_bytes[IN][PFR_OP_BLOCK]);
2133
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2134
		break;
2135
	case 12:
2136
		ber = ber_add_integer(ber, ts.pfrts_packets[IN][PFR_OP_XPASS]);
2137
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2138
		break;
2139
	case 13:
2140
		ber = ber_add_integer(ber, ts.pfrts_bytes[IN][PFR_OP_XPASS]);
2141
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2142
		break;
2143
	case 14:
2144
		ber = ber_add_integer(ber, ts.pfrts_packets[OUT][PFR_OP_PASS]);
2145
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2146
		break;
2147
	case 15:
2148
		ber = ber_add_integer(ber, ts.pfrts_bytes[OUT][PFR_OP_PASS]);
2149
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2150
		break;
2151
	case 16:
2152
		ber = ber_add_integer(ber, ts.pfrts_packets[OUT][PFR_OP_BLOCK]);
2153
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2154
		break;
2155
	case 17:
2156
		ber = ber_add_integer(ber, ts.pfrts_bytes[OUT][PFR_OP_BLOCK]);
2157
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2158
		break;
2159
	case 18:
2160
		ber = ber_add_integer(ber, ts.pfrts_packets[OUT][PFR_OP_XPASS]);
2161
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2162
		break;
2163
	case 19:
2164
		ber = ber_add_integer(ber, ts.pfrts_bytes[OUT][PFR_OP_XPASS]);
2165
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2166
		break;
2167
	case 20:
2168
		tzero = (time(NULL) - ts.pfrts_tzero) * 100;
2169
		ber = ber_add_integer(ber, tzero);
2170
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
2171
		break;
2172
	case 21:
2173
		ber = ber_add_integer(ber, ts.pfrts_packets[IN][PFR_OP_MATCH]);
2174
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2175
		break;
2176
	case 22:
2177
		ber = ber_add_integer(ber, ts.pfrts_bytes[IN][PFR_OP_MATCH]);
2178
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2179
		break;
2180
	case 23:
2181
		ber = ber_add_integer(ber, ts.pfrts_packets[OUT][PFR_OP_MATCH]);
2182
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2183
		break;
2184
	case 24:
2185
		ber = ber_add_integer(ber, ts.pfrts_bytes[OUT][PFR_OP_MATCH]);
2186
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2187
		break;
2188
	default:
2189
		return (1);
2190
	}
2191
2192
	return (0);
2193
}
2194
2195
int
2196
mib_pftableaddrs(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2197
{
2198
	struct ber_element	*ber = *elm;
2199
	struct pfr_astats	 as;
2200
	int			 tblidx;
2201
2202
	tblidx = o->bo_id[OIDIDX_pfTblAddr + 1];
2203
	mps_decodeinaddr(o, &as.pfras_a.pfra_ip4addr, OIDIDX_pfTblAddr + 2);
2204
	as.pfras_a.pfra_net = o->bo_id[OIDIDX_pfTblAddr + 6];
2205
2206
	if (pfta_get_addr(&as, tblidx))
2207
		return (-1);
2208
2209
	/* write OID */
2210
	ber = ber_add_oid(ber, o);
2211
2212
	switch (o->bo_id[OIDIDX_pfTblAddr]) {
2213
	case 1:
2214
		ber = ber_add_integer(ber, tblidx);
2215
		break;
2216
	case 2:
2217
		ber = ber_add_nstring(ber, (char *)&as.pfras_a.pfra_ip4addr,
2218
		    sizeof(u_int32_t));
2219
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_IPADDR);
2220
		break;
2221
	case 3:
2222
		ber = ber_add_integer(ber, as.pfras_a.pfra_net);
2223
		break;
2224
	case 4:
2225
		ber = ber_add_integer(ber, (time(NULL) - as.pfras_tzero) * 100);
2226
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
2227
		break;
2228
	case 5:
2229
		ber = ber_add_integer(ber, as.pfras_packets[IN][PFR_OP_BLOCK]);
2230
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2231
		break;
2232
	case 6:
2233
		ber = ber_add_integer(ber, as.pfras_bytes[IN][PFR_OP_BLOCK]);
2234
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2235
		break;
2236
	case 7:
2237
		ber = ber_add_integer(ber, as.pfras_packets[IN][PFR_OP_PASS]);
2238
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2239
		break;
2240
	case 8:
2241
		ber = ber_add_integer(ber, as.pfras_bytes[IN][PFR_OP_PASS]);
2242
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2243
		break;
2244
	case 9:
2245
		ber = ber_add_integer(ber, as.pfras_packets[OUT][PFR_OP_BLOCK]);
2246
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2247
		break;
2248
	case 10:
2249
		ber = ber_add_integer(ber, as.pfras_bytes[OUT][PFR_OP_BLOCK]);
2250
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2251
		break;
2252
	case 11:
2253
		ber = ber_add_integer(ber, as.pfras_packets[OUT][PFR_OP_PASS]);
2254
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2255
		break;
2256
	case 12:
2257
		ber = ber_add_integer(ber, as.pfras_bytes[OUT][PFR_OP_PASS]);
2258
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2259
		break;
2260
	case 13:
2261
		ber = ber_add_integer(ber, as.pfras_packets[IN][PFR_OP_MATCH]);
2262
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2263
		break;
2264
	case 14:
2265
		ber = ber_add_integer(ber, as.pfras_bytes[IN][PFR_OP_MATCH]);
2266
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2267
		break;
2268
	case 15:
2269
		ber = ber_add_integer(ber, as.pfras_packets[OUT][PFR_OP_MATCH]);
2270
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2271
		break;
2272
	case 16:
2273
		ber = ber_add_integer(ber, as.pfras_bytes[OUT][PFR_OP_MATCH]);
2274
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2275
		break;
2276
	default:
2277
		return (-1);
2278
	}
2279
2280
	return (0);
2281
}
2282
2283
struct ber_oid *
2284
mib_pftableaddrstable(struct oid *oid, struct ber_oid *o, struct ber_oid *no)
2285
{
2286
	struct pfr_astats	 as;
2287
	struct oid		 a, b;
2288
	u_int32_t		 id, tblidx;
2289
2290
	bcopy(&oid->o_id, no, sizeof(*no));
2291
	id = oid->o_oidlen - 1;
2292
2293
	if (o->bo_n >= oid->o_oidlen) {
2294
		/*
2295
		 * Compare the requested and the matched OID to see
2296
		 * if we have to iterate to the next element.
2297
		 */
2298
		bzero(&a, sizeof(a));
2299
		bcopy(o, &a.o_id, sizeof(struct ber_oid));
2300
		bzero(&b, sizeof(b));
2301
		bcopy(&oid->o_id, &b.o_id, sizeof(struct ber_oid));
2302
		b.o_oidlen--;
2303
		b.o_flags |= OID_TABLE;
2304
		if (smi_oid_cmp(&a, &b) == 0) {
2305
			o->bo_id[id] = oid->o_oid[id];
2306
			bcopy(o, no, sizeof(*no));
2307
		}
2308
	}
2309
2310
	tblidx = no->bo_id[OIDIDX_pfTblAddr + 1];
2311
	mps_decodeinaddr(no, &as.pfras_a.pfra_ip4addr, OIDIDX_pfTblAddr + 2);
2312
	as.pfras_a.pfra_net = no->bo_id[OIDIDX_pfTblAddr + 6];
2313
2314
	if (tblidx == 0) {
2315
		if (pfta_get_first(&as))
2316
			return (NULL);
2317
		tblidx = 1;
2318
	} else {
2319
		if (pfta_get_nextaddr(&as, &tblidx)) {
2320
			/* We reached the last addr in the last table.
2321
			 * When the next OIDIDX_pfTblAddr'th OID is requested,
2322
			 * get the first table address again.
2323
			 */
2324
			o->bo_id[OIDIDX_pfTblAddr + 1] = 0;
2325
			smi_oidlen(o);
2326
			return (NULL);
2327
		}
2328
	}
2329
2330
	no->bo_id[OIDIDX_pfTblAddr + 1] = tblidx;
2331
	mps_encodeinaddr(no, &as.pfras_a.pfra_ip4addr, OIDIDX_pfTblAddr + 2);
2332
	no->bo_id[OIDIDX_pfTblAddr + 6] = as.pfras_a.pfra_net;
2333
	no->bo_n += 1;
2334
2335
	smi_oidlen(o);
2336
2337
	return (no);
2338
}
2339
2340
int
2341
mib_pflabelnum(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2342
{
2343
	struct pfioc_rule	 pr;
2344
	u_int32_t		 nr, mnr, lnr;
2345
	extern int		 devpf;
2346
2347
	memset(&pr, 0, sizeof(pr));
2348
	if (ioctl(devpf, DIOCGETRULES, &pr)) {
2349
		log_warn("DIOCGETRULES");
2350
		return (-1);
2351
	}
2352
2353
	mnr = pr.nr;
2354
	lnr = 0;
2355
	for (nr = 0; nr < mnr; ++nr) {
2356
		pr.nr = nr;
2357
		if (ioctl(devpf, DIOCGETRULE, &pr)) {
2358
			log_warn("DIOCGETRULE");
2359
			return (-1);
2360
		}
2361
2362
		if (pr.rule.label[0])
2363
			lnr++;
2364
	}
2365
2366
	*elm = ber_add_integer(*elm, lnr);
2367
2368
	return (0);
2369
}
2370
2371
int
2372
mib_pflabels(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2373
{
2374
	struct ber_element	*ber = *elm;
2375
	struct pfioc_rule	 pr;
2376
	struct pf_rule		*r = NULL;
2377
	u_int32_t		 nr, mnr, lnr;
2378
	u_int32_t		 idx;
2379
	extern int		 devpf;
2380
2381
	/* Get and verify the current row index */
2382
	idx = o->bo_id[OIDIDX_pfLabelEntry];
2383
2384
	memset(&pr, 0, sizeof(pr));
2385
	if (ioctl(devpf, DIOCGETRULES, &pr)) {
2386
		log_warn("DIOCGETRULES");
2387
		return (-1);
2388
	}
2389
2390
	mnr = pr.nr;
2391
	lnr = 0;
2392
	for (nr = 0; nr < mnr; ++nr) {
2393
		pr.nr = nr;
2394
		if (ioctl(devpf, DIOCGETRULE, &pr)) {
2395
			log_warn("DIOCGETRULE");
2396
			return (-1);
2397
		}
2398
2399
		if (pr.rule.label[0] && ++lnr == idx) {
2400
			r = &pr.rule;
2401
			break;
2402
		}
2403
	}
2404
2405
	if (r == NULL)
2406
		return (1);
2407
2408
	ber = ber_add_oid(ber, o);
2409
2410
	switch (o->bo_id[OIDIDX_pfLabel]) {
2411
	case 1:
2412
		ber = ber_add_integer(ber, lnr);
2413
		break;
2414
	case 2:
2415
		ber = ber_add_string(ber, r->label);
2416
		break;
2417
	case 3:
2418
		ber = ber_add_integer(ber, r->evaluations);
2419
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2420
		break;
2421
	case 4:
2422
		ber = ber_add_integer(ber, r->packets[IN] + r->packets[OUT]);
2423
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2424
		break;
2425
	case 5:
2426
		ber = ber_add_integer(ber, r->bytes[IN] + r->bytes[OUT]);
2427
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2428
		break;
2429
	case 6:
2430
		ber = ber_add_integer(ber, r->packets[IN]);
2431
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2432
		break;
2433
	case 7:
2434
		ber = ber_add_integer(ber, r->bytes[IN]);
2435
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2436
		break;
2437
	case 8:
2438
		ber = ber_add_integer(ber, r->packets[OUT]);
2439
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2440
		break;
2441
	case 9:
2442
		ber = ber_add_integer(ber, r->bytes[OUT]);
2443
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2444
		break;
2445
	case 10:
2446
		ber = ber_add_integer(ber, r->states_tot);
2447
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
2448
		break;
2449
	default:
2450
		return (1);
2451
	}
2452
2453
	return (0);
2454
}
2455
2456
int
2457
mib_pfsyncstats(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2458
{
2459
	int			 i;
2460
	int			 mib[] = { CTL_NET, PF_INET, IPPROTO_PFSYNC,
2461
				    PFSYNCCTL_STATS };
2462
	size_t			 len = sizeof(struct pfsyncstats);
2463
	struct pfsyncstats	 s;
2464
	struct statsmap {
2465
		u_int8_t	 m_id;
2466
		u_int64_t	*m_ptr;
2467
	}			 mapping[] = {
2468
		{ 1, &s.pfsyncs_ipackets },
2469
		{ 2, &s.pfsyncs_ipackets6 },
2470
		{ 3, &s.pfsyncs_badif },
2471
		{ 4, &s.pfsyncs_badttl },
2472
		{ 5, &s.pfsyncs_hdrops },
2473
		{ 6, &s.pfsyncs_badver },
2474
		{ 7, &s.pfsyncs_badact },
2475
		{ 8, &s.pfsyncs_badlen },
2476
		{ 9, &s.pfsyncs_badauth },
2477
		{ 10, &s.pfsyncs_stale },
2478
		{ 11, &s.pfsyncs_badval },
2479
		{ 12, &s.pfsyncs_badstate },
2480
		{ 13, &s.pfsyncs_opackets },
2481
		{ 14, &s.pfsyncs_opackets6 },
2482
		{ 15, &s.pfsyncs_onomem },
2483
		{ 16, &s.pfsyncs_oerrors }
2484
	};
2485
2486
	if (sysctl(mib, 4, &s, &len, NULL, 0) == -1) {
2487
		log_warn("sysctl");
2488
		return (-1);
2489
	}
2490
2491
	for (i = 0;
2492
	    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
2493
		if (oid->o_oid[OIDIDX_pfstatus] == mapping[i].m_id) {
2494
			*elm = ber_add_integer(*elm, *mapping[i].m_ptr);
2495
			ber_set_header(*elm, BER_CLASS_APPLICATION,
2496
			    SNMP_T_COUNTER64);
2497
			return (0);
2498
		}
2499
	}
2500
2501
	return (-1);
2502
}
2503
2504
int
2505
mib_sensornum(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2506
{
2507
	struct sensordev	 sensordev;
2508
	size_t			 len = sizeof(sensordev);
2509
	int			 mib[] = { CTL_HW, HW_SENSORS, 0 };
2510
	int			 i, c;
2511
2512
	for (i = c = 0; ; i++) {
2513
		mib[2] = i;
2514
		if (sysctl(mib, sizeofa(mib),
2515
		    &sensordev, &len, NULL, 0) == -1) {
2516
			if (errno == ENXIO)
2517
				continue;
2518
			if (errno == ENOENT)
2519
				break;
2520
			return (-1);
2521
		}
2522
		c += sensordev.sensors_count;
2523
	}
2524
2525
	*elm = ber_add_integer(*elm, c);
2526
	return (0);
2527
}
2528
2529
int
2530
mib_sensors(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2531
{
2532
	struct ber_element	*ber = *elm;
2533
	struct sensordev	 sensordev;
2534
	size_t			 len = sizeof(sensordev);
2535
	struct sensor		 sensor;
2536
	size_t			 slen = sizeof(sensor);
2537
	char			 desc[32];
2538
	int			 mib[] = { CTL_HW, HW_SENSORS, 0, 0, 0 };
2539
	int			 i, j, k;
2540
	u_int32_t		 idx = 0, n;
2541
	char			*s;
2542
2543
	/* Get and verify the current row index */
2544
	idx = o->bo_id[OIDIDX_sensorEntry];
2545
2546
	for (i = 0, n = 1; ; i++) {
2547
		mib[2] = i;
2548
		if (sysctl(mib, 3, &sensordev, &len, NULL, 0) == -1) {
2549
			if (errno == ENXIO)
2550
				continue;
2551
			if (errno == ENOENT)
2552
				break;
2553
			return (-1);
2554
		}
2555
		for (j = 0; j < SENSOR_MAX_TYPES; j++) {
2556
			mib[3] = j;
2557
			for (k = 0; k < sensordev.maxnumt[j]; k++) {
2558
				mib[4] = k;
2559
				if (sysctl(mib, 5,
2560
				    &sensor, &slen, NULL, 0) == -1) {
2561
					if (errno == ENXIO)
2562
						continue;
2563
					if (errno == ENOENT)
2564
						break;
2565
					return (-1);
2566
				}
2567
				if (sensor.flags & SENSOR_FINVALID)
2568
					continue;
2569
				if (n == idx)
2570
					goto found;
2571
				n++;
2572
			}
2573
		}
2574
	}
2575
	return (1);
2576
2577
 found:
2578
	ber = ber_add_oid(ber, o);
2579
2580
	switch (o->bo_id[OIDIDX_sensor]) {
2581
	case 1:
2582
		ber = ber_add_integer(ber, (int32_t)n);
2583
		break;
2584
	case 2:
2585
		if (sensor.desc[0] == '\0') {
2586
			snprintf(desc, sizeof(desc), "%s%d",
2587
			    sensor_type_s[sensor.type],
2588
			    sensor.numt);
2589
			ber = ber_add_string(ber, desc);
2590
		} else
2591
			ber = ber_add_string(ber, sensor.desc);
2592
		break;
2593
	case 3:
2594
		ber = ber_add_integer(ber, sensor.type);
2595
		break;
2596
	case 4:
2597
		ber = ber_add_string(ber, sensordev.xname);
2598
		break;
2599
	case 5:
2600
		if ((s = mib_sensorvalue(&sensor)) == NULL)
2601
			return (-1);
2602
		ber = ber_add_string(ber, s);
2603
		free(s);
2604
		break;
2605
	case 6:
2606
		ber = ber_add_string(ber, mib_sensorunit(&sensor));
2607
		break;
2608
	case 7:
2609
		ber = ber_add_integer(ber, sensor.status);
2610
		break;
2611
	}
2612
2613
	return (0);
2614
}
2615
2616
#define SENSOR_DRIVE_STATES	(SENSOR_DRIVE_PFAIL + 1)
2617
static const char * const sensor_drive_s[SENSOR_DRIVE_STATES] = {
2618
	NULL, "empty", "ready", "powerup", "online", "idle", "active",
2619
	"rebuild", "powerdown", "fail", "pfail"
2620
};
2621
2622
static const char * const sensor_unit_s[SENSOR_MAX_TYPES + 1] = {
2623
	"degC",	"RPM", "V DC", "V AC", "Ohm", "W", "A", "Wh", "Ah",
2624
	"", "", "%", "lx", "", "sec", "%RH", "Hz", "degree",
2625
	"mm", "Pa", "m/s^2", ""
2626
};
2627
2628
const char *
2629
mib_sensorunit(struct sensor *s)
2630
{
2631
	u_int	 idx;
2632
	idx = s->type > SENSOR_MAX_TYPES ?
2633
	    SENSOR_MAX_TYPES : s->type;
2634
	return (sensor_unit_s[idx]);
2635
}
2636
2637
char *
2638
mib_sensorvalue(struct sensor *s)
2639
{
2640
	char	*v;
2641
	int	 ret = -1;
2642
2643
	switch (s->type) {
2644
	case SENSOR_TEMP:
2645
		ret = asprintf(&v, "%.2f",
2646
		    (s->value - 273150000) / 1000000.0);
2647
		break;
2648
	case SENSOR_VOLTS_DC:
2649
	case SENSOR_VOLTS_AC:
2650
	case SENSOR_WATTS:
2651
	case SENSOR_AMPS:
2652
	case SENSOR_WATTHOUR:
2653
	case SENSOR_AMPHOUR:
2654
	case SENSOR_LUX:
2655
	case SENSOR_FREQ:
2656
	case SENSOR_ACCEL:
2657
		ret = asprintf(&v, "%.2f", s->value / 1000000.0);
2658
		break;
2659
	case SENSOR_INDICATOR:
2660
		ret = asprintf(&v, "%s", s->value ? "on" : "off");
2661
		break;
2662
	case SENSOR_PERCENT:
2663
	case SENSOR_HUMIDITY:
2664
		ret = asprintf(&v, "%.2f", s->value / 1000.0);
2665
		break;
2666
	case SENSOR_DISTANCE:
2667
	case SENSOR_PRESSURE:
2668
		ret = asprintf(&v, "%.2f", s->value / 1000.0);
2669
		break;
2670
	case SENSOR_TIMEDELTA:
2671
		ret = asprintf(&v, "%.6f", s->value / 1000000000.0);
2672
		break;
2673
	case SENSOR_DRIVE:
2674
		if (s->value > 0 && s->value < SENSOR_DRIVE_STATES) {
2675
			ret = asprintf(&v, "%s", sensor_drive_s[s->value]);
2676
			break;
2677
		}
2678
		/* FALLTHROUGH */
2679
	case SENSOR_FANRPM:
2680
	case SENSOR_OHMS:
2681
	case SENSOR_INTEGER:
2682
	default:
2683
		ret = asprintf(&v, "%lld", s->value);
2684
		break;
2685
	}
2686
2687
	if (ret == -1)
2688
		return (NULL);
2689
	return (v);
2690
}
2691
2692
int
2693
mib_carpsysctl(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2694
{
2695
	size_t	 len;
2696
	int	 mib[] = { CTL_NET, PF_INET, IPPROTO_CARP, 0 };
2697
	int	 v;
2698
2699
	mib[3] = oid->o_oid[OIDIDX_carpsysctl];
2700
	len = sizeof(v);
2701
2702
	if (sysctl(mib, 4, &v, &len, NULL, 0) == -1)
2703
		return (1);
2704
2705
	*elm = ber_add_integer(*elm, v);
2706
	return (0);
2707
}
2708
2709
int
2710
mib_carpstats(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2711
{
2712
	int			 mib[] = { CTL_NET, PF_INET, IPPROTO_CARP,
2713
				    CARPCTL_STATS };
2714
	size_t			 len;
2715
	struct			 carpstats stats;
2716
	int			 i;
2717
	struct statsmap {
2718
		u_int8_t	 m_id;
2719
		u_int64_t	*m_ptr;
2720
	}			 mapping[] = {
2721
		{ 1, &stats.carps_ipackets },
2722
		{ 2, &stats.carps_ipackets6 },
2723
		{ 3, &stats.carps_badif },
2724
		{ 4, &stats.carps_badttl },
2725
		{ 5, &stats.carps_hdrops },
2726
		{ 6, &stats.carps_badsum },
2727
		{ 7, &stats.carps_badver },
2728
		{ 8, &stats.carps_badlen },
2729
		{ 9, &stats.carps_badauth },
2730
		{ 10, &stats.carps_badvhid },
2731
		{ 11, &stats.carps_badaddrs },
2732
		{ 12, &stats.carps_opackets },
2733
		{ 13, &stats.carps_opackets6 },
2734
		{ 14, &stats.carps_onomem },
2735
		{ 15, &stats.carps_preempt }
2736
	};
2737
2738
	len = sizeof(stats);
2739
2740
	if (sysctl(mib, 4, &stats, &len, NULL, 0) == -1)
2741
		return (1);
2742
2743
	for (i = 0;
2744
	    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
2745
		if (oid->o_oid[OIDIDX_carpstats] == mapping[i].m_id) {
2746
			*elm = ber_add_integer(*elm, *mapping[i].m_ptr);
2747
			ber_set_header(*elm, BER_CLASS_APPLICATION,
2748
			    SNMP_T_COUNTER64);
2749
			return (0);
2750
		}
2751
	}
2752
2753
	return (-1);
2754
}
2755
2756
int
2757
mib_carpifnum(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2758
{
2759
	struct kif	*kif;
2760
	int		 c = 0;
2761
2762
	for (kif = kr_getif(0); kif != NULL;
2763
	    kif = kr_getnextif(kif->if_index))
2764
		if (kif->if_type == IFT_CARP)
2765
			c++;
2766
2767
	*elm = ber_add_integer(*elm, c);
2768
	return (0);
2769
}
2770
2771
struct carpif *
2772
mib_carpifget(u_int idx)
2773
{
2774
	struct kif	*kif;
2775
	struct carpif	*cif;
2776
	int		 s;
2777
	struct ifreq	 ifr;
2778
	struct carpreq	 carpr;
2779
2780
	if ((kif = kr_getif(idx)) == NULL || kif->if_type != IFT_CARP) {
2781
		/*
2782
		 * It may happen that an interface with a specific index
2783
		 * does not exist, has been removed, or is not a carp(4)
2784
		 * interface. Jump to the next available carp(4) interface
2785
		 * index.
2786
		 */
2787
		for (kif = kr_getif(0); kif != NULL;
2788
		    kif = kr_getnextif(kif->if_index)) {
2789
			if (kif->if_type != IFT_CARP)
2790
				continue;
2791
			if (kif->if_index > idx)
2792
				break;
2793
2794
		}
2795
		if (kif == NULL)
2796
			return (NULL);
2797
	}
2798
	idx = kif->if_index;
2799
2800
	/* Update interface information */
2801
	kr_updateif(idx);
2802
	if ((kif = kr_getif(idx)) == NULL) {
2803
		log_debug("mib_carpifget: interface %d disappeared?", idx);
2804
		return (NULL);
2805
	}
2806
2807
	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
2808
		return (NULL);
2809
2810
	memset(&ifr, 0, sizeof(ifr));
2811
	strlcpy(ifr.ifr_name, kif->if_name, sizeof(ifr.ifr_name));
2812
	memset((char *)&carpr, 0, sizeof(carpr));
2813
	ifr.ifr_data = (caddr_t)&carpr;
2814
2815
	if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) {
2816
		close(s);
2817
		return (NULL);
2818
	}
2819
2820
	cif = calloc(1, sizeof(struct carpif));
2821
	if (cif != NULL) {
2822
		memcpy(&cif->carpr, &carpr, sizeof(struct carpreq));
2823
		memcpy(&cif->kif, kif, sizeof(struct kif));
2824
	}
2825
2826
	close(s);
2827
2828
	return (cif);
2829
}
2830
2831
int
2832
mib_carpiftable(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2833
{
2834
	u_int32_t		 idx;
2835
	struct carpif		*cif;
2836
2837
	/* Get and verify the current row index */
2838
	idx = o->bo_id[OIDIDX_carpIfEntry];
2839
2840
	if ((cif = mib_carpifget(idx)) == NULL)
2841
		return (1);
2842
2843
	/* Tables need to prepend the OID on their own */
2844
	o->bo_id[OIDIDX_carpIfEntry] = cif->kif.if_index;
2845
	*elm = ber_add_oid(*elm, o);
2846
2847
	switch (o->bo_id[OIDIDX_carpIf]) {
2848
	case 1:
2849
		*elm = ber_add_integer(*elm, cif->kif.if_index);
2850
		break;
2851
	case 2:
2852
		*elm = ber_add_string(*elm, cif->kif.if_name);
2853
		break;
2854
	case 3:
2855
		*elm = ber_add_integer(*elm, cif->carpr.carpr_vhids[0]);
2856
		break;
2857
	case 4:
2858
		*elm = ber_add_string(*elm, cif->carpr.carpr_carpdev);
2859
		break;
2860
	case 5:
2861
		*elm = ber_add_integer(*elm, cif->carpr.carpr_advbase);
2862
		break;
2863
	case 6:
2864
		*elm = ber_add_integer(*elm, cif->carpr.carpr_advskews[0]);
2865
		break;
2866
	case 7:
2867
		*elm = ber_add_integer(*elm, cif->carpr.carpr_states[0]);
2868
		break;
2869
	default:
2870
		free(cif);
2871
		return (1);
2872
	}
2873
2874
	free(cif);
2875
	return (0);
2876
}
2877
2878
int
2879
mib_memiftable(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2880
{
2881
	struct ber_element	*ber = *elm;
2882
	u_int32_t		 idx = 0;
2883
	struct kif		*kif;
2884
2885
	idx = o->bo_id[OIDIDX_memIfEntry];
2886
	if ((kif = mib_ifget(idx)) == NULL)
2887
		return (1);
2888
2889
	o->bo_id[OIDIDX_memIfEntry] = kif->if_index;
2890
	ber = ber_add_oid(ber, o);
2891
2892
	switch (o->bo_id[OIDIDX_memIf]) {
2893
	case 1:
2894
		ber = ber_add_string(ber, kif->if_name);
2895
		break;
2896
	case 2:
2897
		ber = ber_add_integer(ber, 0);
2898
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
2899
		break;
2900
	default:
2901
		return (-1);
2902
	}
2903
2904
	return (0);
2905
}
2906
2907
/*
2908
 * Defined in IP-MIB.txt
2909
 */
2910
2911
int mib_getipstat(struct ipstat *);
2912
int mib_ipstat(struct oid *, struct ber_oid *, struct ber_element **);
2913
int mib_ipforwarding(struct oid *, struct ber_oid *, struct ber_element **);
2914
int mib_ipdefaultttl(struct oid *, struct ber_oid *, struct ber_element **);
2915
int mib_ipinhdrerrs(struct oid *, struct ber_oid *, struct ber_element **);
2916
int mib_ipinaddrerrs(struct oid *, struct ber_oid *, struct ber_element **);
2917
int mib_ipforwdgrams(struct oid *, struct ber_oid *, struct ber_element **);
2918
int mib_ipindiscards(struct oid *, struct ber_oid *, struct ber_element **);
2919
int mib_ipreasmfails(struct oid *, struct ber_oid *, struct ber_element **);
2920
int mib_ipfragfails(struct oid *, struct ber_oid *, struct ber_element **);
2921
int mib_iproutingdiscards(struct oid *, struct ber_oid *,
2922
    struct ber_element **);
2923
int mib_ipaddr(struct oid *, struct ber_oid *, struct ber_element **);
2924
struct ber_oid *
2925
    mib_ipaddrtable(struct oid *, struct ber_oid *, struct ber_oid *);
2926
int mib_physaddr(struct oid *, struct ber_oid *, struct ber_element **);
2927
struct ber_oid *
2928
    mib_physaddrtable(struct oid *, struct ber_oid *, struct ber_oid *);
2929
2930
static struct oid ip_mib[] = {
2931
	{ MIB(ipMIB),			OID_MIB },
2932
	{ MIB(ipForwarding),		OID_RD, mib_ipforwarding },
2933
	{ MIB(ipDefaultTTL),		OID_RD, mib_ipdefaultttl },
2934
	{ MIB(ipInReceives),		OID_RD, mib_ipstat },
2935
	{ MIB(ipInHdrErrors),		OID_RD, mib_ipinhdrerrs },
2936
	{ MIB(ipInAddrErrors),		OID_RD, mib_ipinaddrerrs },
2937
	{ MIB(ipForwDatagrams),		OID_RD, mib_ipforwdgrams },
2938
	{ MIB(ipInUnknownProtos),	OID_RD, mib_ipstat },
2939
#ifdef notyet
2940
	{ MIB(ipInDiscards) },
2941
#endif
2942
	{ MIB(ipInDelivers),		OID_RD, mib_ipstat },
2943
	{ MIB(ipOutRequests),		OID_RD, mib_ipstat },
2944
	{ MIB(ipOutDiscards),		OID_RD, mib_ipstat },
2945
	{ MIB(ipOutNoRoutes),		OID_RD, mib_ipstat },
2946
	{ MIB(ipReasmTimeout),		OID_RD, mps_getint, NULL,
2947
	    NULL, IPFRAGTTL },
2948
	{ MIB(ipReasmReqds),		OID_RD, mib_ipstat },
2949
	{ MIB(ipReasmOKs),		OID_RD, mib_ipstat },
2950
	{ MIB(ipReasmFails),		OID_RD, mib_ipreasmfails },
2951
	{ MIB(ipFragOKs),		OID_RD, mib_ipstat },
2952
	{ MIB(ipFragFails),		OID_RD, mib_ipfragfails },
2953
	{ MIB(ipFragCreates),		OID_RD, mib_ipstat },
2954
	{ MIB(ipAdEntAddr),		OID_TRD, mib_ipaddr, NULL,
2955
	    mib_ipaddrtable },
2956
	{ MIB(ipAdEntIfIndex),		OID_TRD, mib_ipaddr, NULL,
2957
	    mib_ipaddrtable },
2958
	{ MIB(ipAdEntNetMask),		OID_TRD, mib_ipaddr, NULL,
2959
	    mib_ipaddrtable },
2960
	{ MIB(ipAdEntBcastAddr),	OID_TRD, mib_ipaddr, NULL,
2961
	    mib_ipaddrtable },
2962
	{ MIB(ipAdEntReasmMaxSize),	OID_TRD, mib_ipaddr, NULL,
2963
	    mib_ipaddrtable },
2964
	{ MIB(ipNetToMediaIfIndex),	OID_TRD, mib_physaddr, NULL,
2965
	    mib_physaddrtable },
2966
	{ MIB(ipNetToMediaPhysAddress),	OID_TRD, mib_physaddr, NULL,
2967
	    mib_physaddrtable },
2968
	{ MIB(ipNetToMediaNetAddress),	OID_TRD, mib_physaddr, NULL,
2969
	    mib_physaddrtable },
2970
	{ MIB(ipNetToMediaType),	OID_TRD, mib_physaddr, NULL,
2971
	    mib_physaddrtable },
2972
#ifdef notyet
2973
	{ MIB(ipRoutingDiscards) },
2974
#endif
2975
	{ MIBEND }
2976
};
2977
2978
int
2979
mib_ipforwarding(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2980
{
2981
	int	mib[] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_FORWARDING };
2982
	int	v;
2983
	size_t	len = sizeof(v);
2984
2985
	if (sysctl(mib, sizeofa(mib), &v, &len, NULL, 0) == -1)
2986
		return (-1);
2987
2988
	/* ipForwarding: forwarding(1), notForwarding(2) */
2989
	*elm = ber_add_integer(*elm, (v == 0) ? 2 : 1);
2990
2991
	return (0);
2992
}
2993
2994
int
2995
mib_ipdefaultttl(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
2996
{
2997
	int	mib[] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
2998
	int	v;
2999
	size_t	len = sizeof(v);
3000
3001
	if (sysctl(mib, sizeofa(mib), &v, &len, NULL, 0) == -1)
3002
		return (-1);
3003
3004
	*elm = ber_add_integer(*elm, v);
3005
3006
	return (0);
3007
}
3008
3009
int
3010
mib_getipstat(struct ipstat *ipstat)
3011
{
3012
	int	 mib[] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS };
3013
	size_t	 len = sizeof(*ipstat);
3014
3015
	return (sysctl(mib, sizeofa(mib), ipstat, &len, NULL, 0));
3016
}
3017
3018
int
3019
mib_ipstat(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3020
{
3021
	struct ipstat		 ipstat;
3022
	long long		 i;
3023
	struct statsmap {
3024
		u_int8_t	 m_id;
3025
		u_long		*m_ptr;
3026
	}			 mapping[] = {
3027
		{ 3, &ipstat.ips_total },
3028
		{ 7, &ipstat.ips_noproto },
3029
		{ 9, &ipstat.ips_delivered },
3030
		{ 10, &ipstat.ips_localout },
3031
		{ 11, &ipstat.ips_odropped },
3032
		{ 12, &ipstat.ips_noroute },
3033
		{ 14, &ipstat.ips_fragments },
3034
		{ 15, &ipstat.ips_reassembled },
3035
		{ 17, &ipstat.ips_fragmented },
3036
		{ 19, &ipstat.ips_ofragments }
3037
	};
3038
3039
	if (mib_getipstat(&ipstat) == -1)
3040
		return (-1);
3041
3042
	for (i = 0;
3043
	    (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) {
3044
		if (oid->o_oid[OIDIDX_ip] == mapping[i].m_id) {
3045
			*elm = ber_add_integer(*elm, *mapping[i].m_ptr);
3046
			ber_set_header(*elm,
3047
			    BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3048
			return (0);
3049
		}
3050
	}
3051
3052
	return (-1);
3053
}
3054
3055
int
3056
mib_ipinhdrerrs(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3057
{
3058
	u_int32_t	errors;
3059
	struct ipstat	ipstat;
3060
3061
	if (mib_getipstat(&ipstat) == -1)
3062
		return (-1);
3063
3064
	errors = ipstat.ips_badsum + ipstat.ips_badvers +
3065
	    ipstat.ips_tooshort + ipstat.ips_toosmall +
3066
	    ipstat.ips_badhlen +  ipstat.ips_badlen +
3067
	    ipstat.ips_badoptions + ipstat.ips_toolong +
3068
	    ipstat.ips_badaddr;
3069
3070
	*elm = ber_add_integer(*elm, errors);
3071
	ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3072
3073
	return (0);
3074
}
3075
3076
int
3077
mib_ipinaddrerrs(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3078
{
3079
	u_int32_t	errors;
3080
	struct ipstat	ipstat;
3081
3082
	if (mib_getipstat(&ipstat) == -1)
3083
		return (-1);
3084
3085
	errors = ipstat.ips_cantforward + ipstat.ips_badaddr;
3086
3087
	*elm = ber_add_integer(*elm, errors);
3088
	ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3089
3090
	return (0);
3091
}
3092
3093
int
3094
mib_ipforwdgrams(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3095
{
3096
	u_int32_t	counter;
3097
	struct ipstat	ipstat;
3098
3099
	if (mib_getipstat(&ipstat) == -1)
3100
		return (-1);
3101
3102
	counter = ipstat.ips_forward + ipstat.ips_redirectsent;
3103
3104
	*elm = ber_add_integer(*elm, counter);
3105
	ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3106
3107
	return (0);
3108
}
3109
3110
int
3111
mib_ipindiscards(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3112
{
3113
	return (0);
3114
}
3115
3116
int
3117
mib_ipreasmfails(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3118
{
3119
	u_int32_t	counter;
3120
	struct ipstat	ipstat;
3121
3122
	if (mib_getipstat(&ipstat) == -1)
3123
		return (-1);
3124
3125
	counter = ipstat.ips_fragdropped + ipstat.ips_fragtimeout;
3126
3127
	*elm = ber_add_integer(*elm, counter);
3128
	ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3129
3130
	return (0);
3131
}
3132
3133
int
3134
mib_ipfragfails(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3135
{
3136
	u_int32_t	counter;
3137
	struct ipstat	ipstat;
3138
3139
	if (mib_getipstat(&ipstat) == -1)
3140
		return (-1);
3141
3142
	counter = ipstat.ips_badfrags + ipstat.ips_cantfrag;
3143
	*elm = ber_add_integer(*elm, counter);
3144
	ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3145
3146
	return (0);
3147
}
3148
3149
int
3150
mib_iproutingdiscards(struct oid *oid, struct ber_oid *o,
3151
    struct ber_element **elm)
3152
{
3153
	return (0);
3154
}
3155
3156
struct ber_oid *
3157
mib_ipaddrtable(struct oid *oid, struct ber_oid *o, struct ber_oid *no)
3158
{
3159
	struct sockaddr_in	 addr;
3160
	u_int32_t		 col, id;
3161
	struct oid		 a, b;
3162
	struct kif_addr		*ka;
3163
3164
	bzero(&addr, sizeof(addr));
3165
	addr.sin_family = AF_INET;
3166
	addr.sin_len = sizeof(addr);
3167
3168
	bcopy(&oid->o_id, no, sizeof(*no));
3169
	id = oid->o_oidlen - 1;
3170
3171
	if (o->bo_n >= oid->o_oidlen) {
3172
		/*
3173
		 * Compare the requested and the matched OID to see
3174
		 * if we have to iterate to the next element.
3175
		 */
3176
		bzero(&a, sizeof(a));
3177
		bcopy(o, &a.o_id, sizeof(struct ber_oid));
3178
		bzero(&b, sizeof(b));
3179
		bcopy(&oid->o_id, &b.o_id, sizeof(struct ber_oid));
3180
		b.o_oidlen--;
3181
		b.o_flags |= OID_TABLE;
3182
		if (smi_oid_cmp(&a, &b) == 0) {
3183
			col = oid->o_oid[id];
3184
			o->bo_id[id] = col;
3185
			bcopy(o, no, sizeof(*no));
3186
		}
3187
	}
3188
3189
	mps_decodeinaddr(no, &addr.sin_addr, OIDIDX_ipAddr + 1);
3190
	if (o->bo_n <= (OIDIDX_ipAddr + 1))
3191
		ka = kr_getaddr(NULL);
3192
	else
3193
		ka = kr_getnextaddr((struct sockaddr *)&addr);
3194
	if (ka == NULL || ka->addr.sa.sa_family != AF_INET) {
3195
		/*
3196
		 * Encode invalid "last address" marker which will tell
3197
		 * mib_ipaddr() to fail and the SNMP engine to find the
3198
		 * next OID.
3199
		 */
3200
		mps_encodeinaddr(no, NULL, OIDIDX_ipAddr + 1);
3201
	} else {
3202
		/* Encode real IPv4 address */
3203
		addr.sin_addr.s_addr = ka->addr.sin.sin_addr.s_addr;
3204
		mps_encodeinaddr(no, &addr.sin_addr, OIDIDX_ipAddr + 1);
3205
	}
3206
	smi_oidlen(o);
3207
3208
	return (no);
3209
}
3210
3211
int
3212
mib_ipaddr(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3213
{
3214
	struct sockaddr_in	 addr;
3215
	struct ber_element	*ber = *elm;
3216
	struct kif_addr		*ka;
3217
	u_int32_t		 val;
3218
3219
	bzero(&addr, sizeof(addr));
3220
	addr.sin_family = AF_INET;
3221
	addr.sin_len = sizeof(addr);
3222
3223
	if (mps_decodeinaddr(o, &addr.sin_addr, OIDIDX_ipAddr + 1) == -1) {
3224
		/* Strip invalid address and fail */
3225
		o->bo_n = OIDIDX_ipAddr + 1;
3226
		return (1);
3227
	}
3228
	ka = kr_getaddr((struct sockaddr *)&addr);
3229
	if (ka == NULL || ka->addr.sa.sa_family != AF_INET)
3230
		return (1);
3231
3232
	/* write OID */
3233
	ber = ber_add_oid(ber, o);
3234
3235
	switch (o->bo_id[OIDIDX_ipAddr]) {
3236
	case 1:
3237
		val = addr.sin_addr.s_addr;
3238
		ber = ber_add_nstring(ber, (char *)&val, sizeof(u_int32_t));
3239
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_IPADDR);
3240
		break;
3241
	case 2:
3242
		ber = ber_add_integer(ber, ka->if_index);
3243
		break;
3244
	case 3:
3245
		val = ka->mask.sin.sin_addr.s_addr;
3246
		ber = ber_add_nstring(ber, (char *)&val, sizeof(u_int32_t));
3247
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_IPADDR);
3248
		break;
3249
	case 4:
3250
		ber = ber_add_integer(ber, ka->dstbrd.sa.sa_len ? 1 : 0);
3251
		break;
3252
	case 5:
3253
		ber = ber_add_integer(ber, IP_MAXPACKET);
3254
		break;
3255
	default:
3256
		return (-1);
3257
	}
3258
3259
	return (0);
3260
}
3261
3262
struct ber_oid *
3263
mib_physaddrtable(struct oid *oid, struct ber_oid *o, struct ber_oid *no)
3264
{
3265
	struct sockaddr_in	 addr;
3266
	struct oid		 a, b;
3267
	struct kif		*kif;
3268
	struct kif_arp		*ka;
3269
	u_int32_t		 id, idx = 0;
3270
3271
	bcopy(&oid->o_id, no, sizeof(*no));
3272
	id = oid->o_oidlen - 1;
3273
3274
	if (o->bo_n >= oid->o_oidlen) {
3275
		/*
3276
		 * Compare the requested and the matched OID to see
3277
		 * if we have to iterate to the next element.
3278
		 */
3279
		bzero(&a, sizeof(a));
3280
		bcopy(o, &a.o_id, sizeof(struct ber_oid));
3281
		bzero(&b, sizeof(b));
3282
		bcopy(&oid->o_id, &b.o_id, sizeof(struct ber_oid));
3283
		b.o_oidlen--;
3284
		b.o_flags |= OID_TABLE;
3285
		if (smi_oid_cmp(&a, &b) == 0) {
3286
			o->bo_id[id] = oid->o_oid[id];
3287
			bcopy(o, no, sizeof(*no));
3288
		}
3289
	}
3290
3291
	if (o->bo_n > OIDIDX_ipNetToMedia + 1)
3292
		idx = o->bo_id[OIDIDX_ipNetToMedia + 1];
3293
3294
	bzero(&addr, sizeof(addr));
3295
	addr.sin_family = AF_INET;
3296
	addr.sin_len = sizeof(addr);
3297
	if (o->bo_n > OIDIDX_ipNetToMedia + 2)
3298
		mps_decodeinaddr(no, &addr.sin_addr, OIDIDX_ipNetToMedia + 2);
3299
3300
	if ((kif = kr_getif(idx)) == NULL) {
3301
		/* No configured interfaces */
3302
		if (idx == 0)
3303
			return (NULL);
3304
		/*
3305
		 * It may happen that an interface with a specific index
3306
		 * does not exist or has been removed.  Jump to the next
3307
		 * available interface.
3308
		 */
3309
		kif = kr_getif(0);
3310
 nextif:
3311
		for (; kif != NULL; kif = kr_getnextif(kif->if_index))
3312
			if (kif->if_index > idx &&
3313
			    (ka = karp_first(kif->if_index)) != NULL)
3314
				break;
3315
		if (kif == NULL) {
3316
			/* No more interfaces with addresses on them */
3317
			o->bo_id[OIDIDX_ipNetToMedia + 1] = 0;
3318
			mps_encodeinaddr(no, NULL, OIDIDX_ipNetToMedia + 2);
3319
			smi_oidlen(o);
3320
			return (NULL);
3321
		}
3322
	} else {
3323
		if (idx == 0 || addr.sin_addr.s_addr == 0)
3324
			ka = karp_first(kif->if_index);
3325
		else
3326
			ka = karp_getaddr((struct sockaddr *)&addr, idx, 1);
3327
		if (ka == NULL) {
3328
			/* Try next interface */
3329
			goto nextif;
3330
		}
3331
	}
3332
	idx = kif->if_index;
3333
3334
	no->bo_id[OIDIDX_ipNetToMedia + 1] = idx;
3335
	/* Encode real IPv4 address */
3336
	memcpy(&addr, &ka->addr.sin, ka->addr.sin.sin_len);
3337
	mps_encodeinaddr(no, &addr.sin_addr, OIDIDX_ipNetToMedia + 2);
3338
3339
	smi_oidlen(o);
3340
	return (no);
3341
}
3342
3343
int
3344
mib_physaddr(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3345
{
3346
	struct ber_element	*ber = *elm;
3347
	struct sockaddr_in	 addr;
3348
	struct kif_arp		*ka;
3349
	u_int32_t		 val, idx = 0;
3350
3351
	idx = o->bo_id[OIDIDX_ipNetToMedia + 1];
3352
	if (idx == 0) {
3353
		/* Strip invalid interface index and fail */
3354
		o->bo_n = OIDIDX_ipNetToMedia + 1;
3355
		return (1);
3356
	}
3357
3358
	/* Get the IP address */
3359
	bzero(&addr, sizeof(addr));
3360
	addr.sin_family = AF_INET;
3361
	addr.sin_len = sizeof(addr);
3362
3363
	if (mps_decodeinaddr(o, &addr.sin_addr,
3364
	    OIDIDX_ipNetToMedia + 2) == -1) {
3365
		/* Strip invalid address and fail */
3366
		o->bo_n = OIDIDX_ipNetToMedia + 2;
3367
		return (1);
3368
	}
3369
	if ((ka = karp_getaddr((struct sockaddr *)&addr, idx, 0)) == NULL)
3370
		return (1);
3371
3372
	/* write OID */
3373
	ber = ber_add_oid(ber, o);
3374
3375
	switch (o->bo_id[OIDIDX_ipNetToMedia]) {
3376
	case 1: /* ipNetToMediaIfIndex */
3377
		ber = ber_add_integer(ber, ka->if_index);
3378
		break;
3379
	case 2: /* ipNetToMediaPhysAddress */
3380
		if (bcmp(LLADDR(&ka->target.sdl), ether_zeroaddr,
3381
		    sizeof(ether_zeroaddr)) == 0)
3382
			ber = ber_add_nstring(ber, ether_zeroaddr,
3383
			    sizeof(ether_zeroaddr));
3384
		else
3385
			ber = ber_add_nstring(ber, LLADDR(&ka->target.sdl),
3386
			    ka->target.sdl.sdl_alen);
3387
		break;
3388
	case 3:	/* ipNetToMediaNetAddress */
3389
		val = addr.sin_addr.s_addr;
3390
		ber = ber_add_nstring(ber, (char *)&val, sizeof(u_int32_t));
3391
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_IPADDR);
3392
		break;
3393
	case 4: /* ipNetToMediaType */
3394
		if (ka->flags & F_STATIC)
3395
			ber = ber_add_integer(ber, 4); /* static */
3396
		else
3397
			ber = ber_add_integer(ber, 3); /* dynamic */
3398
		break;
3399
	default:
3400
		return (-1);
3401
	}
3402
	return (0);
3403
}
3404
3405
/*
3406
 * Defined in IP-FORWARD-MIB.txt (rfc4292)
3407
 */
3408
3409
int mib_ipfnroutes(struct oid *, struct ber_oid *, struct ber_element **);
3410
struct ber_oid *
3411
mib_ipfroutetable(struct oid *oid, struct ber_oid *o, struct ber_oid *no);
3412
int mib_ipfroute(struct oid *, struct ber_oid *, struct ber_element **);
3413
3414
static struct oid ipf_mib[] = {
3415
	{ MIB(ipfMIB),			OID_MIB },
3416
	{ MIB(ipfInetCidrRouteNumber),	OID_RD, mib_ipfnroutes },
3417
3418
	{ MIB(ipfRouteEntIfIndex),	OID_TRD, mib_ipfroute, NULL,
3419
	    mib_ipfroutetable },
3420
	{ MIB(ipfRouteEntType),		OID_TRD, mib_ipfroute, NULL,
3421
	    mib_ipfroutetable },
3422
	{ MIB(ipfRouteEntProto),	OID_TRD, mib_ipfroute, NULL,
3423
	    mib_ipfroutetable },
3424
	{ MIB(ipfRouteEntAge),		OID_TRD, mib_ipfroute, NULL,
3425
	    mib_ipfroutetable },
3426
	{ MIB(ipfRouteEntNextHopAS),	OID_TRD, mib_ipfroute, NULL,
3427
	    mib_ipfroutetable },
3428
	{ MIB(ipfRouteEntRouteMetric1),	OID_TRD, mib_ipfroute, NULL,
3429
	    mib_ipfroutetable },
3430
	{ MIB(ipfRouteEntRouteMetric2),	OID_TRD, mib_ipfroute, NULL,
3431
	    mib_ipfroutetable },
3432
	{ MIB(ipfRouteEntRouteMetric3),	OID_TRD, mib_ipfroute, NULL,
3433
	    mib_ipfroutetable },
3434
	{ MIB(ipfRouteEntRouteMetric4),	OID_TRD, mib_ipfroute, NULL,
3435
	    mib_ipfroutetable },
3436
	{ MIB(ipfRouteEntRouteMetric5),	OID_TRD, mib_ipfroute, NULL,
3437
	    mib_ipfroutetable },
3438
	{ MIB(ipfRouteEntStatus),	OID_TRD, mib_ipfroute, NULL,
3439
	    mib_ipfroutetable },
3440
	{ MIBEND }
3441
};
3442
3443
int
3444
mib_ipfnroutes(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3445
{
3446
	*elm = ber_add_integer(*elm, kr_routenumber());
3447
	ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_GAUGE32);
3448
3449
	return (0);
3450
}
3451
3452
struct ber_oid *
3453
mib_ipfroutetable(struct oid *oid, struct ber_oid *o, struct ber_oid *no)
3454
{
3455
	u_int32_t		 col, id;
3456
	struct oid		 a, b;
3457
	struct sockaddr_in	 addr;
3458
	struct kroute		*kr;
3459
	int			 af, atype, idx;
3460
	u_int8_t		 prefixlen;
3461
	u_int8_t		 prio;
3462
3463
	bzero(&addr, sizeof(addr));
3464
	addr.sin_family = AF_INET;
3465
	addr.sin_len = sizeof(addr);
3466
3467
	bcopy(&oid->o_id, no, sizeof(*no));
3468
	id = oid->o_oidlen - 1;
3469
3470
	if (o->bo_n >= oid->o_oidlen) {
3471
		/*
3472
		 * Compare the requested and the matched OID to see
3473
		 * if we have to iterate to the next element.
3474
		 */
3475
		bzero(&a, sizeof(a));
3476
		bcopy(o, &a.o_id, sizeof(struct ber_oid));
3477
		bzero(&b, sizeof(b));
3478
		bcopy(&oid->o_id, &b.o_id, sizeof(struct ber_oid));
3479
		b.o_oidlen--;
3480
		b.o_flags |= OID_TABLE;
3481
		if (smi_oid_cmp(&a, &b) == 0) {
3482
			col = oid->o_oid[id];
3483
			o->bo_id[id] = col;
3484
			bcopy(o, no, sizeof(*no));
3485
		}
3486
	}
3487
3488
	af = no->bo_id[OIDIDX_ipfInetCidrRoute + 1];
3489
	mps_decodeinaddr(no, &addr.sin_addr, OIDIDX_ipfInetCidrRoute + 3);
3490
	prefixlen = o->bo_id[OIDIDX_ipfInetCidrRoute + 7];
3491
	prio = o->bo_id[OIDIDX_ipfInetCidrRoute + 10];
3492
3493
	if (af == 0)
3494
		kr = kroute_first();
3495
	else
3496
		kr = kroute_getaddr(addr.sin_addr.s_addr, prefixlen, prio, 1);
3497
3498
	if (kr == NULL) {
3499
		addr.sin_addr.s_addr = 0;
3500
		prefixlen = 0;
3501
		prio = 0;
3502
		addr.sin_family = 0;
3503
	} else {
3504
		addr.sin_addr.s_addr = kr->prefix.s_addr;
3505
		prefixlen = kr->prefixlen;
3506
		prio = kr->priority;
3507
	}
3508
3509
	switch (addr.sin_family) {
3510
	case AF_INET:
3511
		atype = 1;
3512
		break;
3513
	case AF_INET6:
3514
		atype = 2;
3515
		break;
3516
	default:
3517
		atype = 0;
3518
		break;
3519
	}
3520
	idx = OIDIDX_ipfInetCidrRoute + 1;
3521
	no->bo_id[idx++] = atype;
3522
	no->bo_id[idx++] = 0x04;
3523
	no->bo_n++;
3524
3525
	mps_encodeinaddr(no, &addr.sin_addr, idx);
3526
	no->bo_id[no->bo_n++] = prefixlen;
3527
	no->bo_id[no->bo_n++] = 0x02;
3528
	no->bo_n += 2; /* policy */
3529
	no->bo_id[OIDIDX_ipfInetCidrRoute + 10]  = prio;
3530
3531
	if (kr != NULL) {
3532
		no->bo_id[no->bo_n++] = atype;
3533
		no->bo_id[no->bo_n++] = 0x04;
3534
		mps_encodeinaddr(no, &kr->nexthop, no->bo_n);
3535
	} else
3536
		no->bo_n += 2;
3537
3538
	smi_oidlen(o);
3539
3540
	return (no);
3541
}
3542
3543
int
3544
mib_ipfroute(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3545
{
3546
	struct ber_element	*ber = *elm;
3547
	struct kroute		*kr;
3548
	struct sockaddr_in	 addr, nhaddr;
3549
	int			 idx = o->bo_id[OIDIDX_ipfInetCidrRoute];
3550
	int			 af;
3551
	u_int8_t		 prefixlen, prio, type, proto;
3552
3553
3554
	bzero(&addr, sizeof(addr));
3555
	addr.sin_family = AF_INET;
3556
	addr.sin_len = sizeof(addr);
3557
3558
	af = o->bo_id[OIDIDX_ipfInetCidrRoute + 1];
3559
	mps_decodeinaddr(o, &addr.sin_addr, OIDIDX_ipfInetCidrRoute + 3);
3560
	mps_decodeinaddr(o, &nhaddr.sin_addr, OIDIDX_ipfInetCidrRoute + 23);
3561
	prefixlen = o->bo_id[OIDIDX_ipfInetCidrRoute + 7];
3562
	prio = o->bo_id[OIDIDX_ipfInetCidrRoute + 10];
3563
	kr = kroute_getaddr(addr.sin_addr.s_addr, prefixlen, prio, 0);
3564
	if (kr == NULL || af == 0) {
3565
		return (1);
3566
	}
3567
3568
	/* write OID */
3569
	ber = ber_add_oid(ber, o);
3570
3571
	switch (idx) {
3572
	case 7: /* IfIndex */
3573
		ber = ber_add_integer(ber, kr->if_index);
3574
		break;
3575
	case 8: /* Type */
3576
		if (kr->flags & F_REJECT)
3577
			type = 2;
3578
		else if (kr->flags & F_BLACKHOLE)
3579
			type = 5;
3580
		else if (kr->flags & F_CONNECTED)
3581
			type = 3;
3582
		else
3583
			type = 4;
3584
		ber = ber_add_integer(ber, type);
3585
		break;
3586
	case 9: /* Proto */
3587
		switch (kr->priority) {
3588
		case RTP_CONNECTED:
3589
			proto = 2;
3590
			break;
3591
		case RTP_STATIC:
3592
			proto = 3;
3593
			break;
3594
		case RTP_OSPF:
3595
			proto = 13;
3596
			break;
3597
		case RTP_ISIS:
3598
			proto = 9;
3599
			break;
3600
		case RTP_RIP:
3601
			proto = 8;
3602
			break;
3603
		case RTP_BGP:
3604
			proto = 14;
3605
			break;
3606
		default:
3607
			if (kr->flags & F_DYNAMIC)
3608
				proto = 4;
3609
			else
3610
				proto = 1; /* not specified */
3611
			break;
3612
		}
3613
		ber = ber_add_integer(ber, proto);
3614
		break;
3615
	case 10: /* Age */
3616
		ber = ber_add_integer(ber, 0);
3617
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_GAUGE32);
3618
		break;
3619
	case 11: /* NextHopAS */
3620
		ber = ber_add_integer(ber, 0);	/* unknown */
3621
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_GAUGE32);
3622
		break;
3623
	case 12: /* Metric1 */
3624
		ber = ber_add_integer(ber, -1);	/* XXX */
3625
		break;
3626
	case 13: /* Metric2 */
3627
		ber = ber_add_integer(ber, -1);	/* XXX */
3628
		break;
3629
	case 14: /* Metric3 */
3630
		ber = ber_add_integer(ber, -1);	/* XXX */
3631
		break;
3632
	case 15: /* Metric4 */
3633
		ber = ber_add_integer(ber, -1);	/* XXX */
3634
		break;
3635
	case 16: /* Metric5 */
3636
		ber = ber_add_integer(ber, -1);	/* XXX */
3637
		break;
3638
	case 17: /* Status */
3639
		ber = ber_add_integer(ber, 1);	/* XXX */
3640
		break;
3641
	default:
3642
		return (-1);
3643
	}
3644
3645
	return (0);
3646
}
3647
3648
/*
3649
 * Defined in UCD-DISKIO-MIB.txt.
3650
 */
3651
3652
int	mib_diskio(struct oid *oid, struct ber_oid *o, struct ber_element **elm);
3653
3654
static struct oid diskio_mib[] = {
3655
	{ MIB(ucdDiskIOMIB),			OID_MIB },
3656
	{ MIB(diskIOIndex),			OID_TRD, mib_diskio },
3657
	{ MIB(diskIODevice),			OID_TRD, mib_diskio },
3658
	{ MIB(diskIONRead),			OID_TRD, mib_diskio },
3659
	{ MIB(diskIONWritten),			OID_TRD, mib_diskio },
3660
	{ MIB(diskIOReads),			OID_TRD, mib_diskio },
3661
	{ MIB(diskIOWrites),			OID_TRD, mib_diskio },
3662
	{ MIB(diskIONReadX),			OID_TRD, mib_diskio },
3663
	{ MIB(diskIONWrittenX),			OID_TRD, mib_diskio },
3664
	{ MIBEND }
3665
};
3666
3667
int
3668
mib_diskio(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3669
{
3670
	struct ber_element	*ber = *elm;
3671
	u_int32_t		 idx;
3672
	int			 mib[] = { CTL_HW, 0 };
3673
	unsigned int		 diskcount;
3674
	struct diskstats	*stats;
3675
	size_t			 len;
3676
3677
	len = sizeof(diskcount);
3678
	mib[1] = HW_DISKCOUNT;
3679
	if (sysctl(mib, sizeofa(mib), &diskcount, &len, NULL, 0) == -1)
3680
		return (-1);
3681
3682
	/* Get and verify the current row index */
3683
	idx = o->bo_id[OIDIDX_diskIOEntry];
3684
	if (idx > diskcount)
3685
		return (1);
3686
3687
	/* Tables need to prepend the OID on their own */
3688
	o->bo_id[OIDIDX_diskIOEntry] = idx;
3689
	ber = ber_add_oid(ber, o);
3690
3691
	stats = calloc(diskcount, sizeof(*stats));
3692
	if (stats == NULL)
3693
		return (-1);
3694
	/* We know len won't overflow, otherwise calloc() would have failed. */
3695
	len = diskcount * sizeof(*stats);
3696
	mib[1] = HW_DISKSTATS;
3697
	if (sysctl(mib, sizeofa(mib), stats, &len, NULL, 0) == -1) {
3698
		free(stats);
3699
		return (-1);
3700
	}
3701
3702
	switch (o->bo_id[OIDIDX_diskIO]) {
3703
	case 1: /* diskIOIndex */
3704
		ber = ber_add_integer(ber, idx);
3705
		break;
3706
	case 2: /* diskIODevice */
3707
		ber = ber_add_string(ber, stats[idx - 1].ds_name);
3708
		break;
3709
	case 3: /* diskIONRead */
3710
		ber = ber_add_integer(ber, (u_int32_t)stats[idx - 1].ds_rbytes);
3711
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3712
		break;
3713
	case 4: /* diskIONWritten */
3714
		ber = ber_add_integer(ber, (u_int32_t)stats[idx - 1].ds_wbytes);
3715
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3716
		break;
3717
	case 5: /* diskIOReads */
3718
		ber = ber_add_integer(ber, (u_int32_t)stats[idx - 1].ds_rxfer);
3719
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3720
		break;
3721
	case 6: /* diskIOWrites */
3722
		ber = ber_add_integer(ber, (u_int32_t)stats[idx - 1].ds_wxfer);
3723
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3724
		break;
3725
	case 12: /* diskIONReadX */
3726
		ber = ber_add_integer(ber, stats[idx - 1].ds_rbytes);
3727
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
3728
		break;
3729
	case 13: /* diskIONWrittenX */
3730
		ber = ber_add_integer(ber, stats[idx - 1].ds_wbytes);
3731
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
3732
		break;
3733
	default:
3734
		free(stats);
3735
		return (-1);
3736
	}
3737
3738
	free(stats);
3739
	return (0);
3740
}
3741
3742
/*
3743
 * Defined in BRIDGE-MIB.txt (rfc1493)
3744
 *
3745
 * This MIB is required by some NMS to accept the device because
3746
 * the RFC says that mostly any network device has to provide this MIB... :(
3747
 */
3748
3749
int	 mib_dot1dtable(struct oid *, struct ber_oid *, struct ber_element **);
3750
3751
static struct oid bridge_mib[] = {
3752
	{ MIB(dot1dBridge),		OID_MIB },
3753
	{ MIB(dot1dBaseBridgeAddress) },
3754
	{ MIB(dot1dBaseNumPorts),	OID_RD, mib_ifnumber },
3755
	{ MIB(dot1dBaseType),		OID_RD, mps_getint, NULL,
3756
	    NULL, 4 /* srt (sourceroute + transparent) */ },
3757
	{ MIB(dot1dBasePort),		OID_TRD, mib_dot1dtable },
3758
	{ MIB(dot1dBasePortIfIndex),	OID_TRD, mib_dot1dtable },
3759
	{ MIB(dot1dBasePortCircuit),	OID_TRD, mib_dot1dtable},
3760
	{ MIB(dot1dBasePortDelayExceededDiscards), OID_TRD, mib_dot1dtable },
3761
	{ MIB(dot1dBasePortMtuExceededDiscards), OID_TRD, mib_dot1dtable },
3762
	{ MIBEND }
3763
};
3764
3765
int
3766
mib_dot1dtable(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
3767
{
3768
	struct ber_element	*ber = *elm;
3769
	u_int32_t		 idx = 0;
3770
	struct kif		*kif;
3771
3772
	/* Get and verify the current row index */
3773
	idx = o->bo_id[OIDIDX_dot1dEntry];
3774
	if ((kif = mib_ifget(idx)) == NULL)
3775
		return (1);
3776
3777
	/* Tables need to prepend the OID on their own */
3778
	o->bo_id[OIDIDX_dot1dEntry] = kif->if_index;
3779
	ber = ber_add_oid(ber, o);
3780
3781
	switch (o->bo_id[OIDIDX_dot1d]) {
3782
	case 1:
3783
	case 2:
3784
		ber = ber_add_integer(ber, kif->if_index);
3785
		break;
3786
	case 3:
3787
		ber = ber_add_oid(ber, &zerodotzero);
3788
		break;
3789
	case 4:
3790
	case 5:
3791
		ber = ber_add_integer(ber, 0);
3792
		ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
3793
		break;
3794
	}
3795
3796
	return (0);
3797
}
3798
3799
/*
3800
 * Import all MIBs
3801
 */
3802
3803
void
3804
mib_init(void)
3805
{
3806
	/*
3807
	 * MIB declarations (to register the OID names)
3808
	 */
3809
32
	smi_mibtree(mib_tree);
3810
3811
	/*
3812
	 * MIB definitions (the implementation)
3813
	 */
3814
3815
	/* SNMPv2-MIB */
3816
16
	smi_mibtree(base_mib);
3817
3818
	/* SNMP-USER-BASED-SM-MIB */
3819
16
	smi_mibtree(usm_mib);
3820
3821
	/* HOST-RESOURCES-MIB */
3822
16
	smi_mibtree(hr_mib);
3823
3824
	/* IF-MIB */
3825
16
	smi_mibtree(if_mib);
3826
3827
	/* IP-MIB */
3828
16
	smi_mibtree(ip_mib);
3829
3830
	/* IP-FORWARD-MIB */
3831
16
	smi_mibtree(ipf_mib);
3832
3833
	/* BRIDGE-MIB */
3834
16
	smi_mibtree(bridge_mib);
3835
3836
	/* UCD-DISKIO-MIB */
3837
16
	smi_mibtree(diskio_mib);
3838
3839
	/* OPENBSD-MIB */
3840
16
	smi_mibtree(openbsd_mib);
3841
16
}