xref: /openbsd-src/usr.sbin/snmpd/application_internal.c (revision 1ad61ae0a79a724d2d3ec69e69c8e1d1ff6b53a0)
1 /*	$OpenBSD: application_internal.c,v 1.7 2023/11/08 19:46:28 martijn Exp $	*/
2 
3 /*
4  * Copyright (c) 2023 Martijn van Duren <martijn@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/tree.h>
20 
21 #include <event.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 
25 #include "application.h"
26 #include "log.h"
27 #include "mib.h"
28 #include "smi.h"
29 #include "snmpd.h"
30 
31 struct appl_internal_object {
32 	struct ber_oid			 oid;
33 	struct ber_element *		(*get)(struct ber_oid *);
34 	/* No getnext means the object is scalar */
35 	struct ber_element *		(*getnext)(int8_t, struct ber_oid *);
36 
37 	RB_ENTRY(appl_internal_object)	 entry;
38 };
39 
40 void appl_internal_region(struct ber_oid *);
41 void appl_internal_object(struct ber_oid *,
42     struct ber_element *(*)(struct ber_oid *),
43     struct ber_element *(*)(int8_t, struct ber_oid *));
44 void appl_internal_get(struct appl_backend *, int32_t, int32_t, const char *,
45     struct appl_varbind *);
46 void appl_internal_getnext(struct appl_backend *, int32_t, int32_t,
47     const char *, struct appl_varbind *);
48 struct ber_element *appl_internal_snmp(struct ber_oid *);
49 struct ber_element *appl_internal_engine(struct ber_oid *);
50 struct ber_element *appl_internal_usmstats(struct ber_oid *);
51 struct ber_element *appl_internal_system(struct ber_oid *);
52 struct appl_internal_object *appl_internal_object_parent(struct ber_oid *);
53 int appl_internal_object_cmp(struct appl_internal_object *,
54     struct appl_internal_object *);
55 
56 struct appl_backend_functions appl_internal_functions = {
57 	.ab_get = appl_internal_get,
58 	.ab_getnext = appl_internal_getnext,
59 	.ab_getbulk = NULL, /* getbulk is too complex */
60 };
61 
62 struct appl_backend appl_internal = {
63 	.ab_name = "internal",
64 	.ab_cookie = NULL,
65 	.ab_retries = 0,
66 	.ab_range = 1,
67 	.ab_fn = &appl_internal_functions
68 };
69 
70 static RB_HEAD(appl_internal_objects, appl_internal_object)
71     appl_internal_objects = RB_INITIALIZER(&appl_internal_objects);
72 RB_PROTOTYPE_STATIC(appl_internal_objects, appl_internal_object, entry,
73     appl_internal_object_cmp);
74 
75 void
76 appl_internal_init(void)
77 {
78 	appl_internal_region(&OID(MIB_system));
79 	appl_internal_object(&OID(MIB_sysDescr), appl_internal_system, NULL);
80 	appl_internal_object(&OID(MIB_sysOID), appl_internal_system, NULL);
81 	appl_internal_object(&OID(MIB_sysUpTime), appl_internal_system, NULL);
82 	appl_internal_object(&OID(MIB_sysContact), appl_internal_system, NULL);
83 	appl_internal_object(&OID(MIB_sysName), appl_internal_system, NULL);
84 	appl_internal_object(&OID(MIB_sysLocation), appl_internal_system, NULL);
85 	appl_internal_object(&OID(MIB_sysServices), appl_internal_system, NULL);
86 	appl_internal_object(&OID(MIB_sysORLastChange), appl_sysorlastchange,
87 	    NULL);
88 
89 	appl_internal_object(&OID(MIB_sysORID), appl_sysortable,
90 	    appl_sysortable_getnext);
91 	appl_internal_object(&OID(MIB_sysORDescr), appl_sysortable,
92 	    appl_sysortable_getnext);
93 	appl_internal_object(&OID(MIB_sysORUpTime), appl_sysortable,
94 	    appl_sysortable_getnext);
95 
96 	appl_internal_region(&OID(MIB_snmp));
97 	appl_internal_object(&OID(MIB_snmpInPkts), appl_internal_snmp, NULL);
98 	appl_internal_object(&OID(MIB_snmpOutPkts), appl_internal_snmp, NULL);
99 	appl_internal_object(&OID(MIB_snmpInBadVersions), appl_internal_snmp,
100 	   NULL);
101 	appl_internal_object(&OID(MIB_snmpInBadCommunityNames),
102 	   appl_internal_snmp, NULL);
103 	appl_internal_object(&OID(MIB_snmpInBadCommunityUses),
104 	   appl_internal_snmp, NULL);
105 	appl_internal_object(&OID(MIB_snmpInASNParseErrs), appl_internal_snmp,
106 	    NULL);
107 	appl_internal_object(&OID(MIB_snmpInTooBigs), appl_internal_snmp, NULL);
108 	appl_internal_object(&OID(MIB_snmpInNoSuchNames), appl_internal_snmp,
109 	    NULL);
110 	appl_internal_object(&OID(MIB_snmpInBadValues), appl_internal_snmp,
111 	    NULL);
112 	appl_internal_object(&OID(MIB_snmpInReadOnlys), appl_internal_snmp,
113 	    NULL);
114 	appl_internal_object(&OID(MIB_snmpInReadOnlys), appl_internal_snmp,
115 	    NULL);
116 	appl_internal_object(&OID(MIB_snmpInGenErrs), appl_internal_snmp, NULL);
117 	appl_internal_object(&OID(MIB_snmpInTotalReqVars), appl_internal_snmp,
118 	    NULL);
119 	appl_internal_object(&OID(MIB_snmpInTotalSetVars), appl_internal_snmp,
120 	    NULL);
121 	appl_internal_object(&OID(MIB_snmpInGetRequests), appl_internal_snmp,
122 	    NULL);
123 	appl_internal_object(&OID(MIB_snmpInGetNexts), appl_internal_snmp,
124 	    NULL);
125 	appl_internal_object(&OID(MIB_snmpInSetRequests), appl_internal_snmp,
126 	    NULL);
127 	appl_internal_object(&OID(MIB_snmpInGetResponses), appl_internal_snmp,
128 	    NULL);
129 	appl_internal_object(&OID(MIB_snmpInTraps), appl_internal_snmp, NULL);
130 	appl_internal_object(&OID(MIB_snmpOutTooBigs), appl_internal_snmp,
131 	    NULL);
132 	appl_internal_object(&OID(MIB_snmpOutNoSuchNames), appl_internal_snmp,
133 	    NULL);
134 	appl_internal_object(&OID(MIB_snmpOutBadValues), appl_internal_snmp,
135 	    NULL);
136 	appl_internal_object(&OID(MIB_snmpOutGenErrs), appl_internal_snmp,
137 	    NULL);
138 	appl_internal_object(&OID(MIB_snmpOutGetRequests), appl_internal_snmp,
139 	    NULL);
140 	appl_internal_object(&OID(MIB_snmpOutGetNexts), appl_internal_snmp,
141 	    NULL);
142 	appl_internal_object(&OID(MIB_snmpOutSetRequests), appl_internal_snmp,
143 	    NULL);
144 	appl_internal_object(&OID(MIB_snmpOutGetResponses), appl_internal_snmp,
145 	    NULL);
146 	appl_internal_object(&OID(MIB_snmpOutTraps), appl_internal_snmp, NULL);
147 	appl_internal_object(&OID(MIB_snmpEnableAuthenTraps),
148 	    appl_internal_snmp, NULL);
149 	appl_internal_object(&OID(MIB_snmpSilentDrops), appl_internal_snmp,
150 	    NULL);
151 	appl_internal_object(&OID(MIB_snmpProxyDrops), appl_internal_snmp,
152 	    NULL);
153 
154 	appl_internal_region(&OID(MIB_snmpV2));
155 	appl_internal_object(&OID(MIB_snmpEngineID), appl_internal_engine,
156 	    NULL);
157 	appl_internal_object(&OID(MIB_snmpEngineBoots), appl_internal_engine,
158 	    NULL);
159 	appl_internal_object(&OID(MIB_snmpEngineTime), appl_internal_engine,
160 	    NULL);
161 	appl_internal_object(&OID(MIB_snmpEngineMaxMsgSize),
162 	    appl_internal_engine, NULL);
163 
164 	appl_internal_object(&OID(MIB_snmpUnavailableContexts),
165 	    appl_targetmib, NULL);
166 	appl_internal_object(&OID(MIB_snmpUnknownContexts),
167 	    appl_targetmib, NULL);
168 
169 	appl_internal_object(&OID(MIB_usmStatsUnsupportedSecLevels),
170 	    appl_internal_usmstats, NULL);
171 	appl_internal_object(&OID(MIB_usmStatsNotInTimeWindow),
172 	    appl_internal_usmstats, NULL);
173 	appl_internal_object(&OID(MIB_usmStatsUnknownUserNames),
174 	    appl_internal_usmstats, NULL);
175 	appl_internal_object(&OID(MIB_usmStatsUnknownEngineId),
176 	    appl_internal_usmstats, NULL);
177 	appl_internal_object(&OID(MIB_usmStatsWrongDigests),
178 	    appl_internal_usmstats, NULL);
179 	appl_internal_object(&OID(MIB_usmStatsDecryptionErrors),
180 	    appl_internal_usmstats, NULL);
181 }
182 
183 void
184 appl_internal_shutdown(void)
185 {
186 	struct appl_internal_object *object;
187 
188 	while ((object = RB_ROOT(&appl_internal_objects)) != NULL) {
189 		RB_REMOVE(appl_internal_objects, &appl_internal_objects,
190 		    object);
191 		free(object);
192 	}
193 
194 	appl_close(&appl_internal);
195 }
196 
197 void
198 appl_internal_region(struct ber_oid *oid)
199 {
200 	enum appl_error error;
201 	char oidbuf[1024];
202 
203 	error = appl_register(NULL, 150, 1, oid, 0, 1, 0, 0, &appl_internal);
204 	/*
205 	 * Ignore requestDenied, duplicateRegistration, and unsupportedContext
206 	 */
207 	if (error == APPL_ERROR_PROCESSINGERROR ||
208 	    error == APPL_ERROR_PARSEERROR) {
209 		smi_oid2string(oid, oidbuf, sizeof(oidbuf), 0);
210 		fatalx("internal: Failed to register %s", oidbuf);
211 	}
212 }
213 
214 void
215 appl_internal_object(struct ber_oid *oid,
216     struct ber_element *(*get)(struct ber_oid *),
217     struct ber_element *(*getnext)(int8_t, struct ber_oid *))
218 {
219 	struct appl_internal_object *obj;
220 
221 	if ((obj = calloc(1, sizeof(*obj))) == NULL)
222 		fatal(NULL);
223 	obj->oid = *oid;
224 	obj->get = get;
225 	obj->getnext = getnext;
226 
227 	RB_INSERT(appl_internal_objects, &appl_internal_objects, obj);
228 }
229 
230 void
231 appl_internal_get(struct appl_backend *backend, __unused int32_t transactionid,
232     int32_t requestid, __unused const char *ctx, struct appl_varbind *vblist)
233 {
234 	struct ber_oid oid;
235 	struct appl_internal_object *object;
236 	struct appl_varbind *vb, *resp;
237 	size_t i;
238 	int r;
239 
240 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++)
241 		continue;
242 
243 	if ((resp = calloc(i, sizeof(*resp))) == NULL) {
244 		log_warn("%s", backend->ab_name);
245 		appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist);
246 		return;
247 	}
248 
249 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++) {
250 		resp[i].av_oid = vb->av_oid;
251 		if ((object = appl_internal_object_parent(&vb->av_oid)) == NULL)
252 			resp[i].av_value =
253 			    appl_exception(APPL_EXC_NOSUCHOBJECT);
254 		else {
255 			oid = object->oid;
256 			/* Add 0 element for scalar */
257 			if (object->getnext == NULL)
258 				oid.bo_id[oid.bo_n++] = 0;
259 			r = ober_oid_cmp(&vb->av_oid, &oid);
260 			if ((r == 0 && object->getnext == NULL) ||
261 			    (r == 2 && object->getnext != NULL))
262 				resp[i].av_value = object->get(&resp[i].av_oid);
263 			else
264 				resp[i].av_value =
265 				    appl_exception(APPL_EXC_NOSUCHINSTANCE);
266 		}
267 		if (resp[i].av_value == NULL) {
268 			log_warnx("%s: Failed to get value", backend->ab_name);
269 			goto fail;
270 		}
271 		resp[i].av_next = &resp[i + 1];
272 	}
273 	resp[i - 1].av_next = NULL;
274 
275 	appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, resp);
276 	return;
277 
278  fail:
279 	for (vb = resp; vb != NULL; vb = vb->av_next)
280 		ober_free_elements(vb->av_value);
281 	free(resp);
282 	appl_response(backend, requestid, APPL_ERROR_GENERR, i + 1, vblist);
283 }
284 
285 void
286 appl_internal_getnext(struct appl_backend *backend,
287     __unused int32_t transactionid, int32_t requestid, __unused const char *ctx,
288     struct appl_varbind *vblist)
289 {
290 	struct ber_oid oid;
291 	struct appl_internal_object *object, search;
292 	struct appl_varbind *vb, *resp;
293 	size_t i;
294 	int r;
295 	int8_t include;
296 
297 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++)
298 		continue;
299 
300 	if ((resp = calloc(i, sizeof(*resp))) == NULL) {
301 		log_warn("%s", backend->ab_name);
302 		appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist);
303 		return;
304 	}
305 
306 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++) {
307 		resp[i].av_oid = vb->av_oid;
308 		object = appl_internal_object_parent(&vb->av_oid);
309 		if (object == NULL) {
310 			search.oid = vb->av_oid;
311 			object = RB_NFIND(appl_internal_objects,
312 			    &appl_internal_objects, &search);
313 		}
314 
315 		include = vb->av_include;
316 		for (; object != NULL; object = RB_NEXT(appl_internal_objects,
317 		    &appl_internal_objects, object), include = 1) {
318 			if (object->getnext == NULL) {
319 				oid = object->oid;
320 				oid.bo_id[oid.bo_n++] = 0;
321 				r = ober_oid_cmp(&resp[i].av_oid, &oid);
322 				if (r > 0 || (r == 0 && !include))
323 					continue;
324 				resp[i].av_oid = oid;
325 				resp[i].av_value = object->get(&oid);
326 				break;
327 			}
328 			/* non-scalar */
329 			if (ober_oid_cmp(&object->oid, &resp[i].av_oid) > 0) {
330 				include = 1;
331 				resp[i].av_oid = object->oid;
332 			}
333 
334 			resp[i].av_value =
335 			    object->getnext(include, &resp[i].av_oid);
336 			if (resp[i].av_value == NULL ||
337 			    resp[i].av_value->be_class != BER_CLASS_CONTEXT)
338 				break;
339 			/* endOfMibView */
340 			ober_free_elements(resp[i].av_value);
341 			resp[i].av_value = NULL;
342 		}
343 		if (ober_oid_cmp(&resp[i].av_oid, &vb->av_oid_end) >= 0 ||
344 		    object == NULL) {
345 			resp[i].av_oid = vb->av_oid;
346 			ober_free_elements(resp[i].av_value);
347 			resp[i].av_value =
348 			    appl_exception(APPL_EXC_ENDOFMIBVIEW);
349 		}
350 		if (resp[i].av_value == NULL) {
351 			log_warnx("%s: Failed to get value", backend->ab_name);
352 			goto fail;
353 		}
354 		resp[i].av_next = &resp[i + 1];
355 	}
356 	resp[i - 1].av_next = NULL;
357 
358 	appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, resp);
359 	return;
360 
361  fail:
362 	for (vb = resp; vb != NULL; vb = vb->av_next)
363 		ober_free_elements(vb->av_value);
364 	free(resp);
365 	appl_response(backend, requestid, APPL_ERROR_GENERR, i + 1, vblist);
366 }
367 
368 struct ber_element *
369 appl_internal_snmp(struct ber_oid *oid)
370 {
371 	struct snmp_stats *stats = &snmpd_env->sc_stats;
372 	struct ber_element *value = NULL;
373 
374 	if (ober_oid_cmp(oid, &OID(MIB_snmpEnableAuthenTraps, 0)) == 0)
375 		return ober_add_integer(NULL,
376 		    stats->snmp_enableauthentraps ? 1 : 2);
377 	if (ober_oid_cmp(&OID(MIB_snmpInPkts, 0), oid) == 0)
378 		value = ober_add_integer(NULL, stats->snmp_inpkts);
379 	else if (ober_oid_cmp(&OID(MIB_snmpOutPkts, 0), oid) == 0)
380 		value = ober_add_integer(NULL, stats->snmp_outpkts);
381 	else if (ober_oid_cmp(&OID(MIB_snmpInBadVersions, 0), oid) == 0)
382 		value = ober_add_integer(NULL, stats->snmp_inbadversions);
383 	else if (ober_oid_cmp(&OID(MIB_snmpInBadCommunityNames, 0), oid) == 0)
384 		value = ober_add_integer(NULL, stats->snmp_inbadcommunitynames);
385 	else if (ober_oid_cmp(&OID(MIB_snmpInBadCommunityUses, 0), oid) == 0)
386 		value = ober_add_integer(NULL, stats->snmp_inbadcommunityuses);
387 	else if (ober_oid_cmp(&OID(MIB_snmpInASNParseErrs, 0), oid) == 0)
388 		value = ober_add_integer(NULL, stats->snmp_inasnparseerrs);
389 	else if (ober_oid_cmp(&OID(MIB_snmpInTooBigs, 0), oid) == 0)
390 		value = ober_add_integer(NULL, stats->snmp_intoobigs);
391 	else if (ober_oid_cmp(&OID(MIB_snmpInNoSuchNames, 0), oid) == 0)
392 		value = ober_add_integer(NULL, stats->snmp_innosuchnames);
393 	else if (ober_oid_cmp(&OID(MIB_snmpInBadValues, 0), oid) == 0)
394 		value = ober_add_integer(NULL, stats->snmp_inbadvalues);
395 	else if (ober_oid_cmp(&OID(MIB_snmpInReadOnlys, 0), oid) == 0)
396 		value = ober_add_integer(NULL, stats->snmp_inreadonlys);
397 	else if (ober_oid_cmp(&OID(MIB_snmpInGenErrs, 0), oid) == 0)
398 		value = ober_add_integer(NULL, stats->snmp_ingenerrs);
399 	else if (ober_oid_cmp(&OID(MIB_snmpInTotalReqVars, 0), oid) == 0)
400 		value = ober_add_integer(NULL, stats->snmp_intotalreqvars);
401 	else if (ober_oid_cmp(&OID(MIB_snmpInTotalSetVars, 0), oid) == 0)
402 		value = ober_add_integer(NULL, stats->snmp_intotalsetvars);
403 	else if (ober_oid_cmp(&OID(MIB_snmpInGetRequests, 0), oid) == 0)
404 		value = ober_add_integer(NULL, stats->snmp_ingetrequests);
405 	else if (ober_oid_cmp(&OID(MIB_snmpInGetNexts, 0), oid) == 0)
406 		value = ober_add_integer(NULL, stats->snmp_ingetnexts);
407 	else if (ober_oid_cmp(&OID(MIB_snmpInSetRequests, 0), oid) == 0)
408 		value = ober_add_integer(NULL, stats->snmp_insetrequests);
409 	else if (ober_oid_cmp(&OID(MIB_snmpInGetResponses, 0), oid) == 0)
410 		value = ober_add_integer(NULL, stats->snmp_ingetresponses);
411 	else if (ober_oid_cmp(&OID(MIB_snmpInTraps, 0), oid) == 0)
412 		value = ober_add_integer(NULL, stats->snmp_intraps);
413 	else if (ober_oid_cmp(&OID(MIB_snmpOutTooBigs, 0), oid) == 0)
414 		value = ober_add_integer(NULL, stats->snmp_outtoobigs);
415 	else if (ober_oid_cmp(&OID(MIB_snmpOutNoSuchNames, 0), oid) == 0)
416 		value = ober_add_integer(NULL, stats->snmp_outnosuchnames);
417 	else if (ober_oid_cmp(&OID(MIB_snmpOutBadValues, 0), oid) == 0)
418 		value = ober_add_integer(NULL, stats->snmp_outbadvalues);
419 	else if (ober_oid_cmp(&OID(MIB_snmpOutGenErrs, 0), oid) == 0)
420 		value = ober_add_integer(NULL, stats->snmp_outgenerrs);
421 	else if (ober_oid_cmp(&OID(MIB_snmpOutGetRequests, 0), oid) == 0)
422 		value = ober_add_integer(NULL, stats->snmp_outgetrequests);
423 	else if (ober_oid_cmp(&OID(MIB_snmpOutGetNexts, 0), oid) == 0)
424 		value = ober_add_integer(NULL, stats->snmp_outgetnexts);
425 	else if (ober_oid_cmp(&OID(MIB_snmpOutSetRequests, 0), oid) == 0)
426 		value = ober_add_integer(NULL, stats->snmp_outsetrequests);
427 	else if (ober_oid_cmp(&OID(MIB_snmpOutGetResponses, 0), oid) == 0)
428 		value = ober_add_integer(NULL, stats->snmp_outgetresponses);
429 	else if (ober_oid_cmp(&OID(MIB_snmpOutTraps, 0), oid) == 0)
430 		value = ober_add_integer(NULL, stats->snmp_outtraps);
431 	else if (ober_oid_cmp(&OID(MIB_snmpSilentDrops, 0), oid) == 0)
432 		value = ober_add_integer(NULL, stats->snmp_silentdrops);
433 	else if (ober_oid_cmp(&OID(MIB_snmpProxyDrops, 0), oid) == 0)
434 		value = ober_add_integer(NULL, stats->snmp_proxydrops);
435 
436 	if (value != NULL)
437 		ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
438 	return value;
439 }
440 
441 struct ber_element *
442 appl_internal_engine(struct ber_oid *oid)
443 {
444 	if (ober_oid_cmp(&OID(MIB_snmpEngineID, 0), oid) == 0)
445 		return ober_add_nstring(NULL, snmpd_env->sc_engineid,
446 		    snmpd_env->sc_engineid_len);
447 	else if (ober_oid_cmp(&OID(MIB_snmpEngineBoots, 0), oid) == 0)
448 		return ober_add_integer(NULL, snmpd_env->sc_engine_boots);
449 	else if (ober_oid_cmp(&OID(MIB_snmpEngineTime, 0), oid) == 0)
450 		return ober_add_integer(NULL, snmpd_engine_time());
451 	else if (ober_oid_cmp(&OID(MIB_snmpEngineMaxMsgSize, 0), oid) == 0)
452 		return ober_add_integer(NULL, READ_BUF_SIZE);
453 	return NULL;
454 }
455 
456 struct ber_element *
457 appl_internal_usmstats(struct ber_oid *oid)
458 {
459 	struct snmp_stats *stats = &snmpd_env->sc_stats;
460 	struct ber_element *value = NULL;
461 
462 	if (ober_oid_cmp(&OID(MIB_usmStatsUnsupportedSecLevels, 0), oid) == 0)
463 		value = ober_add_integer(NULL, stats->snmp_usmbadseclevel);
464 	else if (ober_oid_cmp(&OID(MIB_usmStatsNotInTimeWindow, 0), oid) == 0)
465 		value = ober_add_integer(NULL, stats->snmp_usmtimewindow);
466 	else if (ober_oid_cmp(&OID(MIB_usmStatsUnknownUserNames, 0), oid) == 0)
467 		value = ober_add_integer(NULL, stats->snmp_usmnosuchuser);
468 	else if (ober_oid_cmp(&OID(MIB_usmStatsUnknownEngineId, 0), oid) == 0)
469 		value = ober_add_integer(NULL, stats->snmp_usmnosuchengine);
470 	else if (ober_oid_cmp(&OID(MIB_usmStatsWrongDigests, 0), oid) == 0)
471 		value = ober_add_integer(NULL, stats->snmp_usmwrongdigest);
472 	else if (ober_oid_cmp(&OID(MIB_usmStatsDecryptionErrors, 0), oid) == 0)
473 		value = ober_add_integer(NULL, stats->snmp_usmdecrypterr);
474 
475 	if (value != NULL)
476 		ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
477 
478 	return value;
479 }
480 
481 struct ber_element *
482 appl_internal_system(struct ber_oid *oid)
483 {
484 	struct snmp_system *s = &snmpd_env->sc_system;
485 	struct ber_element *value = NULL;
486 
487 	if (ober_oid_cmp(&OID(MIB_sysDescr, 0), oid) == 0)
488 		return ober_add_string(NULL, s->sys_descr);
489 	else if (ober_oid_cmp(&OID(MIB_sysOID, 0), oid) == 0)
490 		return ober_add_oid(NULL, &s->sys_oid);
491 	else if (ober_oid_cmp(&OID(MIB_sysUpTime, 0), oid) == 0) {
492 		value = ober_add_integer(NULL, smi_getticks());
493 		ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
494 	} else if (ober_oid_cmp(&OID(MIB_sysContact, 0), oid) == 0)
495 		return ober_add_string(NULL, s->sys_contact);
496 	else if (ober_oid_cmp(&OID(MIB_sysName, 0), oid) == 0)
497 		return ober_add_string(NULL, s->sys_name);
498 	else if (ober_oid_cmp(&OID(MIB_sysLocation, 0), oid) == 0)
499 		return ober_add_string(NULL, s->sys_location);
500 	else if (ober_oid_cmp(&OID(MIB_sysServices, 0), oid) == 0)
501 		return ober_add_integer(NULL, s->sys_services);
502 	return value;
503 }
504 
505 struct appl_internal_object *
506 appl_internal_object_parent(struct ber_oid *oid)
507 {
508 	struct appl_internal_object *object, search;
509 
510 	search.oid = *oid;
511 	do {
512 		if ((object = RB_FIND(appl_internal_objects,
513 		    &appl_internal_objects, &search)) != NULL)
514 			return object;
515 	} while (--search.oid.bo_n > 0);
516 
517 	return NULL;
518 }
519 
520 int
521 appl_internal_object_cmp(struct appl_internal_object *o1,
522     struct appl_internal_object *o2)
523 {
524 	return ober_oid_cmp(&o1->oid, &o2->oid);
525 }
526 
527 RB_GENERATE_STATIC(appl_internal_objects, appl_internal_object, entry,
528     appl_internal_object_cmp);
529