This one is a little more involved than the previous 2. Since the snmpd.conf's system variables are stored inside a 'struct oid', I want to move these into their own struct inside 'struct snmpd'.
If we also move mib_tree to smi.c we can completely remove mib.c As stated in my previous mail, this removes the sysORTable. I'll add these back later in a proper way. (mib.c removal omitted from diff) With these the only consumer of mps.c left is the oid keyword of snmpd.conf. OK? martijn@ diff --git a/Makefile b/Makefile index 3522a38..98bdda5 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ MAN= snmpd.8 snmpd.conf.5 SRCS= parse.y log.c snmpe.c application.c application_legacy.c \ application_blocklist.c application_internal.c \ application_agentx.c ax.c \ - mps.c trap.c mib.c smi.c snmpd.c \ + mps.c trap.c smi.c snmpd.c \ proc.c usm.c traphandler.c util.c LDADD= -levent -lutil -lcrypto diff --git a/application_internal.c b/application_internal.c index 36ab8ef..e682cc7 100644 --- a/application_internal.c +++ b/application_internal.c @@ -47,6 +47,7 @@ void appl_internal_getnext(struct appl_backend *, int32_t, int32_t, struct ber_element *appl_internal_snmp(struct ber_oid *); struct ber_element *appl_internal_engine(struct ber_oid *); struct ber_element *appl_internal_usmstats(struct ber_oid *); +struct ber_element *appl_internal_system(struct ber_oid *); struct appl_internal_object *appl_internal_object_parent(struct ber_oid *); int appl_internal_object_cmp(struct appl_internal_object *, struct appl_internal_object *); @@ -73,6 +74,15 @@ RB_PROTOTYPE_STATIC(appl_internal_objects, appl_internal_object, entry, void appl_internal_init(void) { + appl_internal_region(&OID(MIB_system)); + appl_internal_object(&OID(MIB_sysDescr), appl_internal_system, NULL); + appl_internal_object(&OID(MIB_sysOID), appl_internal_system, NULL); + appl_internal_object(&OID(MIB_sysUpTime), appl_internal_system, NULL); + appl_internal_object(&OID(MIB_sysContact), appl_internal_system, NULL); + appl_internal_object(&OID(MIB_sysName), appl_internal_system, NULL); + appl_internal_object(&OID(MIB_sysLocation), appl_internal_system, NULL); + appl_internal_object(&OID(MIB_sysServices), appl_internal_system, NULL); + appl_internal_region(&OID(MIB_snmp)); appl_internal_object(&OID(MIB_snmpInPkts), appl_internal_snmp, NULL); appl_internal_object(&OID(MIB_snmpOutPkts), appl_internal_snmp, NULL); @@ -441,6 +451,30 @@ appl_internal_usmstats(struct ber_oid *oid) return value; } +struct ber_element * +appl_internal_system(struct ber_oid *oid) +{ + struct snmp_system *s = &snmpd_env->sc_system; + struct ber_element *value = NULL; + + if (ober_oid_cmp(&OID(MIB_sysDescr, 0), oid) == 0) + return ober_add_string(NULL, s->sys_descr); + else if (ober_oid_cmp(&OID(MIB_sysOID, 0), oid) == 0) + return ober_add_oid(NULL, &s->sys_oid); + else if (ober_oid_cmp(&OID(MIB_sysUpTime, 0), oid) == 0) { + value = ober_add_integer(NULL, smi_getticks()); + ober_set_header(value, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS); + } else if (ober_oid_cmp(&OID(MIB_sysContact, 0), oid) == 0) + return ober_add_string(NULL, s->sys_contact); + else if (ober_oid_cmp(&OID(MIB_sysName, 0), oid) == 0) + return ober_add_string(NULL, s->sys_name); + else if (ober_oid_cmp(&OID(MIB_sysLocation, 0), oid) == 0) + return ober_add_string(NULL, s->sys_location); + else if (ober_oid_cmp(&OID(MIB_sysServices, 0), oid) == 0) + return ober_add_integer(NULL, s->sys_services); + return value; +} + struct appl_internal_object * appl_internal_object_parent(struct ber_oid *oid) { diff --git a/parse.y b/parse.y index 8f9bad0..7ae7ce1 100644 --- a/parse.y +++ b/parse.y @@ -28,6 +28,7 @@ #include <sys/stat.h> #include <sys/queue.h> #include <sys/tree.h> +#include <sys/utsname.h> #include <netinet/in.h> #include <net/if.h> @@ -760,28 +761,87 @@ system : SYSTEM sysmib ; sysmib : CONTACT STRING { - struct ber_oid o = OID(MIB_sysContact); - mps_set(&o, $2, strlen($2)); + if (conf->sc_system.sys_contact[0] != '\0') { + yyerror("system contact already defined"); + free($2); + YYERROR; + } + if (strlcpy(conf->sc_system.sys_contact, $2, + sizeof(conf->sc_system.sys_contact)) >= + sizeof(conf->sc_system.sys_contact)) { + yyerror("system contact too long"); + free($2); + YYERROR; + } + free($2); } | DESCR STRING { - struct ber_oid o = OID(MIB_sysDescr); - mps_set(&o, $2, strlen($2)); + if (conf->sc_system.sys_descr[0] != '\0') { + yyerror("system description already defined"); + free($2); + YYERROR; + } + if (strlcpy(conf->sc_system.sys_descr, $2, + sizeof(conf->sc_system.sys_descr)) >= + sizeof(conf->sc_system.sys_descr)) { + yyerror("system description too long"); + free($2); + YYERROR; + } + free($2); } | LOCATION STRING { - struct ber_oid o = OID(MIB_sysLocation); - mps_set(&o, $2, strlen($2)); + if (conf->sc_system.sys_location[0] != '\0') { + yyerror("system location already defined"); + free($2); + YYERROR; + } + if (strlcpy(conf->sc_system.sys_location, $2, + sizeof(conf->sc_system.sys_location)) >= + sizeof(conf->sc_system.sys_location)) { + yyerror("system location too long"); + free($2); + YYERROR; + } + free($2); } | NAME STRING { - struct ber_oid o = OID(MIB_sysName); - mps_set(&o, $2, strlen($2)); + if (conf->sc_system.sys_name[0] != '\0') { + yyerror("system name already defined"); + free($2); + YYERROR; + } + if (strlcpy(conf->sc_system.sys_name, $2, + sizeof(conf->sc_system.sys_name)) >= + sizeof(conf->sc_system.sys_name)) { + yyerror("system name too long"); + free($2); + YYERROR; + } + free($2); } | OBJECTID oid { - struct ber_oid o = OID(MIB_sysOID); - mps_set(&o, $2, sizeof(struct ber_oid)); + if (conf->sc_system.sys_oid.bo_n != 0) { + yyerror("system oid already defined"); + free($2); + YYERROR; + } + conf->sc_system.sys_oid = *$2; + free($2); } | SERVICES NUMBER { - struct ber_oid o = OID(MIB_sysServices); - mps_set(&o, NULL, $2); + if (conf->sc_system.sys_services != -1) { + yyerror("system services already defined"); + YYERROR; + } + if ($2 < 0) { + yyerror("system services too small"); + YYERROR; + } else if ($2 > 127) { + yyerror("system services too large"); + YYERROR; + } + conf->sc_system.sys_services = $2; } ; @@ -1575,6 +1635,7 @@ struct snmpd * parse_config(const char *filename, u_int flags) { struct sockaddr_storage ss; + struct utsname u; struct sym *sym, *next; struct address *h; struct trap_address *tr; @@ -1589,6 +1650,7 @@ parse_config(const char *filename, u_int flags) return (NULL); } + conf->sc_system.sys_services = -1; conf->sc_flags = flags; conf->sc_confpath = filename; TAILQ_INIT(&conf->sc_addresses); @@ -1609,6 +1671,25 @@ parse_config(const char *filename, u_int flags) endservent(); + if (uname(&u) == -1) + fatal("uname"); + + if (conf->sc_system.sys_descr[0] == '\0') + snprintf(conf->sc_system.sys_descr, + sizeof(conf->sc_system.sys_descr), "%s %s %s %s %s", + u.sysname, u.nodename, u.release, u.version, u.machine); + if (conf->sc_system.sys_oid.bo_n == 0) + conf->sc_system.sys_oid = OID(MIB_SYSOID_DEFAULT); + if (conf->sc_system.sys_contact[0] == '\0') + snprintf(conf->sc_system.sys_contact, + sizeof(conf->sc_system.sys_contact), "root@%s", u.nodename); + if (conf->sc_system.sys_name[0] == '\0') + snprintf(conf->sc_system.sys_name, + sizeof(conf->sc_system.sys_name), "%s", u.nodename); + if (conf->sc_system.sys_services == -1) + conf->sc_system.sys_services = 0; + + /* Must be identical to enginefmt_local:HOSTHASH */ if (conf->sc_engineid_len == 0) { if (gethostname(hostname, sizeof(hostname)) == -1) diff --git a/smi.c b/smi.c index 3a5b3ba..655904d 100644 --- a/smi.c +++ b/smi.c @@ -53,6 +53,7 @@ RB_HEAD(oidtree, oid); RB_PROTOTYPE(oidtree, oid, o_element, smi_oid_cmp); struct oidtree smi_oidtree; +static struct oid smi_objects[] = MIB_TREE; RB_HEAD(keytree, oid); RB_PROTOTYPE(keytree, oid, o_keyword, smi_key_cmp); @@ -231,7 +232,7 @@ smi_init(void) { /* Initialize the Structure of Managed Information (SMI) */ RB_INIT(&smi_oidtree); - mib_init(); + smi_mibtree(smi_objects); return (0); } diff --git a/snmpd.h b/snmpd.h index 8313a79..d0b6914 100644 --- a/snmpd.h +++ b/snmpd.h @@ -428,6 +428,15 @@ struct usmuser { SLIST_ENTRY(usmuser) uu_next; }; +struct snmp_system { + char sys_descr[256]; + struct ber_oid sys_oid; + char sys_contact[256]; + char sys_name[256]; + char sys_location[256]; + int8_t sys_services; +}; + struct snmpd { u_int8_t sc_flags; #define SNMPD_F_VERBOSE 0x01 @@ -448,6 +457,7 @@ struct snmpd { size_t sc_engineid_len; struct snmp_stats sc_stats; + struct snmp_system sc_system; struct trap_addresslist sc_trapreceivers;