diff options
Diffstat (limited to 'agent/mibgroup/mibII/udp.c')
-rw-r--r-- | agent/mibgroup/mibII/udp.c | 570 |
1 files changed, 570 insertions, 0 deletions
diff --git a/agent/mibgroup/mibII/udp.c b/agent/mibgroup/mibII/udp.c new file mode 100644 index 0000000..1ddcbc5 --- /dev/null +++ b/agent/mibgroup/mibII/udp.c @@ -0,0 +1,570 @@ +/* + * UDP MIB group implementation - udp.c + * + */ + +#include <net-snmp/net-snmp-config.h> +#include "mibII_common.h" + +#ifdef HAVE_NETINET_UDP_H +#include <netinet/udp.h> +#endif +#if HAVE_NETINET_UDP_VAR_H +#include <netinet/udp_var.h> +#endif + +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include <net-snmp/agent/auto_nlist.h> +#include <net-snmp/agent/sysORTable.h> + +#include "util_funcs/MIB_STATS_CACHE_TIMEOUT.h" + +#ifdef linux +#include "tcp.h" +#endif +#include "udp.h" +#include "udpTable.h" + +#ifdef NETSNMP_CAN_USE_SYSCTL +#include <sys/sysctl.h> +#endif + +#ifndef MIB_STATS_CACHE_TIMEOUT +#define MIB_STATS_CACHE_TIMEOUT 5 +#endif +#ifndef UDP_STATS_CACHE_TIMEOUT +#define UDP_STATS_CACHE_TIMEOUT MIB_STATS_CACHE_TIMEOUT +#endif + +#if defined(HAVE_LIBPERFSTAT_H) && (defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)) && !defined(FIRST_PROTOCOL) +#ifdef HAVE_SYS_PROTOSW_H +#include <sys/protosw.h> +#endif +#include <libperfstat.h> +#ifdef FIRST_PROTOCOL +perfstat_protocol_t ps_proto; +perfstat_id_t ps_name; +#define _USE_PERFSTAT_PROTOCOL 1 +#endif +#endif + + /********************* + * + * Kernel & interface information, + * and internal forward declarations + * + *********************/ + + + /********************* + * + * Initialisation & common implementation functions + * + *********************/ + +/* + * Define the OID pointer to the top of the mib tree that we're + * registering underneath, and the OID for the MIB module + */ +oid udp_oid[] = { SNMP_OID_MIB2, 7 }; +oid udp_module_oid[] = { SNMP_OID_MIB2, 50 }; + +void +init_udp(void) +{ + netsnmp_handler_registration *reginfo; + int rc; + + /* + * register ourselves with the agent as a group of scalars... + */ + DEBUGMSGTL(("mibII/udpScalar", "Initialising UDP scalar group\n")); + reginfo = netsnmp_create_handler_registration("udp", udp_handler, + udp_oid, OID_LENGTH(udp_oid), HANDLER_CAN_RONLY); + rc = netsnmp_register_scalar_group(reginfo, UDPINDATAGRAMS, UDPOUTDATAGRAMS); + if (rc != SNMPERR_SUCCESS) + return; + + /* + * .... with a local cache + * (except for HP-UX 11, which extracts objects individually) + */ +#ifndef hpux11 + netsnmp_inject_handler( reginfo, + netsnmp_get_cache_handler(UDP_STATS_CACHE_TIMEOUT, + udp_load, udp_free, + udp_oid, OID_LENGTH(udp_oid))); +#endif + + REGISTER_SYSOR_ENTRY(udp_module_oid, + "The MIB module for managing UDP implementations"); + +#if !defined(_USE_PERFSTAT_PROTOCOL) +#ifdef UDPSTAT_SYMBOL + auto_nlist(UDPSTAT_SYMBOL, 0, 0); +#endif +#ifdef UDB_SYMBOL + auto_nlist(UDB_SYMBOL, 0, 0); +#endif +#ifdef solaris2 + init_kernel_sunos5(); +#endif +#endif +} + + + /********************* + * + * System specific implementation functions + * + *********************/ + +#ifdef hpux11 +#define UDP_STAT_STRUCTURE int +#endif + +#ifdef linux +#define UDP_STAT_STRUCTURE struct udp_mib +#define USES_SNMP_DESIGNED_UDPSTAT +#undef UDPSTAT_SYMBOL +#endif + +#ifdef solaris2 +#define UDP_STAT_STRUCTURE mib2_udp_t +#define USES_SNMP_DESIGNED_UDPSTAT +#endif + +#ifdef NETBSD_STATS_VIA_SYSCTL +#define UDP_STAT_STRUCTURE struct udp_mib +#define USES_SNMP_DESIGNED_UDPSTAT +#undef UDP_NSTATS +#endif + +#ifdef HAVE_IPHLPAPI_H +#include <iphlpapi.h> +#define UDP_STAT_STRUCTURE MIB_UDPSTATS +#endif + +#ifdef HAVE_SYS_TCPIPSTATS_H +#define UDP_STAT_STRUCTURE struct kna +#define USES_TRADITIONAL_UDPSTAT +#endif + + +#if !defined(UDP_STAT_STRUCTURE) +#define UDP_STAT_STRUCTURE struct udpstat +#define USES_TRADITIONAL_UDPSTAT +#endif + +UDP_STAT_STRUCTURE udpstat; + + + /********************* + * + * System independent handler (mostly) + * + *********************/ + + + +int +udp_handler(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + netsnmp_request_info *request; + netsnmp_variable_list *requestvb; + long ret_value = -1; + oid subid; + int type = ASN_COUNTER; + + /* + * The cached data should already have been loaded by the + * cache handler, higher up the handler chain. + * But just to be safe, check this and load it manually if necessary + */ +#if defined(_USE_PERFSTAT_PROTOCOL) + udp_load(NULL, NULL); +#endif + + + /* + * + * + */ + DEBUGMSGTL(("mibII/udpScalar", "Handler - mode %s\n", + se_find_label_in_slist("agent_mode", reqinfo->mode))); + switch (reqinfo->mode) { + case MODE_GET: + for (request=requests; request; request=request->next) { + requestvb = request->requestvb; + subid = requestvb->name[OID_LENGTH(udp_oid)]; /* XXX */ + DEBUGMSGTL(( "mibII/udpScalar", "oid: ")); + DEBUGMSGOID(("mibII/udpScalar", requestvb->name, + requestvb->name_length)); + DEBUGMSG(( "mibII/udpScalar", "\n")); + + switch (subid) { +#ifdef USES_SNMP_DESIGNED_UDPSTAT + case UDPINDATAGRAMS: + ret_value = udpstat.udpInDatagrams; + break; + case UDPNOPORTS: +#ifdef solaris2 + ret_value = udp_load(NULL, (void *)UDPNOPORTS); + if (ret_value == -1) { + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); + continue; + } + break; +#else + ret_value = udpstat.udpNoPorts; + break; +#endif + case UDPOUTDATAGRAMS: + ret_value = udpstat.udpOutDatagrams; + break; + case UDPINERRORS: + ret_value = udpstat.udpInErrors; + break; +#elif defined(USES_TRADITIONAL_UDPSTAT) && !defined(_USE_PERFSTAT_PROTOCOL) +#ifdef HAVE_SYS_TCPIPSTATS_H + /* + * This actually reads statistics for *all* the groups together, + * so we need to isolate the UDP-specific bits. + */ +#define udpstat udpstat.udpstat +#endif + case UDPINDATAGRAMS: +#if HAVE_STRUCT_UDPSTAT_UDPS_IPACKETS + ret_value = udpstat.udps_ipackets; + break; +#else + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); + continue; +#endif + + case UDPNOPORTS: +#if HAVE_STRUCT_UDPSTAT_UDPS_NOPORT + ret_value = udpstat.udps_noport; + break; +#else + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); + continue; +#endif + + case UDPOUTDATAGRAMS: +#if HAVE_STRUCT_UDPSTAT_UDPS_OPACKETS + ret_value = udpstat.udps_opackets; + break; +#else + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); + continue; +#endif + + case UDPINERRORS: + ret_value = udpstat.udps_hdrops + udpstat.udps_badsum + +#ifdef HAVE_STRUCT_UDPSTAT_UDPS_DISCARD + udpstat.udps_discard + +#endif +#ifdef HAVE_STRUCT_UDPSTAT_UDPS_FULLSOCK + udpstat.udps_fullsock + +#endif + udpstat.udps_badlen; + break; +#ifdef HAVE_SYS_TCPIPSTATS_H +#undef udpstat +#endif +#elif defined(hpux11) + case UDPINDATAGRAMS: + case UDPNOPORTS: + case UDPOUTDATAGRAMS: + case UDPINERRORS: + /* + * This is a bit of a hack, to shoehorn the HP-UX 11 + * single-object retrieval approach into the caching + * architecture. + */ + if (udp_load(NULL, (void*)subid) == -1 ) { + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); + continue; + } + ret_value = udpstat; + break; +#elif defined(WIN32) + case UDPINDATAGRAMS: + ret_value = udpstat.dwInDatagrams; + break; + case UDPNOPORTS: + ret_value = udpstat.dwNoPorts; + break; + case UDPOUTDATAGRAMS: + ret_value = udpstat.dwOutDatagrams; + break; + case UDPINERRORS: + ret_value = udpstat.dwInErrors; + break; +#elif defined(_USE_PERFSTAT_PROTOCOL) + case UDPINDATAGRAMS: + ret_value = ps_proto.u.udp.ipackets; + break; + case UDPNOPORTS: + ret_value = ps_proto.u.udp.no_socket; + break; + case UDPOUTDATAGRAMS: + ret_value = ps_proto.u.udp.opackets; + break; + case UDPINERRORS: + ret_value = ps_proto.u.udp.ierrors; + break; +#endif /* USES_SNMP_DESIGNED_UDPSTAT */ + + } + snmp_set_var_typed_value(request->requestvb, (u_char)type, + (u_char *)&ret_value, sizeof(ret_value)); + } + break; + + case MODE_GETNEXT: + case MODE_GETBULK: +#ifndef NETSNMP_NO_WRITE_SUPPORT + case MODE_SET_RESERVE1: + case MODE_SET_RESERVE2: + case MODE_SET_ACTION: + case MODE_SET_COMMIT: + case MODE_SET_FREE: + case MODE_SET_UNDO: + snmp_log(LOG_WARNING, "mibII/udp: Unsupported mode (%d)\n", + reqinfo->mode); + break; +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ + default: + snmp_log(LOG_WARNING, "mibII/udp: Unrecognised mode (%d)\n", + reqinfo->mode); + break; + } + + return SNMP_ERR_NOERROR; +} + + + /********************* + * + * Internal implementation functions + * + *********************/ + +#ifdef hpux11 +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + int fd; + struct nmparms p; + unsigned int ulen; + int ret; + int magic = (int) vmagic; + + if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) < 0) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP object %d (hpux11)\n", magic)); + return (-1); /* error */ + } + + switch (magic) { + case UDPINDATAGRAMS: + p.objid = ID_udpInDatagrams; + break; + case UDPNOPORTS: + p.objid = ID_udpNoPorts; + break; + case UDPOUTDATAGRAMS: + p.objid = ID_udpOutDatagrams; + break; + case UDPINERRORS: + p.objid = ID_udpInErrors; + break; + default: + udpstat = 0; + close_mib(fd); + return -1; + } + + p.buffer = (void *)&udpstat; + ulen = sizeof(UDP_STAT_STRUCTURE); + p.len = &ulen; + ret = get_mib_info(fd, &p); + close_mib(fd); + + DEBUGMSGTL(("mibII/udpScalar", "%s UDP object %d (hpux11)\n", + (ret < 0 ? "Failed to load" : "Loaded"), magic)); + return (ret); /* 0: ok, < 0: error */ +} +#elif defined(linux) +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + long ret_value = -1; + + ret_value = linux_read_udp_stat(&udpstat); + + if ( ret_value < 0 ) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP scalar Group (linux)\n")); + } else { + DEBUGMSGTL(("mibII/udpScalar", "Loaded UDP scalar Group (linux)\n")); + } + return ret_value; +} +#elif defined(solaris2) +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + long ret_value = -1; + int magic = (int)vmagic; + mib2_ip_t ipstat; + + /* + * udpNoPorts is actually implemented as part of the MIB_IP group + * so we need to retrieve this independently + */ + if (magic == UDPNOPORTS) { + if (getMibstat + (MIB_IP, &ipstat, sizeof(mib2_ip_t), GET_FIRST, + &Get_everything, NULL) < 0) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP object %d (solaris)\n", magic)); + return -1; + } else { + DEBUGMSGTL(("mibII/udpScalar", "Loaded UDP object %d (solaris)\n", magic)); + return ipstat.udpNoPorts; + } + } + + /* + * Otherwise, retrieve the whole of the MIB_UDP group (and cache it) + */ + ret_value = getMibstat(MIB_UDP, &udpstat, sizeof(mib2_udp_t), + GET_FIRST, &Get_everything, NULL); + + if ( ret_value < 0 ) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP scalar Group (solaris)\n")); + } else { + DEBUGMSGTL(("mibII/udpScalar", "Loaded UDP scalar Group (solaris)\n")); + } + return ret_value; +} +#elif defined(NETBSD_STATS_VIA_SYSCTL) +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + long ret_value = -1; + + ret_value = netbsd_read_udp_stat(&udpstat); + + if ( ret_value < 0 ) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP scalar Group (netbsd)\n")); + } else { + DEBUGMSGTL(("mibII/udpScalar", "Loaded UDP scalar Group (netbsd)\n")); + } + return ret_value; +} +#elif defined(WIN32) +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + long ret_value = -1; + + ret_value = GetUdpStatistics(&udpstat); + + if ( ret_value < 0 ) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP scalar Group (win32)\n")); + } else { + DEBUGMSGTL(("mibII/udpScalar", "Loaded UDP scalar Group (win32)\n")); + } + return ret_value; +} +#elif defined(_USE_PERFSTAT_PROTOCOL) +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + long ret_value = -1; + + strcpy(ps_name.name, "udp"); + ret_value = perfstat_protocol(&ps_name, &ps_proto, sizeof(ps_proto), 1); + + if ( ret_value < 0 ) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP scalar Group (AIX)\n")); + } else { + ret_value = 0; + DEBUGMSGTL(("mibII/udpScalar", "Loaded UDP scalar Group (AIX)\n")); + } + return ret_value; +} +#elif (defined(NETSNMP_CAN_USE_SYSCTL) && defined(UDPCTL_STATS)) +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + int sname[4] = { CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_STATS }; + size_t len = sizeof(udpstat); + long ret_value = -1; + + ret_value = sysctl(sname, 4, &udpstat, &len, 0, 0); + + if ( ret_value < 0 ) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP scalar Group (sysctl)\n")); + } else { + DEBUGMSGTL(("mibII/udpScalar", "Loaded UDP scalar Group (sysctl)\n")); + } + return ret_value; +} +#elif defined(HAVE_SYS_TCPIPSTATS_H) +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + long ret_value = -1; + + ret_value = sysmp(MP_SAGET, MPSA_TCPIPSTATS, &udpstat, sizeof(udpstat)); + + if ( ret_value < 0 ) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP scalar Group (tcpipstats)\n")); + } else { + DEBUGMSGTL(("mibII/udpScalar", "Loaded UDP scalar Group (tcpipstats)\n")); + } + return ret_value; +} +#elif defined(UDPSTAT_SYMBOL) +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + long ret_value = -1; + + if (auto_nlist(UDPSTAT_SYMBOL, (char *)&udpstat, sizeof(udpstat))) + ret_value = 0; + + if ( ret_value < 0 ) { + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP scalar Group (udpstat)\n")); + } else { + DEBUGMSGTL(("mibII/udpScalar", "Loaded UDP scalar Group (udpstat)\n")); + } + return ret_value; +} +#else /* UDPSTAT_SYMBOL */ +int +udp_load(netsnmp_cache *cache, void *vmagic) +{ + long ret_value = -1; + + DEBUGMSGTL(("mibII/udpScalar", "Failed to load UDP scalar Group (null)\n")); + return ret_value; +} +#endif /* hpux11 */ + + +void +udp_free(netsnmp_cache *cache, void *magic) +{ +#if defined(_USE_PERFSTAT_PROTOCOL) + memset(&ps_proto, 0, sizeof(ps_proto)); +#else + memset(&udpstat, 0, sizeof(udpstat)); +#endif +} |