/* $OpenBSD: mib.c,v 1.105 2022/10/06 14:41:08 martijn Exp $ */ /* * Copyright (c) 2012 Joel Knight * Copyright (c) 2007, 2008, 2012 Reyk Floeter * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "snmpd.h" #include "mib.h" /* * Defined in SNMPv2-MIB.txt (RFC 3418) */ int mib_getsys(struct oid *, struct ber_oid *, struct ber_element **); int mib_getsnmp(struct oid *, struct ber_oid *, struct ber_element **); int mib_sysor(struct oid *, struct ber_oid *, struct ber_element **); int mib_setsnmp(struct oid *, struct ber_oid *, struct ber_element **); static struct oid mib_tree[] = MIB_TREE; /* base MIB tree */ static struct oid base_mib[] = { { MIB(mib_2), OID_MIB }, { MIB(sysDescr), OID_RD, mib_getsys }, { MIB(sysOID), OID_RD, mib_getsys }, { MIB(sysUpTime), OID_RD, mib_getsys }, { MIB(sysContact), OID_RD, mib_getsys }, { MIB(sysName), OID_RD, mib_getsys }, { MIB(sysLocation), OID_RD, mib_getsys }, { MIB(sysServices), OID_RS, mib_getsys }, { MIB(sysORLastChange), OID_RD, mps_getts }, { MIB(sysORIndex), OID_TRD, mib_sysor }, { MIB(sysORID), OID_TRD, mib_sysor }, { MIB(sysORDescr), OID_TRD, mib_sysor }, { MIB(sysORUpTime), OID_TRD, mib_sysor }, { MIB(snmp), OID_MIB }, { MIB(snmpInPkts), OID_RD, mib_getsnmp }, { MIB(snmpOutPkts), OID_RD, mib_getsnmp }, { MIB(snmpInBadVersions), OID_RD, mib_getsnmp }, { MIB(snmpInBadCommunityNames), OID_RD, mib_getsnmp }, { MIB(snmpInBadCommunityUses), OID_RD, mib_getsnmp }, { MIB(snmpInASNParseErrs), OID_RD, mib_getsnmp }, { MIB(snmpInTooBigs), OID_RD, mib_getsnmp }, { MIB(snmpInNoSuchNames), OID_RD, mib_getsnmp }, { MIB(snmpInBadValues), OID_RD, mib_getsnmp }, { MIB(snmpInReadOnlys), OID_RD, mib_getsnmp }, { MIB(snmpInGenErrs), OID_RD, mib_getsnmp }, { MIB(snmpInTotalReqVars), OID_RD, mib_getsnmp }, { MIB(snmpInTotalSetVars), OID_RD, mib_getsnmp }, { MIB(snmpInGetRequests), OID_RD, mib_getsnmp }, { MIB(snmpInGetNexts), OID_RD, mib_getsnmp }, { MIB(snmpInSetRequests), OID_RD, mib_getsnmp }, { MIB(snmpInGetResponses), OID_RD, mib_getsnmp }, { MIB(snmpInTraps), OID_RD, mib_getsnmp }, { MIB(snmpOutTooBigs), OID_RD, mib_getsnmp }, { MIB(snmpOutNoSuchNames), OID_RD, mib_getsnmp }, { MIB(snmpOutBadValues), OID_RD, mib_getsnmp }, { MIB(snmpOutGenErrs), OID_RD, mib_getsnmp }, { MIB(snmpOutGetRequests), OID_RD, mib_getsnmp }, { MIB(snmpOutGetNexts), OID_RD, mib_getsnmp }, { MIB(snmpOutSetRequests), OID_RD, mib_getsnmp }, { MIB(snmpOutGetResponses), OID_RD, mib_getsnmp }, { MIB(snmpOutTraps), OID_RD, mib_getsnmp }, { MIB(snmpEnableAuthenTraps), OID_RD, mib_getsnmp }, { MIB(snmpSilentDrops), OID_RD, mib_getsnmp }, { MIB(snmpProxyDrops), OID_RD, mib_getsnmp }, { MIBEND } }; int mib_getsys(struct oid *oid, struct ber_oid *o, struct ber_element **elm) { struct ber_oid sysoid = OID(MIB_SYSOID_DEFAULT); char *s = oid->o_data; struct ber_oid *so = oid->o_data; struct utsname u; long long ticks; if (uname(&u) == -1) return (-1); switch (oid->o_oid[OIDIDX_system]) { case 1: if (s == NULL) { if (asprintf(&s, "%s %s %s %s %s", u.sysname, u.nodename, u.release, u.version, u.machine) == -1) return (-1); oid->o_data = s; oid->o_val = strlen(s); } *elm = ober_add_string(*elm, s); break; case 2: if (so == NULL) so = &sysoid; smi_oidlen(so); *elm = ober_add_oid(*elm, so); break; case 3: ticks = smi_getticks(); *elm = ober_add_integer(*elm, ticks); ober_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS); break; case 4: if (s == NULL) { if (asprintf(&s, "root@%s", u.nodename) == -1) return (-1); oid->o_data = s; oid->o_val = strlen(s); } *elm = ober_add_string(*elm, s); break; case 5: if (s == NULL) { if ((s = strdup(u.nodename)) == NULL) return (-1); oid->o_data = s; oid->o_val = strlen(s); } *elm = ober_add_string(*elm, s); break; case 6: if (s == NULL) s = ""; *elm = ober_add_string(*elm, s); break; case 7: *elm = ober_add_integer(*elm, oid->o_val); break; default: return (-1); } return (0); } int mib_sysor(struct oid *oid, struct ber_oid *o, struct ber_element **elm) { struct ber_element *ber = *elm; u_int32_t idx = 1, nmib = 0; struct oid *next, *miboid; char buf[SNMPD_MAXSTRLEN]; /* Count MIB root OIDs in the tree */ for (next = NULL; (next = smi_foreach(next, OID_MIB)) != NULL; nmib++); /* Get and verify the current row index */ idx = o->bo_id[OIDIDX_sysOREntry]; if (idx > nmib) return (1); /* Find the MIB root element for this Id */ for (next = miboid = NULL, nmib = 1; (next = smi_foreach(next, OID_MIB)) != NULL; nmib++) { if (nmib == idx) miboid = next; } if (miboid == NULL) return (-1); /* Tables need to prepend the OID on their own */ ber = ober_add_oid(ber, o); switch (o->bo_id[OIDIDX_sysOR]) { case 1: ber = ober_add_integer(ber, idx); break; case 2: ber = ober_add_oid(ber, &miboid->o_id); break; case 3: /* * This should be a description of the MIB. * But we use the symbolic OID string for now, it may * help to display names of internal OIDs. */ smi_oid2string(&miboid->o_id, buf, sizeof(buf), 0); ber = ober_add_string(ber, buf); break; case 4: /* * We do not support dynamic loading of MIB at runtime, * the sysORUpTime value of 0 will indicate "loaded at * startup". */ ber = ober_add_integer(ber, 0); ober_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS); break; default: return (-1); } return (0); } int mib_getsnmp(struct oid *oid, struct ber_oid *o, struct ber_element **elm) { struct snmp_stats *stats = &snmpd_env->sc_stats; long long i; struct statsmap { u_int8_t m_id; u_int32_t *m_ptr; } mapping[] = { { 1, &stats->snmp_inpkts }, { 2, &stats->snmp_outpkts }, { 3, &stats->snmp_inbadversions }, { 4, &stats->snmp_inbadcommunitynames }, { 5, &stats->snmp_inbadcommunityuses }, { 6, &stats->snmp_inasnparseerrs }, { 8, &stats->snmp_intoobigs }, { 9, &stats->snmp_innosuchnames }, { 10, &stats->snmp_inbadvalues }, { 11, &stats->snmp_inreadonlys }, { 12, &stats->snmp_ingenerrs }, { 13, &stats->snmp_intotalreqvars }, { 14, &stats->snmp_intotalsetvars }, { 15, &stats->snmp_ingetrequests }, { 16, &stats->snmp_ingetnexts }, { 17, &stats->snmp_insetrequests }, { 18, &stats->snmp_ingetresponses }, { 19, &stats->snmp_intraps }, { 20, &stats->snmp_outtoobigs }, { 21, &stats->snmp_outnosuchnames }, { 22, &stats->snmp_outbadvalues }, { 24, &stats->snmp_outgenerrs }, { 25, &stats->snmp_outgetrequests }, { 26, &stats->snmp_outgetnexts }, { 27, &stats->snmp_outsetrequests }, { 28, &stats->snmp_outgetresponses }, { 29, &stats->snmp_outtraps }, { 31, &stats->snmp_silentdrops }, { 32, &stats->snmp_proxydrops } }; switch (oid->o_oid[OIDIDX_snmp]) { case 30: i = stats->snmp_enableauthentraps == 1 ? 1 : 2; *elm = ober_add_integer(*elm, i); break; default: for (i = 0; (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) { if (oid->o_oid[OIDIDX_snmp] == mapping[i].m_id) { *elm = ober_add_integer(*elm, *mapping[i].m_ptr); ober_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_COUNTER32); return (0); } } return (-1); } return (0); } int mib_setsnmp(struct oid *oid, struct ber_oid *o, struct ber_element **elm) { struct snmp_stats *stats = &snmpd_env->sc_stats; long long i; if (ober_get_integer(*elm, &i) == -1) return (-1); stats->snmp_enableauthentraps = i == 1 ? 1 : 0; return (0); } /* * Defined in SNMP-USER-BASED-SM-MIB.txt (RFC 3414) */ int mib_engine(struct oid *, struct ber_oid *, struct ber_element **); int mib_usmstats(struct oid *, struct ber_oid *, struct ber_element **); static struct oid usm_mib[] = { { MIB(snmpEngine), OID_MIB }, { MIB(snmpEngineID), OID_RD, mib_engine }, { MIB(snmpEngineBoots), OID_RD, mib_engine }, { MIB(snmpEngineTime), OID_RD, mib_engine }, { MIB(snmpEngineMaxMsgSize), OID_RD, mib_engine }, { MIB(usmStats), OID_MIB }, { MIB(usmStatsUnsupportedSecLevels), OID_RD, mib_usmstats }, { MIB(usmStatsNotInTimeWindow), OID_RD, mib_usmstats }, { MIB(usmStatsUnknownUserNames), OID_RD, mib_usmstats }, { MIB(usmStatsUnknownEngineId), OID_RD, mib_usmstats }, { MIB(usmStatsWrongDigests), OID_RD, mib_usmstats }, { MIB(usmStatsDecryptionErrors), OID_RD, mib_usmstats }, { MIBEND } }; int mib_engine(struct oid *oid, struct ber_oid *o, struct ber_element **elm) { switch (oid->o_oid[OIDIDX_snmpEngine]) { case 1: *elm = ober_add_nstring(*elm, snmpd_env->sc_engineid, snmpd_env->sc_engineid_len); break; case 2: *elm = ober_add_integer(*elm, snmpd_env->sc_engine_boots); break; case 3: *elm = ober_add_integer(*elm, snmpd_engine_time()); break; case 4: *elm = ober_add_integer(*elm, READ_BUF_SIZE); break; default: return -1; } return 0; } int mib_usmstats(struct oid *oid, struct ber_oid *o, struct ber_element **elm) { struct snmp_stats *stats = &snmpd_env->sc_stats; long long i; struct statsmap { u_int8_t m_id; u_int32_t *m_ptr; } mapping[] = { { OIDVAL_usmErrSecLevel, &stats->snmp_usmbadseclevel }, { OIDVAL_usmErrTimeWindow, &stats->snmp_usmtimewindow }, { OIDVAL_usmErrUserName, &stats->snmp_usmnosuchuser }, { OIDVAL_usmErrEngineId, &stats->snmp_usmnosuchengine }, { OIDVAL_usmErrDigest, &stats->snmp_usmwrongdigest }, { OIDVAL_usmErrDecrypt, &stats->snmp_usmdecrypterr }, }; for (i = 0; (u_int)i < (sizeof(mapping) / sizeof(mapping[0])); i++) { if (oid->o_oid[OIDIDX_usmStats] == mapping[i].m_id) { *elm = ober_add_integer(*elm, *mapping[i].m_ptr); ober_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_COUNTER32); return (0); } } return (-1); } /* * Import all MIBs */ void mib_init(void) { /* * MIB declarations (to register the OID names) */ smi_mibtree(mib_tree); /* * MIB definitions (the implementation) */ /* SNMPv2-MIB */ smi_mibtree(base_mib); /* SNMP-USER-BASED-SM-MIB */ smi_mibtree(usm_mib); }