xref: /openbsd-src/usr.sbin/snmpd/application_internal.c (revision f0bcdb5c6239ddfcf095a4b7b5b5205416faadb1)
1 /*	$OpenBSD: application_internal.c,v 1.12 2024/02/06 12:44:27 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 #include <sys/types.h>
21 
22 #include <stddef.h>
23 
24 #include <ber.h>
25 #include <errno.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "application.h"
31 #include "log.h"
32 #include "mib.h"
33 #include "smi.h"
34 #include "snmp.h"
35 #include "snmpd.h"
36 
37 struct appl_internal_object {
38 	struct ber_oid			 oid;
39 	struct ber_element *		(*get)(struct ber_oid *);
40 	/* No getnext means the object is scalar */
41 	struct ber_element *		(*getnext)(int8_t, struct ber_oid *);
42 
43 	int32_t				 intval;
44 	char				*stringval;
45 
46 	RB_ENTRY(appl_internal_object)	 entry;
47 };
48 
49 void appl_internal_region(struct ber_oid *);
50 void appl_internal_object(struct ber_oid *,
51     struct ber_element *(*)(struct ber_oid *),
52     struct ber_element *(*)(int8_t, struct ber_oid *));
53 void appl_internal_get(struct appl_backend *, int32_t, int32_t, const char *,
54     struct appl_varbind *);
55 void appl_internal_getnext(struct appl_backend *, int32_t, int32_t,
56     const char *, struct appl_varbind *);
57 struct ber_element *appl_internal_snmp(struct ber_oid *);
58 struct ber_element *appl_internal_engine(struct ber_oid *);
59 struct ber_element *appl_internal_usmstats(struct ber_oid *);
60 struct ber_element *appl_internal_system(struct ber_oid *);
61 struct ber_element *appl_internal_get_int(struct ber_oid *);
62 struct ber_element *appl_internal_get_string(struct ber_oid *);
63 struct appl_internal_object *appl_internal_object_parent(struct ber_oid *);
64 int appl_internal_object_cmp(struct appl_internal_object *,
65     struct appl_internal_object *);
66 
67 struct appl_backend_functions appl_internal_functions = {
68 	.ab_get = appl_internal_get,
69 	.ab_getnext = appl_internal_getnext,
70 	.ab_getbulk = NULL, /* getbulk is too complex */
71 };
72 
73 struct appl_backend appl_internal = {
74 	.ab_name = "internal",
75 	.ab_cookie = NULL,
76 	.ab_retries = 0,
77 	.ab_range = 1,
78 	.ab_fn = &appl_internal_functions
79 };
80 
81 struct appl_backend appl_config = {
82 	.ab_name = "config",
83 	.ab_cookie = NULL,
84 	.ab_retries = 0,
85 	.ab_range = 1,
86 	.ab_fn = &appl_internal_functions
87 };
88 
89 static RB_HEAD(appl_internal_objects, appl_internal_object)
90     appl_internal_objects = RB_INITIALIZER(&appl_internal_objects),
91     appl_internal_objects_conf = RB_INITIALIZER(&appl_internal_objects_conf);
92 RB_PROTOTYPE_STATIC(appl_internal_objects, appl_internal_object, entry,
93     appl_internal_object_cmp);
94 
95 void
appl_internal_init(void)96 appl_internal_init(void)
97 {
98 	struct appl_internal_object *obj;
99 	struct ber_oid oid;
100 
101 	appl_internal_region(&OID(MIB_system));
102 	appl_internal_object(&OID(MIB_sysDescr), appl_internal_system, NULL);
103 	appl_internal_object(&OID(MIB_sysOID), appl_internal_system, NULL);
104 	appl_internal_object(&OID(MIB_sysUpTime), appl_internal_system, NULL);
105 	appl_internal_object(&OID(MIB_sysContact), appl_internal_system, NULL);
106 	appl_internal_object(&OID(MIB_sysName), appl_internal_system, NULL);
107 	appl_internal_object(&OID(MIB_sysLocation), appl_internal_system, NULL);
108 	appl_internal_object(&OID(MIB_sysServices), appl_internal_system, NULL);
109 	appl_internal_object(&OID(MIB_sysORLastChange), appl_sysorlastchange,
110 	    NULL);
111 
112 	appl_internal_object(&OID(MIB_sysORID), appl_sysortable,
113 	    appl_sysortable_getnext);
114 	appl_internal_object(&OID(MIB_sysORDescr), appl_sysortable,
115 	    appl_sysortable_getnext);
116 	appl_internal_object(&OID(MIB_sysORUpTime), appl_sysortable,
117 	    appl_sysortable_getnext);
118 
119 	appl_internal_region(&OID(MIB_snmp));
120 	appl_internal_object(&OID(MIB_snmpInPkts), appl_internal_snmp, NULL);
121 	appl_internal_object(&OID(MIB_snmpOutPkts), appl_internal_snmp, NULL);
122 	appl_internal_object(&OID(MIB_snmpInBadVersions), appl_internal_snmp,
123 	   NULL);
124 	appl_internal_object(&OID(MIB_snmpInBadCommunityNames),
125 	   appl_internal_snmp, NULL);
126 	appl_internal_object(&OID(MIB_snmpInBadCommunityUses),
127 	   appl_internal_snmp, NULL);
128 	appl_internal_object(&OID(MIB_snmpInASNParseErrs), appl_internal_snmp,
129 	    NULL);
130 	appl_internal_object(&OID(MIB_snmpInTooBigs), appl_internal_snmp, NULL);
131 	appl_internal_object(&OID(MIB_snmpInNoSuchNames), appl_internal_snmp,
132 	    NULL);
133 	appl_internal_object(&OID(MIB_snmpInBadValues), appl_internal_snmp,
134 	    NULL);
135 	appl_internal_object(&OID(MIB_snmpInReadOnlys), appl_internal_snmp,
136 	    NULL);
137 	appl_internal_object(&OID(MIB_snmpInGenErrs), appl_internal_snmp, NULL);
138 	appl_internal_object(&OID(MIB_snmpInTotalReqVars), appl_internal_snmp,
139 	    NULL);
140 	appl_internal_object(&OID(MIB_snmpInTotalSetVars), appl_internal_snmp,
141 	    NULL);
142 	appl_internal_object(&OID(MIB_snmpInGetRequests), appl_internal_snmp,
143 	    NULL);
144 	appl_internal_object(&OID(MIB_snmpInGetNexts), appl_internal_snmp,
145 	    NULL);
146 	appl_internal_object(&OID(MIB_snmpInSetRequests), appl_internal_snmp,
147 	    NULL);
148 	appl_internal_object(&OID(MIB_snmpInGetResponses), appl_internal_snmp,
149 	    NULL);
150 	appl_internal_object(&OID(MIB_snmpInTraps), appl_internal_snmp, NULL);
151 	appl_internal_object(&OID(MIB_snmpOutTooBigs), appl_internal_snmp,
152 	    NULL);
153 	appl_internal_object(&OID(MIB_snmpOutNoSuchNames), appl_internal_snmp,
154 	    NULL);
155 	appl_internal_object(&OID(MIB_snmpOutBadValues), appl_internal_snmp,
156 	    NULL);
157 	appl_internal_object(&OID(MIB_snmpOutGenErrs), appl_internal_snmp,
158 	    NULL);
159 	appl_internal_object(&OID(MIB_snmpOutGetRequests), appl_internal_snmp,
160 	    NULL);
161 	appl_internal_object(&OID(MIB_snmpOutGetNexts), appl_internal_snmp,
162 	    NULL);
163 	appl_internal_object(&OID(MIB_snmpOutSetRequests), appl_internal_snmp,
164 	    NULL);
165 	appl_internal_object(&OID(MIB_snmpOutGetResponses), appl_internal_snmp,
166 	    NULL);
167 	appl_internal_object(&OID(MIB_snmpOutTraps), appl_internal_snmp, NULL);
168 	appl_internal_object(&OID(MIB_snmpEnableAuthenTraps),
169 	    appl_internal_snmp, NULL);
170 	appl_internal_object(&OID(MIB_snmpSilentDrops), appl_internal_snmp,
171 	    NULL);
172 	appl_internal_object(&OID(MIB_snmpProxyDrops), appl_internal_snmp,
173 	    NULL);
174 
175 	appl_internal_region(&OID(MIB_snmpV2));
176 	appl_internal_object(&OID(MIB_snmpEngineID), appl_internal_engine,
177 	    NULL);
178 	appl_internal_object(&OID(MIB_snmpEngineBoots), appl_internal_engine,
179 	    NULL);
180 	appl_internal_object(&OID(MIB_snmpEngineTime), appl_internal_engine,
181 	    NULL);
182 	appl_internal_object(&OID(MIB_snmpEngineMaxMsgSize),
183 	    appl_internal_engine, NULL);
184 
185 	appl_internal_object(&OID(MIB_snmpUnavailableContexts),
186 	    appl_targetmib, NULL);
187 	appl_internal_object(&OID(MIB_snmpUnknownContexts),
188 	    appl_targetmib, NULL);
189 
190 	appl_internal_object(&OID(MIB_usmStatsUnsupportedSecLevels),
191 	    appl_internal_usmstats, NULL);
192 	appl_internal_object(&OID(MIB_usmStatsNotInTimeWindow),
193 	    appl_internal_usmstats, NULL);
194 	appl_internal_object(&OID(MIB_usmStatsUnknownUserNames),
195 	    appl_internal_usmstats, NULL);
196 	appl_internal_object(&OID(MIB_usmStatsUnknownEngineId),
197 	    appl_internal_usmstats, NULL);
198 	appl_internal_object(&OID(MIB_usmStatsWrongDigests),
199 	    appl_internal_usmstats, NULL);
200 	appl_internal_object(&OID(MIB_usmStatsDecryptionErrors),
201 	    appl_internal_usmstats, NULL);
202 
203 	while ((obj = RB_MIN(appl_internal_objects,
204 	    &appl_internal_objects_conf)) != NULL) {
205 		RB_REMOVE(appl_internal_objects,
206 		    &appl_internal_objects_conf, obj);
207 		oid = obj->oid;
208 		oid.bo_id[oid.bo_n++] = 0;
209 		if (appl_register(NULL, 150, 1, &oid,
210 		    1, 1, 0, 0, &appl_config) != APPL_ERROR_NOERROR) {
211 			free(obj->stringval);
212 			free(obj);
213 		} else
214 			RB_INSERT(appl_internal_objects, &appl_internal_objects,
215 			    obj);
216 	}
217 }
218 
219 void
appl_internal_shutdown(void)220 appl_internal_shutdown(void)
221 {
222 	struct appl_internal_object *object;
223 
224 	while ((object = RB_ROOT(&appl_internal_objects)) != NULL) {
225 		RB_REMOVE(appl_internal_objects, &appl_internal_objects,
226 		    object);
227 		free(object->stringval);
228 		free(object);
229 	}
230 
231 	appl_close(&appl_internal);
232 	appl_close(&appl_config);
233 }
234 
235 void
appl_internal_region(struct ber_oid * oid)236 appl_internal_region(struct ber_oid *oid)
237 {
238 	enum appl_error error;
239 	char oidbuf[1024];
240 
241 	error = appl_register(NULL, 150, 1, oid, 0, 1, 0, 0, &appl_internal);
242 	/*
243 	 * Ignore requestDenied, duplicateRegistration, and unsupportedContext
244 	 */
245 	if (error == APPL_ERROR_PROCESSINGERROR ||
246 	    error == APPL_ERROR_PARSEERROR)
247 		fatalx("internal: Failed to register %s", mib_oid2string(oid,
248 		    oidbuf, sizeof(oidbuf), snmpd_env->sc_oidfmt));
249 }
250 
251 void
appl_internal_object(struct ber_oid * oid,struct ber_element * (* get)(struct ber_oid *),struct ber_element * (* getnext)(int8_t,struct ber_oid *))252 appl_internal_object(struct ber_oid *oid,
253     struct ber_element *(*get)(struct ber_oid *),
254     struct ber_element *(*getnext)(int8_t, struct ber_oid *))
255 {
256 	struct appl_internal_object *obj;
257 	char buf[1024];
258 
259 	if ((obj = calloc(1, sizeof(*obj))) == NULL)
260 		fatal(NULL);
261 	obj->oid = *oid;
262 	obj->get = get;
263 	obj->getnext = getnext;
264 	obj->stringval = NULL;
265 
266 	if (RB_INSERT(appl_internal_objects,
267 	    &appl_internal_objects, obj) != NULL)
268 		fatalx("%s: %s already registered", __func__,
269 		    mib_oid2string(oid, buf, sizeof(buf),
270 		    snmpd_env->sc_oidfmt));
271 }
272 
273 const char *
appl_internal_object_int(struct ber_oid * oid,int32_t val)274 appl_internal_object_int(struct ber_oid *oid, int32_t val)
275 {
276 	struct appl_internal_object *obj;
277 
278 	if ((obj = calloc(1, sizeof(*obj))) == NULL)
279 		return strerror(errno);
280 	obj->oid = *oid;
281 	obj->get = appl_internal_get_int;
282 	obj->getnext = NULL;
283 	obj->intval = val;
284 	obj->stringval = NULL;
285 
286 	if (RB_INSERT(appl_internal_objects,
287 	    &appl_internal_objects_conf, obj) != NULL) {
288 		free(obj);
289 		return "OID already defined";
290 	}
291 	return NULL;
292 }
293 
294 const char *
appl_internal_object_string(struct ber_oid * oid,char * val)295 appl_internal_object_string(struct ber_oid *oid, char *val)
296 {
297 	struct appl_internal_object *obj;
298 
299 	if ((obj = calloc(1, sizeof(*obj))) == NULL)
300 		return strerror(errno);
301 	obj->oid = *oid;
302 	obj->get = appl_internal_get_string;
303 	obj->getnext = NULL;
304 	obj->stringval = val;
305 
306 	if (RB_INSERT(appl_internal_objects,
307 	    &appl_internal_objects_conf, obj) != NULL) {
308 		free(obj);
309 		return "OID already defined";
310 	}
311 	return NULL;
312 }
313 
314 void
appl_internal_get(struct appl_backend * backend,__unused int32_t transactionid,int32_t requestid,__unused const char * ctx,struct appl_varbind * vblist)315 appl_internal_get(struct appl_backend *backend, __unused int32_t transactionid,
316     int32_t requestid, __unused const char *ctx, struct appl_varbind *vblist)
317 {
318 	struct ber_oid oid;
319 	struct appl_internal_object *object;
320 	struct appl_varbind *vb, *resp;
321 	size_t i;
322 	int r;
323 
324 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++)
325 		continue;
326 
327 	if ((resp = calloc(i, sizeof(*resp))) == NULL) {
328 		log_warn("%s", backend->ab_name);
329 		appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist);
330 		return;
331 	}
332 
333 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++) {
334 		resp[i].av_oid = vb->av_oid;
335 		if ((object = appl_internal_object_parent(&vb->av_oid)) == NULL)
336 			resp[i].av_value =
337 			    appl_exception(APPL_EXC_NOSUCHOBJECT);
338 		else {
339 			oid = object->oid;
340 			/* Add 0 element for scalar */
341 			if (object->getnext == NULL)
342 				oid.bo_id[oid.bo_n++] = 0;
343 			r = ober_oid_cmp(&vb->av_oid, &oid);
344 			if ((r == 0 && object->getnext == NULL) ||
345 			    (r == 2 && object->getnext != NULL))
346 				resp[i].av_value = object->get(&resp[i].av_oid);
347 			else
348 				resp[i].av_value =
349 				    appl_exception(APPL_EXC_NOSUCHINSTANCE);
350 		}
351 		if (resp[i].av_value == NULL) {
352 			log_warnx("%s: Failed to get value", backend->ab_name);
353 			goto fail;
354 		}
355 		resp[i].av_next = &resp[i + 1];
356 	}
357 	resp[i - 1].av_next = NULL;
358 
359 	appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, resp);
360 
361 	free(resp);
362 	return;
363 
364  fail:
365 	for (vb = resp; vb != NULL; vb = vb->av_next)
366 		ober_free_elements(vb->av_value);
367 	free(resp);
368 	appl_response(backend, requestid, APPL_ERROR_GENERR, i + 1, vblist);
369 }
370 
371 void
appl_internal_getnext(struct appl_backend * backend,__unused int32_t transactionid,int32_t requestid,__unused const char * ctx,struct appl_varbind * vblist)372 appl_internal_getnext(struct appl_backend *backend,
373     __unused int32_t transactionid, int32_t requestid, __unused const char *ctx,
374     struct appl_varbind *vblist)
375 {
376 	struct ber_oid oid;
377 	struct appl_internal_object *object, search;
378 	struct appl_varbind *vb, *resp;
379 	size_t i;
380 	int r;
381 	int8_t include;
382 
383 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++)
384 		continue;
385 
386 	if ((resp = calloc(i, sizeof(*resp))) == NULL) {
387 		log_warn("%s", backend->ab_name);
388 		appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist);
389 		return;
390 	}
391 
392 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++) {
393 		resp[i].av_oid = vb->av_oid;
394 		object = appl_internal_object_parent(&vb->av_oid);
395 		if (object == NULL) {
396 			search.oid = vb->av_oid;
397 			object = RB_NFIND(appl_internal_objects,
398 			    &appl_internal_objects, &search);
399 		}
400 
401 		include = vb->av_include;
402 		for (; object != NULL; object = RB_NEXT(appl_internal_objects,
403 		    &appl_internal_objects, object), include = 1) {
404 			if (object->getnext == NULL) {
405 				oid = object->oid;
406 				oid.bo_id[oid.bo_n++] = 0;
407 				r = ober_oid_cmp(&resp[i].av_oid, &oid);
408 				if (r > 0 || (r == 0 && !include))
409 					continue;
410 				resp[i].av_oid = oid;
411 				resp[i].av_value = object->get(&oid);
412 				break;
413 			}
414 			/* non-scalar */
415 			if (ober_oid_cmp(&object->oid, &resp[i].av_oid) > 0) {
416 				include = 1;
417 				resp[i].av_oid = object->oid;
418 			}
419 
420 			resp[i].av_value =
421 			    object->getnext(include, &resp[i].av_oid);
422 			if (resp[i].av_value == NULL ||
423 			    resp[i].av_value->be_class != BER_CLASS_CONTEXT)
424 				break;
425 			/* endOfMibView */
426 			ober_free_elements(resp[i].av_value);
427 			resp[i].av_value = NULL;
428 		}
429 		if (ober_oid_cmp(&resp[i].av_oid, &vb->av_oid_end) >= 0 ||
430 		    object == NULL) {
431 			resp[i].av_oid = vb->av_oid;
432 			ober_free_elements(resp[i].av_value);
433 			resp[i].av_value =
434 			    appl_exception(APPL_EXC_ENDOFMIBVIEW);
435 		}
436 		if (resp[i].av_value == NULL) {
437 			log_warnx("%s: Failed to get value", backend->ab_name);
438 			goto fail;
439 		}
440 		resp[i].av_next = &resp[i + 1];
441 	}
442 	resp[i - 1].av_next = NULL;
443 
444 	appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, resp);
445 
446 	free(resp);
447 	return;
448 
449  fail:
450 	for (vb = resp; vb != NULL; vb = vb->av_next)
451 		ober_free_elements(vb->av_value);
452 	free(resp);
453 	appl_response(backend, requestid, APPL_ERROR_GENERR, i + 1, vblist);
454 }
455 
456 struct ber_element *
appl_internal_snmp(struct ber_oid * oid)457 appl_internal_snmp(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, &OID(MIB_snmpEnableAuthenTraps, 0)) == 0)
463 		return ober_add_integer(NULL,
464 		    stats->snmp_enableauthentraps ? 1 : 2);
465 	if (ober_oid_cmp(&OID(MIB_snmpInPkts, 0), oid) == 0)
466 		value = ober_add_integer(NULL, stats->snmp_inpkts);
467 	else if (ober_oid_cmp(&OID(MIB_snmpOutPkts, 0), oid) == 0)
468 		value = ober_add_integer(NULL, stats->snmp_outpkts);
469 	else if (ober_oid_cmp(&OID(MIB_snmpInBadVersions, 0), oid) == 0)
470 		value = ober_add_integer(NULL, stats->snmp_inbadversions);
471 	else if (ober_oid_cmp(&OID(MIB_snmpInBadCommunityNames, 0), oid) == 0)
472 		value = ober_add_integer(NULL, stats->snmp_inbadcommunitynames);
473 	else if (ober_oid_cmp(&OID(MIB_snmpInBadCommunityUses, 0), oid) == 0)
474 		value = ober_add_integer(NULL, stats->snmp_inbadcommunityuses);
475 	else if (ober_oid_cmp(&OID(MIB_snmpInASNParseErrs, 0), oid) == 0)
476 		value = ober_add_integer(NULL, stats->snmp_inasnparseerrs);
477 	else if (ober_oid_cmp(&OID(MIB_snmpInTooBigs, 0), oid) == 0)
478 		value = ober_add_integer(NULL, stats->snmp_intoobigs);
479 	else if (ober_oid_cmp(&OID(MIB_snmpInNoSuchNames, 0), oid) == 0)
480 		value = ober_add_integer(NULL, stats->snmp_innosuchnames);
481 	else if (ober_oid_cmp(&OID(MIB_snmpInBadValues, 0), oid) == 0)
482 		value = ober_add_integer(NULL, stats->snmp_inbadvalues);
483 	else if (ober_oid_cmp(&OID(MIB_snmpInReadOnlys, 0), oid) == 0)
484 		value = ober_add_integer(NULL, stats->snmp_inreadonlys);
485 	else if (ober_oid_cmp(&OID(MIB_snmpInGenErrs, 0), oid) == 0)
486 		value = ober_add_integer(NULL, stats->snmp_ingenerrs);
487 	else if (ober_oid_cmp(&OID(MIB_snmpInTotalReqVars, 0), oid) == 0)
488 		value = ober_add_integer(NULL, stats->snmp_intotalreqvars);
489 	else if (ober_oid_cmp(&OID(MIB_snmpInTotalSetVars, 0), oid) == 0)
490 		value = ober_add_integer(NULL, stats->snmp_intotalsetvars);
491 	else if (ober_oid_cmp(&OID(MIB_snmpInGetRequests, 0), oid) == 0)
492 		value = ober_add_integer(NULL, stats->snmp_ingetrequests);
493 	else if (ober_oid_cmp(&OID(MIB_snmpInGetNexts, 0), oid) == 0)
494 		value = ober_add_integer(NULL, stats->snmp_ingetnexts);
495 	else if (ober_oid_cmp(&OID(MIB_snmpInSetRequests, 0), oid) == 0)
496 		value = ober_add_integer(NULL, stats->snmp_insetrequests);
497 	else if (ober_oid_cmp(&OID(MIB_snmpInGetResponses, 0), oid) == 0)
498 		value = ober_add_integer(NULL, stats->snmp_ingetresponses);
499 	else if (ober_oid_cmp(&OID(MIB_snmpInTraps, 0), oid) == 0)
500 		value = ober_add_integer(NULL, stats->snmp_intraps);
501 	else if (ober_oid_cmp(&OID(MIB_snmpOutTooBigs, 0), oid) == 0)
502 		value = ober_add_integer(NULL, stats->snmp_outtoobigs);
503 	else if (ober_oid_cmp(&OID(MIB_snmpOutNoSuchNames, 0), oid) == 0)
504 		value = ober_add_integer(NULL, stats->snmp_outnosuchnames);
505 	else if (ober_oid_cmp(&OID(MIB_snmpOutBadValues, 0), oid) == 0)
506 		value = ober_add_integer(NULL, stats->snmp_outbadvalues);
507 	else if (ober_oid_cmp(&OID(MIB_snmpOutGenErrs, 0), oid) == 0)
508 		value = ober_add_integer(NULL, stats->snmp_outgenerrs);
509 	else if (ober_oid_cmp(&OID(MIB_snmpOutGetRequests, 0), oid) == 0)
510 		value = ober_add_integer(NULL, stats->snmp_outgetrequests);
511 	else if (ober_oid_cmp(&OID(MIB_snmpOutGetNexts, 0), oid) == 0)
512 		value = ober_add_integer(NULL, stats->snmp_outgetnexts);
513 	else if (ober_oid_cmp(&OID(MIB_snmpOutSetRequests, 0), oid) == 0)
514 		value = ober_add_integer(NULL, stats->snmp_outsetrequests);
515 	else if (ober_oid_cmp(&OID(MIB_snmpOutGetResponses, 0), oid) == 0)
516 		value = ober_add_integer(NULL, stats->snmp_outgetresponses);
517 	else if (ober_oid_cmp(&OID(MIB_snmpOutTraps, 0), oid) == 0)
518 		value = ober_add_integer(NULL, stats->snmp_outtraps);
519 	else if (ober_oid_cmp(&OID(MIB_snmpSilentDrops, 0), oid) == 0)
520 		value = ober_add_integer(NULL, stats->snmp_silentdrops);
521 	else if (ober_oid_cmp(&OID(MIB_snmpProxyDrops, 0), oid) == 0)
522 		value = ober_add_integer(NULL, stats->snmp_proxydrops);
523 
524 	if (value != NULL)
525 		ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
526 	return value;
527 }
528 
529 struct ber_element *
appl_internal_engine(struct ber_oid * oid)530 appl_internal_engine(struct ber_oid *oid)
531 {
532 	if (ober_oid_cmp(&OID(MIB_snmpEngineID, 0), oid) == 0)
533 		return ober_add_nstring(NULL, snmpd_env->sc_engineid,
534 		    snmpd_env->sc_engineid_len);
535 	else if (ober_oid_cmp(&OID(MIB_snmpEngineBoots, 0), oid) == 0)
536 		return ober_add_integer(NULL, snmpd_env->sc_engine_boots);
537 	else if (ober_oid_cmp(&OID(MIB_snmpEngineTime, 0), oid) == 0)
538 		return ober_add_integer(NULL, snmpd_engine_time());
539 	else if (ober_oid_cmp(&OID(MIB_snmpEngineMaxMsgSize, 0), oid) == 0)
540 		return ober_add_integer(NULL, READ_BUF_SIZE);
541 	return NULL;
542 }
543 
544 struct ber_element *
appl_internal_usmstats(struct ber_oid * oid)545 appl_internal_usmstats(struct ber_oid *oid)
546 {
547 	struct snmp_stats *stats = &snmpd_env->sc_stats;
548 	struct ber_element *value = NULL;
549 
550 	if (ober_oid_cmp(&OID(MIB_usmStatsUnsupportedSecLevels, 0), oid) == 0)
551 		value = ober_add_integer(NULL, stats->snmp_usmbadseclevel);
552 	else if (ober_oid_cmp(&OID(MIB_usmStatsNotInTimeWindow, 0), oid) == 0)
553 		value = ober_add_integer(NULL, stats->snmp_usmtimewindow);
554 	else if (ober_oid_cmp(&OID(MIB_usmStatsUnknownUserNames, 0), oid) == 0)
555 		value = ober_add_integer(NULL, stats->snmp_usmnosuchuser);
556 	else if (ober_oid_cmp(&OID(MIB_usmStatsUnknownEngineId, 0), oid) == 0)
557 		value = ober_add_integer(NULL, stats->snmp_usmnosuchengine);
558 	else if (ober_oid_cmp(&OID(MIB_usmStatsWrongDigests, 0), oid) == 0)
559 		value = ober_add_integer(NULL, stats->snmp_usmwrongdigest);
560 	else if (ober_oid_cmp(&OID(MIB_usmStatsDecryptionErrors, 0), oid) == 0)
561 		value = ober_add_integer(NULL, stats->snmp_usmdecrypterr);
562 
563 	if (value != NULL)
564 		ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
565 
566 	return value;
567 }
568 
569 struct ber_element *
appl_internal_system(struct ber_oid * oid)570 appl_internal_system(struct ber_oid *oid)
571 {
572 	struct snmp_system *s = &snmpd_env->sc_system;
573 	struct ber_element *value = NULL;
574 
575 	if (ober_oid_cmp(&OID(MIB_sysDescr, 0), oid) == 0)
576 		return ober_add_string(NULL, s->sys_descr);
577 	else if (ober_oid_cmp(&OID(MIB_sysOID, 0), oid) == 0)
578 		return ober_add_oid(NULL, &s->sys_oid);
579 	else if (ober_oid_cmp(&OID(MIB_sysUpTime, 0), oid) == 0) {
580 		value = ober_add_integer(NULL, smi_getticks());
581 		ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
582 	} else if (ober_oid_cmp(&OID(MIB_sysContact, 0), oid) == 0)
583 		return ober_add_string(NULL, s->sys_contact);
584 	else if (ober_oid_cmp(&OID(MIB_sysName, 0), oid) == 0)
585 		return ober_add_string(NULL, s->sys_name);
586 	else if (ober_oid_cmp(&OID(MIB_sysLocation, 0), oid) == 0)
587 		return ober_add_string(NULL, s->sys_location);
588 	else if (ober_oid_cmp(&OID(MIB_sysServices, 0), oid) == 0)
589 		return ober_add_integer(NULL, s->sys_services);
590 	return value;
591 }
592 
593 struct ber_element *
appl_internal_get_int(struct ber_oid * oid)594 appl_internal_get_int(struct ber_oid *oid)
595 {
596 	struct appl_internal_object *obj;
597 
598 	obj = appl_internal_object_parent(oid);
599 	return ober_add_integer(NULL, obj->intval);
600 }
601 
602 struct ber_element *
appl_internal_get_string(struct ber_oid * oid)603 appl_internal_get_string(struct ber_oid *oid)
604 {
605 	struct appl_internal_object *obj;
606 
607 	obj = appl_internal_object_parent(oid);
608 	return ober_add_string(NULL, obj->stringval);
609 }
610 
611 struct appl_internal_object *
appl_internal_object_parent(struct ber_oid * oid)612 appl_internal_object_parent(struct ber_oid *oid)
613 {
614 	struct appl_internal_object *object, search;
615 
616 	search.oid = *oid;
617 	do {
618 		if ((object = RB_FIND(appl_internal_objects,
619 		    &appl_internal_objects, &search)) != NULL)
620 			return object;
621 	} while (--search.oid.bo_n > 0);
622 
623 	return NULL;
624 }
625 
626 int
appl_internal_object_cmp(struct appl_internal_object * o1,struct appl_internal_object * o2)627 appl_internal_object_cmp(struct appl_internal_object *o1,
628     struct appl_internal_object *o2)
629 {
630 	return ober_oid_cmp(&o1->oid, &o2->oid);
631 }
632 
633 RB_GENERATE_STATIC(appl_internal_objects, appl_internal_object, entry,
634     appl_internal_object_cmp);
635