summaryrefslogtreecommitdiff
path: root/agent/mibgroup/mibII/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/mibII/udp.c')
-rw-r--r--agent/mibgroup/mibII/udp.c570
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
+}