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