xref: /openbsd-src/usr.sbin/snmpd/application_internal.c (revision f0bcdb5c6239ddfcf095a4b7b5b5205416faadb1)
1*f0bcdb5cSmartijn /*	$OpenBSD: application_internal.c,v 1.12 2024/02/06 12:44:27 martijn Exp $	*/
216365c53Smartijn 
316365c53Smartijn /*
416365c53Smartijn  * Copyright (c) 2023 Martijn van Duren <martijn@openbsd.org>
516365c53Smartijn  *
616365c53Smartijn  * Permission to use, copy, modify, and distribute this software for any
716365c53Smartijn  * purpose with or without fee is hereby granted, provided that the above
816365c53Smartijn  * copyright notice and this permission notice appear in all copies.
916365c53Smartijn  *
1016365c53Smartijn  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1116365c53Smartijn  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1216365c53Smartijn  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1316365c53Smartijn  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1416365c53Smartijn  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1516365c53Smartijn  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1616365c53Smartijn  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1716365c53Smartijn  */
1816365c53Smartijn 
1916365c53Smartijn #include <sys/tree.h>
20a9292d2aSmartijn #include <sys/types.h>
2116365c53Smartijn 
22a9292d2aSmartijn #include <stddef.h>
23a9292d2aSmartijn 
24a9292d2aSmartijn #include <ber.h>
259352f69fSmartijn #include <errno.h>
26a9292d2aSmartijn #include <stdint.h>
2716365c53Smartijn #include <stdlib.h>
289352f69fSmartijn #include <string.h>
2916365c53Smartijn 
3016365c53Smartijn #include "application.h"
3116365c53Smartijn #include "log.h"
3216365c53Smartijn #include "mib.h"
3316365c53Smartijn #include "smi.h"
34a9292d2aSmartijn #include "snmp.h"
3516365c53Smartijn #include "snmpd.h"
3616365c53Smartijn 
3716365c53Smartijn struct appl_internal_object {
3816365c53Smartijn 	struct ber_oid			 oid;
3916365c53Smartijn 	struct ber_element *		(*get)(struct ber_oid *);
4016365c53Smartijn 	/* No getnext means the object is scalar */
4116365c53Smartijn 	struct ber_element *		(*getnext)(int8_t, struct ber_oid *);
4216365c53Smartijn 
439352f69fSmartijn 	int32_t				 intval;
449352f69fSmartijn 	char				*stringval;
459352f69fSmartijn 
4616365c53Smartijn 	RB_ENTRY(appl_internal_object)	 entry;
4716365c53Smartijn };
4816365c53Smartijn 
4916365c53Smartijn void appl_internal_region(struct ber_oid *);
5016365c53Smartijn void appl_internal_object(struct ber_oid *,
5116365c53Smartijn     struct ber_element *(*)(struct ber_oid *),
5216365c53Smartijn     struct ber_element *(*)(int8_t, struct ber_oid *));
5316365c53Smartijn void appl_internal_get(struct appl_backend *, int32_t, int32_t, const char *,
5416365c53Smartijn     struct appl_varbind *);
5516365c53Smartijn void appl_internal_getnext(struct appl_backend *, int32_t, int32_t,
5616365c53Smartijn     const char *, struct appl_varbind *);
5783c0bf83Smartijn struct ber_element *appl_internal_snmp(struct ber_oid *);
589b677935Smartijn struct ber_element *appl_internal_engine(struct ber_oid *);
599b677935Smartijn struct ber_element *appl_internal_usmstats(struct ber_oid *);
6060cc2743Smartijn struct ber_element *appl_internal_system(struct ber_oid *);
619352f69fSmartijn struct ber_element *appl_internal_get_int(struct ber_oid *);
629352f69fSmartijn struct ber_element *appl_internal_get_string(struct ber_oid *);
6316365c53Smartijn struct appl_internal_object *appl_internal_object_parent(struct ber_oid *);
6416365c53Smartijn int appl_internal_object_cmp(struct appl_internal_object *,
6516365c53Smartijn     struct appl_internal_object *);
6616365c53Smartijn 
6716365c53Smartijn struct appl_backend_functions appl_internal_functions = {
6816365c53Smartijn 	.ab_get = appl_internal_get,
6916365c53Smartijn 	.ab_getnext = appl_internal_getnext,
7016365c53Smartijn 	.ab_getbulk = NULL, /* getbulk is too complex */
7116365c53Smartijn };
7216365c53Smartijn 
7316365c53Smartijn struct appl_backend appl_internal = {
7416365c53Smartijn 	.ab_name = "internal",
7516365c53Smartijn 	.ab_cookie = NULL,
7616365c53Smartijn 	.ab_retries = 0,
7716365c53Smartijn 	.ab_range = 1,
7816365c53Smartijn 	.ab_fn = &appl_internal_functions
7916365c53Smartijn };
8016365c53Smartijn 
819352f69fSmartijn struct appl_backend appl_config = {
829352f69fSmartijn 	.ab_name = "config",
839352f69fSmartijn 	.ab_cookie = NULL,
849352f69fSmartijn 	.ab_retries = 0,
859352f69fSmartijn 	.ab_range = 1,
869352f69fSmartijn 	.ab_fn = &appl_internal_functions
879352f69fSmartijn };
889352f69fSmartijn 
8916365c53Smartijn static RB_HEAD(appl_internal_objects, appl_internal_object)
909352f69fSmartijn     appl_internal_objects = RB_INITIALIZER(&appl_internal_objects),
919352f69fSmartijn     appl_internal_objects_conf = RB_INITIALIZER(&appl_internal_objects_conf);
9216365c53Smartijn RB_PROTOTYPE_STATIC(appl_internal_objects, appl_internal_object, entry,
9316365c53Smartijn     appl_internal_object_cmp);
9416365c53Smartijn 
9516365c53Smartijn void
appl_internal_init(void)9616365c53Smartijn appl_internal_init(void)
9716365c53Smartijn {
989352f69fSmartijn 	struct appl_internal_object *obj;
999352f69fSmartijn 	struct ber_oid oid;
1009352f69fSmartijn 
10160cc2743Smartijn 	appl_internal_region(&OID(MIB_system));
10260cc2743Smartijn 	appl_internal_object(&OID(MIB_sysDescr), appl_internal_system, NULL);
10360cc2743Smartijn 	appl_internal_object(&OID(MIB_sysOID), appl_internal_system, NULL);
10460cc2743Smartijn 	appl_internal_object(&OID(MIB_sysUpTime), appl_internal_system, NULL);
10560cc2743Smartijn 	appl_internal_object(&OID(MIB_sysContact), appl_internal_system, NULL);
10660cc2743Smartijn 	appl_internal_object(&OID(MIB_sysName), appl_internal_system, NULL);
10760cc2743Smartijn 	appl_internal_object(&OID(MIB_sysLocation), appl_internal_system, NULL);
10860cc2743Smartijn 	appl_internal_object(&OID(MIB_sysServices), appl_internal_system, NULL);
109215fd4bcSmartijn 	appl_internal_object(&OID(MIB_sysORLastChange), appl_sysorlastchange,
110215fd4bcSmartijn 	    NULL);
111215fd4bcSmartijn 
112215fd4bcSmartijn 	appl_internal_object(&OID(MIB_sysORID), appl_sysortable,
113215fd4bcSmartijn 	    appl_sysortable_getnext);
114215fd4bcSmartijn 	appl_internal_object(&OID(MIB_sysORDescr), appl_sysortable,
115215fd4bcSmartijn 	    appl_sysortable_getnext);
116215fd4bcSmartijn 	appl_internal_object(&OID(MIB_sysORUpTime), appl_sysortable,
117215fd4bcSmartijn 	    appl_sysortable_getnext);
11860cc2743Smartijn 
11983c0bf83Smartijn 	appl_internal_region(&OID(MIB_snmp));
12083c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInPkts), appl_internal_snmp, NULL);
12183c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutPkts), appl_internal_snmp, NULL);
12283c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInBadVersions), appl_internal_snmp,
12383c0bf83Smartijn 	   NULL);
12483c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInBadCommunityNames),
12583c0bf83Smartijn 	   appl_internal_snmp, NULL);
12683c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInBadCommunityUses),
12783c0bf83Smartijn 	   appl_internal_snmp, NULL);
12883c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInASNParseErrs), appl_internal_snmp,
12983c0bf83Smartijn 	    NULL);
13083c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInTooBigs), appl_internal_snmp, NULL);
13183c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInNoSuchNames), appl_internal_snmp,
13283c0bf83Smartijn 	    NULL);
13383c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInBadValues), appl_internal_snmp,
13483c0bf83Smartijn 	    NULL);
13583c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInReadOnlys), appl_internal_snmp,
13683c0bf83Smartijn 	    NULL);
13783c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInGenErrs), appl_internal_snmp, NULL);
13883c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInTotalReqVars), appl_internal_snmp,
13983c0bf83Smartijn 	    NULL);
14083c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInTotalSetVars), appl_internal_snmp,
14183c0bf83Smartijn 	    NULL);
14283c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInGetRequests), appl_internal_snmp,
14383c0bf83Smartijn 	    NULL);
14483c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInGetNexts), appl_internal_snmp,
14583c0bf83Smartijn 	    NULL);
14683c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInSetRequests), appl_internal_snmp,
14783c0bf83Smartijn 	    NULL);
14883c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInGetResponses), appl_internal_snmp,
14983c0bf83Smartijn 	    NULL);
15083c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpInTraps), appl_internal_snmp, NULL);
15183c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutTooBigs), appl_internal_snmp,
15283c0bf83Smartijn 	    NULL);
15383c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutNoSuchNames), appl_internal_snmp,
15483c0bf83Smartijn 	    NULL);
15583c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutBadValues), appl_internal_snmp,
15683c0bf83Smartijn 	    NULL);
15783c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutGenErrs), appl_internal_snmp,
15883c0bf83Smartijn 	    NULL);
15983c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutGetRequests), appl_internal_snmp,
16083c0bf83Smartijn 	    NULL);
16183c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutGetNexts), appl_internal_snmp,
16283c0bf83Smartijn 	    NULL);
16383c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutSetRequests), appl_internal_snmp,
16483c0bf83Smartijn 	    NULL);
16583c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutGetResponses), appl_internal_snmp,
16683c0bf83Smartijn 	    NULL);
16783c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpOutTraps), appl_internal_snmp, NULL);
16883c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpEnableAuthenTraps),
16983c0bf83Smartijn 	    appl_internal_snmp, NULL);
17083c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpSilentDrops), appl_internal_snmp,
17183c0bf83Smartijn 	    NULL);
17283c0bf83Smartijn 	appl_internal_object(&OID(MIB_snmpProxyDrops), appl_internal_snmp,
17383c0bf83Smartijn 	    NULL);
1749b677935Smartijn 
1759b677935Smartijn 	appl_internal_region(&OID(MIB_snmpV2));
1769b677935Smartijn 	appl_internal_object(&OID(MIB_snmpEngineID), appl_internal_engine,
1779b677935Smartijn 	    NULL);
1789b677935Smartijn 	appl_internal_object(&OID(MIB_snmpEngineBoots), appl_internal_engine,
1799b677935Smartijn 	    NULL);
1809b677935Smartijn 	appl_internal_object(&OID(MIB_snmpEngineTime), appl_internal_engine,
1819b677935Smartijn 	    NULL);
1829b677935Smartijn 	appl_internal_object(&OID(MIB_snmpEngineMaxMsgSize),
1839b677935Smartijn 	    appl_internal_engine, NULL);
1849b677935Smartijn 
18592d4cb1dSmartijn 	appl_internal_object(&OID(MIB_snmpUnavailableContexts),
18692d4cb1dSmartijn 	    appl_targetmib, NULL);
18792d4cb1dSmartijn 	appl_internal_object(&OID(MIB_snmpUnknownContexts),
18892d4cb1dSmartijn 	    appl_targetmib, NULL);
18992d4cb1dSmartijn 
1909b677935Smartijn 	appl_internal_object(&OID(MIB_usmStatsUnsupportedSecLevels),
1919b677935Smartijn 	    appl_internal_usmstats, NULL);
1929b677935Smartijn 	appl_internal_object(&OID(MIB_usmStatsNotInTimeWindow),
1939b677935Smartijn 	    appl_internal_usmstats, NULL);
1949b677935Smartijn 	appl_internal_object(&OID(MIB_usmStatsUnknownUserNames),
1959b677935Smartijn 	    appl_internal_usmstats, NULL);
1969b677935Smartijn 	appl_internal_object(&OID(MIB_usmStatsUnknownEngineId),
1979b677935Smartijn 	    appl_internal_usmstats, NULL);
1989b677935Smartijn 	appl_internal_object(&OID(MIB_usmStatsWrongDigests),
1999b677935Smartijn 	    appl_internal_usmstats, NULL);
2009b677935Smartijn 	appl_internal_object(&OID(MIB_usmStatsDecryptionErrors),
2019b677935Smartijn 	    appl_internal_usmstats, NULL);
2029352f69fSmartijn 
2039352f69fSmartijn 	while ((obj = RB_MIN(appl_internal_objects,
2049352f69fSmartijn 	    &appl_internal_objects_conf)) != NULL) {
2059352f69fSmartijn 		RB_REMOVE(appl_internal_objects,
2069352f69fSmartijn 		    &appl_internal_objects_conf, obj);
2079352f69fSmartijn 		oid = obj->oid;
2089352f69fSmartijn 		oid.bo_id[oid.bo_n++] = 0;
2099352f69fSmartijn 		if (appl_register(NULL, 150, 1, &oid,
2109352f69fSmartijn 		    1, 1, 0, 0, &appl_config) != APPL_ERROR_NOERROR) {
2119352f69fSmartijn 			free(obj->stringval);
2129352f69fSmartijn 			free(obj);
2139352f69fSmartijn 		} else
2149352f69fSmartijn 			RB_INSERT(appl_internal_objects, &appl_internal_objects,
2159352f69fSmartijn 			    obj);
2169352f69fSmartijn 	}
21716365c53Smartijn }
21816365c53Smartijn 
21916365c53Smartijn void
appl_internal_shutdown(void)22016365c53Smartijn appl_internal_shutdown(void)
22116365c53Smartijn {
22216365c53Smartijn 	struct appl_internal_object *object;
22316365c53Smartijn 
22416365c53Smartijn 	while ((object = RB_ROOT(&appl_internal_objects)) != NULL) {
22516365c53Smartijn 		RB_REMOVE(appl_internal_objects, &appl_internal_objects,
22616365c53Smartijn 		    object);
227aea9a53aSmartijn 		free(object->stringval);
22816365c53Smartijn 		free(object);
22916365c53Smartijn 	}
23016365c53Smartijn 
23116365c53Smartijn 	appl_close(&appl_internal);
232aea9a53aSmartijn 	appl_close(&appl_config);
23316365c53Smartijn }
23416365c53Smartijn 
23516365c53Smartijn void
appl_internal_region(struct ber_oid * oid)23616365c53Smartijn appl_internal_region(struct ber_oid *oid)
23716365c53Smartijn {
23816365c53Smartijn 	enum appl_error error;
23916365c53Smartijn 	char oidbuf[1024];
24016365c53Smartijn 
24116365c53Smartijn 	error = appl_register(NULL, 150, 1, oid, 0, 1, 0, 0, &appl_internal);
24216365c53Smartijn 	/*
24316365c53Smartijn 	 * Ignore requestDenied, duplicateRegistration, and unsupportedContext
24416365c53Smartijn 	 */
24516365c53Smartijn 	if (error == APPL_ERROR_PROCESSINGERROR ||
246*f0bcdb5cSmartijn 	    error == APPL_ERROR_PARSEERROR)
247*f0bcdb5cSmartijn 		fatalx("internal: Failed to register %s", mib_oid2string(oid,
248*f0bcdb5cSmartijn 		    oidbuf, sizeof(oidbuf), snmpd_env->sc_oidfmt));
24916365c53Smartijn }
25016365c53Smartijn 
25116365c53Smartijn void
appl_internal_object(struct ber_oid * oid,struct ber_element * (* get)(struct ber_oid *),struct ber_element * (* getnext)(int8_t,struct ber_oid *))25216365c53Smartijn appl_internal_object(struct ber_oid *oid,
25316365c53Smartijn     struct ber_element *(*get)(struct ber_oid *),
25416365c53Smartijn     struct ber_element *(*getnext)(int8_t, struct ber_oid *))
25516365c53Smartijn {
25616365c53Smartijn 	struct appl_internal_object *obj;
257063971ddSmartijn 	char buf[1024];
25816365c53Smartijn 
25916365c53Smartijn 	if ((obj = calloc(1, sizeof(*obj))) == NULL)
26016365c53Smartijn 		fatal(NULL);
26116365c53Smartijn 	obj->oid = *oid;
26216365c53Smartijn 	obj->get = get;
26316365c53Smartijn 	obj->getnext = getnext;
264aea9a53aSmartijn 	obj->stringval = NULL;
26516365c53Smartijn 
266063971ddSmartijn 	if (RB_INSERT(appl_internal_objects,
267063971ddSmartijn 	    &appl_internal_objects, obj) != NULL)
268063971ddSmartijn 		fatalx("%s: %s already registered", __func__,
269*f0bcdb5cSmartijn 		    mib_oid2string(oid, buf, sizeof(buf),
270*f0bcdb5cSmartijn 		    snmpd_env->sc_oidfmt));
27116365c53Smartijn }
27216365c53Smartijn 
2739352f69fSmartijn const char *
appl_internal_object_int(struct ber_oid * oid,int32_t val)2749352f69fSmartijn appl_internal_object_int(struct ber_oid *oid, int32_t val)
2759352f69fSmartijn {
2769352f69fSmartijn 	struct appl_internal_object *obj;
2779352f69fSmartijn 
2789352f69fSmartijn 	if ((obj = calloc(1, sizeof(*obj))) == NULL)
2799352f69fSmartijn 		return strerror(errno);
2809352f69fSmartijn 	obj->oid = *oid;
2819352f69fSmartijn 	obj->get = appl_internal_get_int;
2829352f69fSmartijn 	obj->getnext = NULL;
2839352f69fSmartijn 	obj->intval = val;
2849352f69fSmartijn 	obj->stringval = NULL;
2859352f69fSmartijn 
2869352f69fSmartijn 	if (RB_INSERT(appl_internal_objects,
2879352f69fSmartijn 	    &appl_internal_objects_conf, obj) != NULL) {
2889352f69fSmartijn 		free(obj);
2899352f69fSmartijn 		return "OID already defined";
2909352f69fSmartijn 	}
2919352f69fSmartijn 	return NULL;
2929352f69fSmartijn }
2939352f69fSmartijn 
2949352f69fSmartijn const char *
appl_internal_object_string(struct ber_oid * oid,char * val)2959352f69fSmartijn appl_internal_object_string(struct ber_oid *oid, char *val)
2969352f69fSmartijn {
2979352f69fSmartijn 	struct appl_internal_object *obj;
2989352f69fSmartijn 
2999352f69fSmartijn 	if ((obj = calloc(1, sizeof(*obj))) == NULL)
3009352f69fSmartijn 		return strerror(errno);
3019352f69fSmartijn 	obj->oid = *oid;
3029352f69fSmartijn 	obj->get = appl_internal_get_string;
3039352f69fSmartijn 	obj->getnext = NULL;
3049352f69fSmartijn 	obj->stringval = val;
3059352f69fSmartijn 
3069352f69fSmartijn 	if (RB_INSERT(appl_internal_objects,
3079352f69fSmartijn 	    &appl_internal_objects_conf, obj) != NULL) {
3089352f69fSmartijn 		free(obj);
3099352f69fSmartijn 		return "OID already defined";
3109352f69fSmartijn 	}
3119352f69fSmartijn 	return NULL;
3129352f69fSmartijn }
3139352f69fSmartijn 
31416365c53Smartijn void
appl_internal_get(struct appl_backend * backend,__unused int32_t transactionid,int32_t requestid,__unused const char * ctx,struct appl_varbind * vblist)31516365c53Smartijn appl_internal_get(struct appl_backend *backend, __unused int32_t transactionid,
31616365c53Smartijn     int32_t requestid, __unused const char *ctx, struct appl_varbind *vblist)
31716365c53Smartijn {
31816365c53Smartijn 	struct ber_oid oid;
31916365c53Smartijn 	struct appl_internal_object *object;
32016365c53Smartijn 	struct appl_varbind *vb, *resp;
32116365c53Smartijn 	size_t i;
32216365c53Smartijn 	int r;
32316365c53Smartijn 
32416365c53Smartijn 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++)
32516365c53Smartijn 		continue;
32616365c53Smartijn 
32716365c53Smartijn 	if ((resp = calloc(i, sizeof(*resp))) == NULL) {
32816365c53Smartijn 		log_warn("%s", backend->ab_name);
32916365c53Smartijn 		appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist);
33016365c53Smartijn 		return;
33116365c53Smartijn 	}
33216365c53Smartijn 
33316365c53Smartijn 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++) {
33416365c53Smartijn 		resp[i].av_oid = vb->av_oid;
33516365c53Smartijn 		if ((object = appl_internal_object_parent(&vb->av_oid)) == NULL)
33616365c53Smartijn 			resp[i].av_value =
33716365c53Smartijn 			    appl_exception(APPL_EXC_NOSUCHOBJECT);
33816365c53Smartijn 		else {
33916365c53Smartijn 			oid = object->oid;
34016365c53Smartijn 			/* Add 0 element for scalar */
34116365c53Smartijn 			if (object->getnext == NULL)
34216365c53Smartijn 				oid.bo_id[oid.bo_n++] = 0;
34316365c53Smartijn 			r = ober_oid_cmp(&vb->av_oid, &oid);
34416365c53Smartijn 			if ((r == 0 && object->getnext == NULL) ||
34516365c53Smartijn 			    (r == 2 && object->getnext != NULL))
34616365c53Smartijn 				resp[i].av_value = object->get(&resp[i].av_oid);
34716365c53Smartijn 			else
34816365c53Smartijn 				resp[i].av_value =
34916365c53Smartijn 				    appl_exception(APPL_EXC_NOSUCHINSTANCE);
35016365c53Smartijn 		}
35116365c53Smartijn 		if (resp[i].av_value == NULL) {
35216365c53Smartijn 			log_warnx("%s: Failed to get value", backend->ab_name);
35316365c53Smartijn 			goto fail;
35416365c53Smartijn 		}
35516365c53Smartijn 		resp[i].av_next = &resp[i + 1];
35616365c53Smartijn 	}
35716365c53Smartijn 	resp[i - 1].av_next = NULL;
35816365c53Smartijn 
35916365c53Smartijn 	appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, resp);
360063971ddSmartijn 
361063971ddSmartijn 	free(resp);
36216365c53Smartijn 	return;
36316365c53Smartijn 
36416365c53Smartijn  fail:
36516365c53Smartijn 	for (vb = resp; vb != NULL; vb = vb->av_next)
36616365c53Smartijn 		ober_free_elements(vb->av_value);
36716365c53Smartijn 	free(resp);
36816365c53Smartijn 	appl_response(backend, requestid, APPL_ERROR_GENERR, i + 1, vblist);
36916365c53Smartijn }
37016365c53Smartijn 
37116365c53Smartijn void
appl_internal_getnext(struct appl_backend * backend,__unused int32_t transactionid,int32_t requestid,__unused const char * ctx,struct appl_varbind * vblist)37216365c53Smartijn appl_internal_getnext(struct appl_backend *backend,
37316365c53Smartijn     __unused int32_t transactionid, int32_t requestid, __unused const char *ctx,
37416365c53Smartijn     struct appl_varbind *vblist)
37516365c53Smartijn {
37616365c53Smartijn 	struct ber_oid oid;
37716365c53Smartijn 	struct appl_internal_object *object, search;
37816365c53Smartijn 	struct appl_varbind *vb, *resp;
37916365c53Smartijn 	size_t i;
38016365c53Smartijn 	int r;
38116365c53Smartijn 	int8_t include;
38216365c53Smartijn 
38316365c53Smartijn 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++)
38416365c53Smartijn 		continue;
38516365c53Smartijn 
38616365c53Smartijn 	if ((resp = calloc(i, sizeof(*resp))) == NULL) {
38716365c53Smartijn 		log_warn("%s", backend->ab_name);
38816365c53Smartijn 		appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist);
38916365c53Smartijn 		return;
39016365c53Smartijn 	}
39116365c53Smartijn 
39216365c53Smartijn 	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next, i++) {
39316365c53Smartijn 		resp[i].av_oid = vb->av_oid;
39416365c53Smartijn 		object = appl_internal_object_parent(&vb->av_oid);
39516365c53Smartijn 		if (object == NULL) {
39616365c53Smartijn 			search.oid = vb->av_oid;
39716365c53Smartijn 			object = RB_NFIND(appl_internal_objects,
39816365c53Smartijn 			    &appl_internal_objects, &search);
39916365c53Smartijn 		}
40016365c53Smartijn 
40116365c53Smartijn 		include = vb->av_include;
40216365c53Smartijn 		for (; object != NULL; object = RB_NEXT(appl_internal_objects,
40316365c53Smartijn 		    &appl_internal_objects, object), include = 1) {
40416365c53Smartijn 			if (object->getnext == NULL) {
40516365c53Smartijn 				oid = object->oid;
40616365c53Smartijn 				oid.bo_id[oid.bo_n++] = 0;
40716365c53Smartijn 				r = ober_oid_cmp(&resp[i].av_oid, &oid);
40816365c53Smartijn 				if (r > 0 || (r == 0 && !include))
40916365c53Smartijn 					continue;
41016365c53Smartijn 				resp[i].av_oid = oid;
41116365c53Smartijn 				resp[i].av_value = object->get(&oid);
41216365c53Smartijn 				break;
41316365c53Smartijn 			}
41416365c53Smartijn 			/* non-scalar */
4155818b8e3Smartijn 			if (ober_oid_cmp(&object->oid, &resp[i].av_oid) > 0) {
4165818b8e3Smartijn 				include = 1;
4175818b8e3Smartijn 				resp[i].av_oid = object->oid;
4185818b8e3Smartijn 			}
4195818b8e3Smartijn 
4205818b8e3Smartijn 			resp[i].av_value =
4215818b8e3Smartijn 			    object->getnext(include, &resp[i].av_oid);
4225818b8e3Smartijn 			if (resp[i].av_value == NULL ||
4235818b8e3Smartijn 			    resp[i].av_value->be_class != BER_CLASS_CONTEXT)
4245818b8e3Smartijn 				break;
4255818b8e3Smartijn 			/* endOfMibView */
4265818b8e3Smartijn 			ober_free_elements(resp[i].av_value);
4275818b8e3Smartijn 			resp[i].av_value = NULL;
42816365c53Smartijn 		}
42916365c53Smartijn 		if (ober_oid_cmp(&resp[i].av_oid, &vb->av_oid_end) >= 0 ||
43016365c53Smartijn 		    object == NULL) {
43116365c53Smartijn 			resp[i].av_oid = vb->av_oid;
43216365c53Smartijn 			ober_free_elements(resp[i].av_value);
43316365c53Smartijn 			resp[i].av_value =
43416365c53Smartijn 			    appl_exception(APPL_EXC_ENDOFMIBVIEW);
43516365c53Smartijn 		}
43616365c53Smartijn 		if (resp[i].av_value == NULL) {
43716365c53Smartijn 			log_warnx("%s: Failed to get value", backend->ab_name);
43816365c53Smartijn 			goto fail;
43916365c53Smartijn 		}
44016365c53Smartijn 		resp[i].av_next = &resp[i + 1];
44116365c53Smartijn 	}
44216365c53Smartijn 	resp[i - 1].av_next = NULL;
44316365c53Smartijn 
44416365c53Smartijn 	appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, resp);
445063971ddSmartijn 
446063971ddSmartijn 	free(resp);
44716365c53Smartijn 	return;
44816365c53Smartijn 
44916365c53Smartijn  fail:
45016365c53Smartijn 	for (vb = resp; vb != NULL; vb = vb->av_next)
45116365c53Smartijn 		ober_free_elements(vb->av_value);
45216365c53Smartijn 	free(resp);
45316365c53Smartijn 	appl_response(backend, requestid, APPL_ERROR_GENERR, i + 1, vblist);
45416365c53Smartijn }
45516365c53Smartijn 
45683c0bf83Smartijn struct ber_element *
appl_internal_snmp(struct ber_oid * oid)45783c0bf83Smartijn appl_internal_snmp(struct ber_oid *oid)
45883c0bf83Smartijn {
45983c0bf83Smartijn 	struct snmp_stats *stats = &snmpd_env->sc_stats;
46083c0bf83Smartijn 	struct ber_element *value = NULL;
46183c0bf83Smartijn 
46283c0bf83Smartijn 	if (ober_oid_cmp(oid, &OID(MIB_snmpEnableAuthenTraps, 0)) == 0)
46383c0bf83Smartijn 		return ober_add_integer(NULL,
46483c0bf83Smartijn 		    stats->snmp_enableauthentraps ? 1 : 2);
46583c0bf83Smartijn 	if (ober_oid_cmp(&OID(MIB_snmpInPkts, 0), oid) == 0)
46683c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_inpkts);
46783c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutPkts, 0), oid) == 0)
46883c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outpkts);
46983c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInBadVersions, 0), oid) == 0)
47083c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_inbadversions);
47183c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInBadCommunityNames, 0), oid) == 0)
47283c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_inbadcommunitynames);
47383c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInBadCommunityUses, 0), oid) == 0)
47483c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_inbadcommunityuses);
47583c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInASNParseErrs, 0), oid) == 0)
47683c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_inasnparseerrs);
47783c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInTooBigs, 0), oid) == 0)
47883c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_intoobigs);
47983c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInNoSuchNames, 0), oid) == 0)
48083c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_innosuchnames);
48183c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInBadValues, 0), oid) == 0)
48283c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_inbadvalues);
48383c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInReadOnlys, 0), oid) == 0)
48483c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_inreadonlys);
48583c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInGenErrs, 0), oid) == 0)
48683c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_ingenerrs);
48783c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInTotalReqVars, 0), oid) == 0)
48883c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_intotalreqvars);
48983c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInTotalSetVars, 0), oid) == 0)
49083c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_intotalsetvars);
49183c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInGetRequests, 0), oid) == 0)
49283c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_ingetrequests);
49383c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInGetNexts, 0), oid) == 0)
49483c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_ingetnexts);
49583c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInSetRequests, 0), oid) == 0)
49683c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_insetrequests);
49783c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInGetResponses, 0), oid) == 0)
49883c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_ingetresponses);
49983c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpInTraps, 0), oid) == 0)
50083c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_intraps);
50183c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutTooBigs, 0), oid) == 0)
50283c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outtoobigs);
50383c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutNoSuchNames, 0), oid) == 0)
50483c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outnosuchnames);
50583c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutBadValues, 0), oid) == 0)
50683c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outbadvalues);
50783c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutGenErrs, 0), oid) == 0)
50883c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outgenerrs);
50983c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutGetRequests, 0), oid) == 0)
51083c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outgetrequests);
51183c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutGetNexts, 0), oid) == 0)
51283c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outgetnexts);
51383c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutSetRequests, 0), oid) == 0)
51483c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outsetrequests);
51583c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutGetResponses, 0), oid) == 0)
51683c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outgetresponses);
51783c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpOutTraps, 0), oid) == 0)
51883c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_outtraps);
51983c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpSilentDrops, 0), oid) == 0)
52083c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_silentdrops);
52183c0bf83Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpProxyDrops, 0), oid) == 0)
52283c0bf83Smartijn 		value = ober_add_integer(NULL, stats->snmp_proxydrops);
52383c0bf83Smartijn 
52483c0bf83Smartijn 	if (value != NULL)
52583c0bf83Smartijn 		ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
52683c0bf83Smartijn 	return value;
52783c0bf83Smartijn }
52883c0bf83Smartijn 
5299b677935Smartijn struct ber_element *
appl_internal_engine(struct ber_oid * oid)5309b677935Smartijn appl_internal_engine(struct ber_oid *oid)
5319b677935Smartijn {
5329b677935Smartijn 	if (ober_oid_cmp(&OID(MIB_snmpEngineID, 0), oid) == 0)
5339b677935Smartijn 		return ober_add_nstring(NULL, snmpd_env->sc_engineid,
5349b677935Smartijn 		    snmpd_env->sc_engineid_len);
5359b677935Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpEngineBoots, 0), oid) == 0)
5369b677935Smartijn 		return ober_add_integer(NULL, snmpd_env->sc_engine_boots);
5379b677935Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpEngineTime, 0), oid) == 0)
5389b677935Smartijn 		return ober_add_integer(NULL, snmpd_engine_time());
5399b677935Smartijn 	else if (ober_oid_cmp(&OID(MIB_snmpEngineMaxMsgSize, 0), oid) == 0)
5409b677935Smartijn 		return ober_add_integer(NULL, READ_BUF_SIZE);
5419b677935Smartijn 	return NULL;
5429b677935Smartijn }
5439b677935Smartijn 
5449b677935Smartijn struct ber_element *
appl_internal_usmstats(struct ber_oid * oid)5459b677935Smartijn appl_internal_usmstats(struct ber_oid *oid)
5469b677935Smartijn {
5479b677935Smartijn 	struct snmp_stats *stats = &snmpd_env->sc_stats;
5489b677935Smartijn 	struct ber_element *value = NULL;
5499b677935Smartijn 
5509b677935Smartijn 	if (ober_oid_cmp(&OID(MIB_usmStatsUnsupportedSecLevels, 0), oid) == 0)
5519b677935Smartijn 		value = ober_add_integer(NULL, stats->snmp_usmbadseclevel);
5529b677935Smartijn 	else if (ober_oid_cmp(&OID(MIB_usmStatsNotInTimeWindow, 0), oid) == 0)
5539b677935Smartijn 		value = ober_add_integer(NULL, stats->snmp_usmtimewindow);
5549b677935Smartijn 	else if (ober_oid_cmp(&OID(MIB_usmStatsUnknownUserNames, 0), oid) == 0)
5559b677935Smartijn 		value = ober_add_integer(NULL, stats->snmp_usmnosuchuser);
5569b677935Smartijn 	else if (ober_oid_cmp(&OID(MIB_usmStatsUnknownEngineId, 0), oid) == 0)
5579b677935Smartijn 		value = ober_add_integer(NULL, stats->snmp_usmnosuchengine);
5589b677935Smartijn 	else if (ober_oid_cmp(&OID(MIB_usmStatsWrongDigests, 0), oid) == 0)
5599b677935Smartijn 		value = ober_add_integer(NULL, stats->snmp_usmwrongdigest);
5609b677935Smartijn 	else if (ober_oid_cmp(&OID(MIB_usmStatsDecryptionErrors, 0), oid) == 0)
5619b677935Smartijn 		value = ober_add_integer(NULL, stats->snmp_usmdecrypterr);
5629b677935Smartijn 
5639b677935Smartijn 	if (value != NULL)
5649b677935Smartijn 		ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_COUNTER32);
5659b677935Smartijn 
5669b677935Smartijn 	return value;
5679b677935Smartijn }
5689b677935Smartijn 
56960cc2743Smartijn struct ber_element *
appl_internal_system(struct ber_oid * oid)57060cc2743Smartijn appl_internal_system(struct ber_oid *oid)
57160cc2743Smartijn {
57260cc2743Smartijn 	struct snmp_system *s = &snmpd_env->sc_system;
57360cc2743Smartijn 	struct ber_element *value = NULL;
57460cc2743Smartijn 
57560cc2743Smartijn 	if (ober_oid_cmp(&OID(MIB_sysDescr, 0), oid) == 0)
57660cc2743Smartijn 		return ober_add_string(NULL, s->sys_descr);
57760cc2743Smartijn 	else if (ober_oid_cmp(&OID(MIB_sysOID, 0), oid) == 0)
57860cc2743Smartijn 		return ober_add_oid(NULL, &s->sys_oid);
57960cc2743Smartijn 	else if (ober_oid_cmp(&OID(MIB_sysUpTime, 0), oid) == 0) {
58060cc2743Smartijn 		value = ober_add_integer(NULL, smi_getticks());
58160cc2743Smartijn 		ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS);
58260cc2743Smartijn 	} else if (ober_oid_cmp(&OID(MIB_sysContact, 0), oid) == 0)
58360cc2743Smartijn 		return ober_add_string(NULL, s->sys_contact);
58460cc2743Smartijn 	else if (ober_oid_cmp(&OID(MIB_sysName, 0), oid) == 0)
58560cc2743Smartijn 		return ober_add_string(NULL, s->sys_name);
58660cc2743Smartijn 	else if (ober_oid_cmp(&OID(MIB_sysLocation, 0), oid) == 0)
58760cc2743Smartijn 		return ober_add_string(NULL, s->sys_location);
58860cc2743Smartijn 	else if (ober_oid_cmp(&OID(MIB_sysServices, 0), oid) == 0)
58960cc2743Smartijn 		return ober_add_integer(NULL, s->sys_services);
59060cc2743Smartijn 	return value;
59160cc2743Smartijn }
59260cc2743Smartijn 
5939352f69fSmartijn struct ber_element *
appl_internal_get_int(struct ber_oid * oid)5949352f69fSmartijn appl_internal_get_int(struct ber_oid *oid)
5959352f69fSmartijn {
5969352f69fSmartijn 	struct appl_internal_object *obj;
5979352f69fSmartijn 
5989352f69fSmartijn 	obj = appl_internal_object_parent(oid);
5999352f69fSmartijn 	return ober_add_integer(NULL, obj->intval);
6009352f69fSmartijn }
6019352f69fSmartijn 
6029352f69fSmartijn struct ber_element *
appl_internal_get_string(struct ber_oid * oid)6039352f69fSmartijn appl_internal_get_string(struct ber_oid *oid)
6049352f69fSmartijn {
6059352f69fSmartijn 	struct appl_internal_object *obj;
6069352f69fSmartijn 
6079352f69fSmartijn 	obj = appl_internal_object_parent(oid);
6089352f69fSmartijn 	return ober_add_string(NULL, obj->stringval);
6099352f69fSmartijn }
6109352f69fSmartijn 
61116365c53Smartijn struct appl_internal_object *
appl_internal_object_parent(struct ber_oid * oid)61216365c53Smartijn appl_internal_object_parent(struct ber_oid *oid)
61316365c53Smartijn {
61416365c53Smartijn 	struct appl_internal_object *object, search;
61516365c53Smartijn 
61616365c53Smartijn 	search.oid = *oid;
61716365c53Smartijn 	do {
61816365c53Smartijn 		if ((object = RB_FIND(appl_internal_objects,
61916365c53Smartijn 		    &appl_internal_objects, &search)) != NULL)
62016365c53Smartijn 			return object;
62116365c53Smartijn 	} while (--search.oid.bo_n > 0);
62216365c53Smartijn 
62316365c53Smartijn 	return NULL;
62416365c53Smartijn }
62516365c53Smartijn 
62616365c53Smartijn int
appl_internal_object_cmp(struct appl_internal_object * o1,struct appl_internal_object * o2)62716365c53Smartijn appl_internal_object_cmp(struct appl_internal_object *o1,
62816365c53Smartijn     struct appl_internal_object *o2)
62916365c53Smartijn {
63016365c53Smartijn 	return ober_oid_cmp(&o1->oid, &o2->oid);
63116365c53Smartijn }
63216365c53Smartijn 
63316365c53Smartijn RB_GENERATE_STATIC(appl_internal_objects, appl_internal_object, entry,
63416365c53Smartijn     appl_internal_object_cmp);
635