net-snmp/agent/mibgroup/mibII/system_mib.c

548 lines
18 KiB
C

/*
* 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 <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-features.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <sys/types.h>
#if HAVE_UTSNAME_H
#include <utsname.h>
#else
#if HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
#endif
#endif
#if defined(cygwin) || defined(mingw32)
#include <winerror.h>
#endif
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/sysORTable.h>
#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,
&registeredOwnerSz) == 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 */