/* * System MIB group implementation - system.c * */ /* Portions of this file are subject to the following copyright(s). See * the Net-SNMP's COPYING file for more details and other copyrights * that may apply: */ /* * Portions of this file are copyrighted by: * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms specified in the COPYING file * distributed with the Net-SNMP package. */ #include #include #if HAVE_STDLIB_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #if HAVE_STRING_H #include #else #include #endif #include #if HAVE_UTSNAME_H #include #else #if HAVE_SYS_UTSNAME_H #include #endif #endif #if defined(cygwin) || defined(mingw32) #include #endif #include #include #include #include "util_funcs.h" #include "system_mib.h" #include "updates.h" #include "agent_global_vars.h" netsnmp_feature_require(watcher_read_only_int_scalar); /********************* * * Kernel & interface information, * and internal forward declarations * *********************/ #define SYS_STRING_LEN 256 static char version_descr[SYS_STRING_LEN] = NETSNMP_VERS_DESC; static char sysContact[SYS_STRING_LEN] = NETSNMP_SYS_CONTACT; static char sysName[SYS_STRING_LEN] = NETSNMP_SYS_NAME; static char sysLocation[SYS_STRING_LEN] = NETSNMP_SYS_LOC; static oid sysObjectID[MAX_OID_LEN]; static size_t sysObjectIDByteLength; static int sysServices = 72; static int sysServicesConfiged = 0; static int sysContactSet = 0, sysLocationSet = 0, sysNameSet = 0; #if (defined (WIN32) && defined (HAVE_WIN32_PLATFORM_SDK)) || defined (mingw32) static void windowsOSVersionString(char [], size_t); #endif /********************* * * snmpd.conf config parsing * *********************/ static void system_parse_config_string2(const char *token, char *cptr, char* value, size_t size) { if (strlen(cptr) < size) { strcpy(value, cptr); } else { netsnmp_config_error("%s token too long (must be < %lu):\n\t%s", token, (unsigned long)size, cptr); } } static void system_parse_config_string(const char *token, char *cptr, const char *name, char* value, size_t size, int* guard) { if (*token == 'p') { if (*guard < 0) { /* * This is bogus (and shouldn't happen anyway) -- the value is * already configured read-only. */ snmp_log(LOG_WARNING, "ignoring attempted override of read-only %s.0\n", name); return; } else { *guard = 1; } } else { if (*guard > 0) { /* * This is bogus (and shouldn't happen anyway) -- we already read a * persistent value which we should ignore in favour of this one. */ snmp_log(LOG_WARNING, "ignoring attempted override of read-only %s.0\n", name); /* * Fall through and copy in this value. */ } *guard = -1; } system_parse_config_string2(token, cptr, value, size); } static void system_parse_config_sysdescr(const char *token, char *cptr) { system_parse_config_string2(token, cptr, version_descr, sizeof(version_descr)); } static void system_parse_config_sysloc(const char *token, char *cptr) { system_parse_config_string(token, cptr, "sysLocation", sysLocation, sizeof(sysLocation), &sysLocationSet); } static void system_parse_config_syscon(const char *token, char *cptr) { system_parse_config_string(token, cptr, "sysContact", sysContact, sizeof(sysContact), &sysContactSet); } static void system_parse_config_sysname(const char *token, char *cptr) { system_parse_config_string(token, cptr, "sysName", sysName, sizeof(sysName), &sysNameSet); } static void system_parse_config_sysServices(const char *token, char *cptr) { sysServices = atoi(cptr); sysServicesConfiged = 1; } static void system_parse_config_sysObjectID(const char *token, char *cptr) { size_t sysObjectIDLength = MAX_OID_LEN; if (!read_objid(cptr, sysObjectID, &sysObjectIDLength)) { netsnmp_config_error("sysobjectid token not a parsable OID:\n\t%s", cptr); sysObjectIDByteLength = version_sysoid_len * sizeof(oid); memcpy(sysObjectID, version_sysoid, sysObjectIDByteLength); } else sysObjectIDByteLength = sysObjectIDLength * sizeof(oid); } /********************* * * Initialisation & common implementation functions * *********************/ oid system_module_oid[] = { SNMP_OID_SNMPMODULES, 1 }; int system_module_oid_len = OID_LENGTH(system_module_oid); int system_module_count = 0; static int system_store(int a, int b, void *c, void *d) { char line[SNMP_MAXBUF_SMALL]; if (sysLocationSet > 0) { snprintf(line, SNMP_MAXBUF_SMALL, "psyslocation %s", sysLocation); snmpd_store_config(line); } if (sysContactSet > 0) { snprintf(line, SNMP_MAXBUF_SMALL, "psyscontact %s", sysContact); snmpd_store_config(line); } if (sysNameSet > 0) { snprintf(line, SNMP_MAXBUF_SMALL, "psysname %s", sysName); snmpd_store_config(line); } return 0; } static int handle_sysServices(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { #if NETSNMP_NO_DUMMY_VALUES if (reqinfo->mode == MODE_GET && !sysServicesConfiged) netsnmp_request_set_error(requests, SNMP_NOSUCHINSTANCE); #endif return SNMP_ERR_NOERROR; } static int handle_sysUpTime(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { snmp_set_var_typed_integer(requests->requestvb, ASN_TIMETICKS, netsnmp_get_agent_uptime()); return SNMP_ERR_NOERROR; } void init_system_mib(void) { #ifdef HAVE_UNAME struct utsname utsName; uname(&utsName); snprintf(version_descr, sizeof(version_descr), "%s %s %s %s %s", utsName.sysname, utsName.nodename, utsName.release, utsName.version, utsName.machine); version_descr[ sizeof(version_descr)-1 ] = 0; #else #if HAVE_EXECV struct extensible extmp; /* * set default values of system stuff */ if (asprintf(&extmp.command, "%s -a", UNAMEPROG) < 0) extmp.command = NULL; /* * setup defaults */ extmp.type = EXECPROC; extmp.next = NULL; exec_command(&extmp); strlcpy(version_descr, extmp.output, sizeof(version_descr)); if (strlen(version_descr) >= 1) version_descr[strlen(version_descr) - 1] = 0; /* chomp new line */ #else #if (defined (WIN32) && defined (HAVE_WIN32_PLATFORM_SDK)) || defined (mingw32) windowsOSVersionString(version_descr, sizeof(version_descr)); #else strcpy(version_descr, "unknown"); #endif #endif #endif #ifdef HAVE_GETHOSTNAME gethostname(sysName, sizeof(sysName)); #else #ifdef HAVE_UNAME strlcpy(sysName, utsName.nodename, sizeof(sysName)); #else #if defined (HAVE_EXECV) && !defined (mingw32) if (asprintf(&extmp.command, "%s -n", UNAMEPROG) < 0) extmp.command = NULL; /* * setup defaults */ extmp.type = EXECPROC; extmp.next = NULL; exec_command(&extmp); strlcpy(sysName, extmp.output, sizeof(sysName)); if (strlen(sysName) >= 1) sysName[strlen(sysName) - 1] = 0; /* chomp new line */ #else strcpy(sysName, "unknown"); #endif /* HAVE_EXECV */ #endif /* HAVE_UNAME */ #endif /* HAVE_GETHOSTNAME */ #if (defined (WIN32) && defined (HAVE_WIN32_PLATFORM_SDK)) || defined (mingw32) { HKEY hKey; /* Default sysContact is the registered windows user */ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { char registeredOwner[256] = ""; DWORD registeredOwnerSz = 256; if (RegQueryValueEx(hKey, "RegisteredOwner", NULL, NULL, (LPBYTE)registeredOwner, ®isteredOwnerSz) == ERROR_SUCCESS) { strlcpy(sysContact, registeredOwner, sizeof(sysContact)); } RegCloseKey(hKey); } } #endif /* default sysObjectID */ memcpy(sysObjectID, version_sysoid, version_sysoid_len * sizeof(oid)); sysObjectIDByteLength = version_sysoid_len * sizeof(oid); { const oid sysDescr_oid[] = { 1, 3, 6, 1, 2, 1, 1, 1 }; static netsnmp_watcher_info sysDescr_winfo; netsnmp_register_watched_scalar( netsnmp_create_handler_registration( "mibII/sysDescr", NULL, sysDescr_oid, OID_LENGTH(sysDescr_oid), HANDLER_CAN_RONLY), netsnmp_init_watcher_info(&sysDescr_winfo, version_descr, 0, ASN_OCTET_STR, WATCHER_SIZE_STRLEN)); } { const oid sysObjectID_oid[] = { 1, 3, 6, 1, 2, 1, 1, 2 }; static netsnmp_watcher_info sysObjectID_winfo; netsnmp_register_watched_scalar( netsnmp_create_handler_registration( "mibII/sysObjectID", NULL, sysObjectID_oid, OID_LENGTH(sysObjectID_oid), HANDLER_CAN_RONLY), netsnmp_init_watcher_info6( &sysObjectID_winfo, sysObjectID, 0, ASN_OBJECT_ID, WATCHER_MAX_SIZE | WATCHER_SIZE_IS_PTR, MAX_OID_LEN, &sysObjectIDByteLength)); } { const oid sysUpTime_oid[] = { 1, 3, 6, 1, 2, 1, 1, 3 }; netsnmp_register_scalar( netsnmp_create_handler_registration( "mibII/sysUpTime", handle_sysUpTime, sysUpTime_oid, OID_LENGTH(sysUpTime_oid), HANDLER_CAN_RONLY)); } { const oid sysContact_oid[] = { 1, 3, 6, 1, 2, 1, 1, 4 }; static netsnmp_watcher_info sysContact_winfo; #ifndef NETSNMP_NO_WRITE_SUPPORT netsnmp_register_watched_scalar( netsnmp_create_update_handler_registration( "mibII/sysContact", sysContact_oid, OID_LENGTH(sysContact_oid), HANDLER_CAN_RWRITE, &sysContactSet), netsnmp_init_watcher_info( &sysContact_winfo, sysContact, SYS_STRING_LEN - 1, ASN_OCTET_STR, WATCHER_MAX_SIZE | WATCHER_SIZE_STRLEN)); #else /* !NETSNMP_NO_WRITE_SUPPORT */ netsnmp_register_watched_scalar( netsnmp_create_update_handler_registration( "mibII/sysContact", sysContact_oid, OID_LENGTH(sysContact_oid), HANDLER_CAN_RONLY, &sysContactSet), netsnmp_init_watcher_info( &sysContact_winfo, sysContact, SYS_STRING_LEN - 1, ASN_OCTET_STR, WATCHER_MAX_SIZE | WATCHER_SIZE_STRLEN)); #endif /* !NETSNMP_NO_WRITE_SUPPORT */ } { const oid sysName_oid[] = { 1, 3, 6, 1, 2, 1, 1, 5 }; static netsnmp_watcher_info sysName_winfo; #ifndef NETSNMP_NO_WRITE_SUPPORT netsnmp_register_watched_scalar( netsnmp_create_update_handler_registration( "mibII/sysName", sysName_oid, OID_LENGTH(sysName_oid), HANDLER_CAN_RWRITE, &sysNameSet), netsnmp_init_watcher_info( &sysName_winfo, sysName, SYS_STRING_LEN - 1, ASN_OCTET_STR, WATCHER_MAX_SIZE | WATCHER_SIZE_STRLEN)); #else /* !NETSNMP_NO_WRITE_SUPPORT */ netsnmp_register_watched_scalar( netsnmp_create_update_handler_registration( "mibII/sysName", sysName_oid, OID_LENGTH(sysName_oid), HANDLER_CAN_RONLY, &sysNameSet), netsnmp_init_watcher_info( &sysName_winfo, sysName, SYS_STRING_LEN - 1, ASN_OCTET_STR, WATCHER_MAX_SIZE | WATCHER_SIZE_STRLEN)); #endif /* !NETSNMP_NO_WRITE_SUPPORT */ } { const oid sysLocation_oid[] = { 1, 3, 6, 1, 2, 1, 1, 6 }; static netsnmp_watcher_info sysLocation_winfo; #ifndef NETSNMP_NO_WRITE_SUPPORT netsnmp_register_watched_scalar( netsnmp_create_update_handler_registration( "mibII/sysLocation", sysLocation_oid, OID_LENGTH(sysLocation_oid), HANDLER_CAN_RWRITE, &sysLocationSet), netsnmp_init_watcher_info( &sysLocation_winfo, sysLocation, SYS_STRING_LEN - 1, ASN_OCTET_STR, WATCHER_MAX_SIZE | WATCHER_SIZE_STRLEN)); #else /* !NETSNMP_NO_WRITE_SUPPORT */ netsnmp_register_watched_scalar( netsnmp_create_update_handler_registration( "mibII/sysLocation", sysLocation_oid, OID_LENGTH(sysLocation_oid), HANDLER_CAN_RONLY, &sysLocationSet), netsnmp_init_watcher_info( &sysLocation_winfo, sysLocation, SYS_STRING_LEN - 1, ASN_OCTET_STR, WATCHER_MAX_SIZE | WATCHER_SIZE_STRLEN)); #endif /* !NETSNMP_NO_WRITE_SUPPORT */ } { const oid sysServices_oid[] = { 1, 3, 6, 1, 2, 1, 1, 7 }; netsnmp_register_read_only_int_scalar( "mibII/sysServices", sysServices_oid, OID_LENGTH(sysServices_oid), &sysServices, handle_sysServices); } if (++system_module_count == 3) REGISTER_SYSOR_ENTRY(system_module_oid, "The MIB module for SNMPv2 entities"); sysContactSet = sysLocationSet = sysNameSet = 0; /* * register our config handlers */ snmpd_register_config_handler("sysdescr", system_parse_config_sysdescr, NULL, "description"); snmpd_register_config_handler("syslocation", system_parse_config_sysloc, NULL, "location"); snmpd_register_config_handler("syscontact", system_parse_config_syscon, NULL, "contact-name"); snmpd_register_config_handler("sysname", system_parse_config_sysname, NULL, "node-name"); snmpd_register_config_handler("psyslocation", system_parse_config_sysloc, NULL, NULL); snmpd_register_config_handler("psyscontact", system_parse_config_syscon, NULL, NULL); snmpd_register_config_handler("psysname", system_parse_config_sysname, NULL, NULL); snmpd_register_config_handler("sysservices", system_parse_config_sysServices, NULL, "NUMBER"); snmpd_register_config_handler("sysobjectid", system_parse_config_sysObjectID, NULL, "OID"); snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, system_store, NULL); } /********************* * * Internal implementation functions - None * *********************/ #if (defined (WIN32) && defined (HAVE_WIN32_PLATFORM_SDK)) || defined (mingw32) static DWORD RegReadDword(HKEY hKey, LPCTSTR lpSubkey, LPCTSTR lpValueName) { HKEY hSubkey; LONG qres; DWORD key_type; DWORD result = 0; DWORD result_len = sizeof(result); if (RegOpenKeyEx(hKey, lpSubkey, 0, KEY_READ, &hSubkey) != ERROR_SUCCESS) goto out; qres = RegQueryValueEx(hSubkey, lpValueName, NULL, &key_type, (void *)&result, &result_len); if (qres != ERROR_SUCCESS || key_type != REG_DWORD || result_len != sizeof(DWORD)) result = 0; RegCloseKey(hKey); out: return result; } static BOOL RegReadString(HKEY hKey, LPCTSTR lpSubkey, LPCTSTR lpValueName, char *str, DWORD *str_len) { HKEY hSubkey; LONG qres; DWORD key_type; BOOL result = FALSE; if (RegOpenKeyEx(hKey, lpSubkey, 0, KEY_READ, &hSubkey) != ERROR_SUCCESS) goto out; qres = RegQueryValueEx(hSubkey, lpValueName, NULL, &key_type, (void *)str, str_len); if (qres == ERROR_SUCCESS && key_type == REG_SZ) result = TRUE; RegCloseKey(hKey); out: return result; } static void windowsOSVersionString(char stringbuf[], size_t stringbuflen) { /* copy OS version to string buffer in 'uname -a' format */ static const char wcv[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; char windowsVersion[256] = "?"; DWORD windowsVersionSz = sizeof(windowsVersion); char build[256] = "?"; DWORD buildSz = sizeof(256); DWORD dwMajorVersion; DWORD dwMinorVersion; char hostname[256] = "?"; char identifier[256] = "?"; DWORD identifierSz = sizeof(identifier); dwMajorVersion = RegReadDword(HKEY_LOCAL_MACHINE, wcv, "CurrentMajorVersionNumber"); dwMinorVersion = RegReadDword(HKEY_LOCAL_MACHINE, wcv, "CurrentMinorVersionNumber"); if (!RegReadString(HKEY_LOCAL_MACHINE, wcv, "CurrentBuildNumber", build, &buildSz)) RegReadString(HKEY_LOCAL_MACHINE, wcv, "CurrentBuild", build, &buildSz); gethostname(hostname, sizeof(hostname)); RegReadString(HKEY_LOCAL_MACHINE, wcv, "ProductName", windowsVersion, &windowsVersionSz); RegReadString(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", "Identifier", identifier, &identifierSz); /* Output is made to look like results from uname -a */ snprintf(stringbuf, stringbuflen, "Windows %s %d.%d.%s %s %s", hostname, (int)dwMajorVersion, (int)dwMinorVersion, build, windowsVersion, identifier); } #endif /* WIN32 and HAVE_WIN32_PLATFORM_SDK or mingw32 */