| |
| /* |
| * TCP MIB group implementation - tcp.c |
| * |
| */ |
| |
| #include <net-snmp/net-snmp-config.h> |
| #include "mibII_common.h" |
| |
| #if HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| #if HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| |
| #if HAVE_SYS_PROTOSW_H |
| #include <sys/protosw.h> |
| #endif |
| #if HAVE_ARPA_INET_H |
| #include <arpa/inet.h> |
| #endif |
| |
| #if defined(osf4) || defined(osf5) || defined(aix4) || defined(hpux10) |
| /* |
| * these are undefed to remove a stupid warning on osf compilers |
| * because they get redefined with a slightly different notation of the |
| * same value. -- Wes |
| */ |
| #undef TCP_NODELAY |
| #undef TCP_MAXSEG |
| #endif |
| #if HAVE_NETINET_TCP_H |
| #include <netinet/tcp.h> |
| #endif |
| #if HAVE_NETINET_TCPIP_H |
| #include <netinet/tcpip.h> |
| #endif |
| #if HAVE_NETINET_TCP_TIMER_H |
| #include <netinet/tcp_timer.h> |
| #endif |
| #if HAVE_NETINET_TCP_VAR_H |
| #include <netinet/tcp_var.h> |
| #endif |
| #if HAVE_NETINET_TCP_FSM_H |
| #include <netinet/tcp_fsm.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 "util_funcs.h" |
| #include "tcp.h" |
| #include "tcpTable.h" |
| #include "sysORTable.h" |
| |
| #ifndef MIB_STATS_CACHE_TIMEOUT |
| #define MIB_STATS_CACHE_TIMEOUT 5 |
| #endif |
| #ifndef TCP_STATS_CACHE_TIMEOUT |
| #define TCP_STATS_CACHE_TIMEOUT MIB_STATS_CACHE_TIMEOUT |
| #endif |
| |
| #if defined(HAVE_LIBPERFSTAT_H) && (defined(aix4) || defined(aix5) || defined(aix6)) && !defined(FIRST_PROTOCOL) |
| #include <libperfstat.h> |
| #ifdef FIRST_PROTOCOL |
| perfstat_protocol_t ps_proto; |
| perfstat_id_t ps_name; |
| #define _USE_FIRST_PROTOCOL 1 |
| #endif |
| #endif |
| |
| /********************* |
| * |
| * Kernel & interface information, |
| * and internal forward declarations |
| * |
| *********************/ |
| |
| /* |
| * FreeBSD4 *does* need an explicit variable 'hz' |
| * since this appears in a system header file. |
| * But only define it under FreeBSD, since it |
| * breaks other systems (notable AIX) |
| */ |
| #ifdef freebsd4 |
| int hz = 1000; |
| #endif |
| |
| extern int TCP_Count_Connections( void ); |
| /********************* |
| * |
| * 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 tcp_oid[] = { SNMP_OID_MIB2, 6 }; |
| oid tcp_module_oid[] = { SNMP_OID_MIB2, 49 }; |
| |
| void |
| init_tcp(void) |
| { |
| netsnmp_handler_registration *reginfo; |
| int rc; |
| |
| /* |
| * register ourselves with the agent as a group of scalars... |
| */ |
| DEBUGMSGTL(("mibII/tcpScalar", "Initialising TCP scalar group\n")); |
| reginfo = netsnmp_create_handler_registration("tcp", tcp_handler, |
| tcp_oid, OID_LENGTH(tcp_oid), HANDLER_CAN_RONLY); |
| rc = netsnmp_register_scalar_group(reginfo, TCPRTOALGORITHM, TCPOUTRSTS); |
| 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(TCP_STATS_CACHE_TIMEOUT, |
| tcp_load, tcp_free, |
| tcp_oid, OID_LENGTH(tcp_oid))); |
| #endif |
| |
| REGISTER_SYSOR_ENTRY(tcp_module_oid, |
| "The MIB module for managing TCP implementations"); |
| |
| #if !defined(_USE_FIRST_PROTOCOL) |
| #ifdef TCPSTAT_SYMBOL |
| auto_nlist(TCPSTAT_SYMBOL, 0, 0); |
| #endif |
| #ifdef TCP_SYMBOL |
| auto_nlist(TCP_SYMBOL, 0, 0); |
| #endif |
| #ifdef freebsd4 |
| hz = sysconf(_SC_CLK_TCK); /* get ticks/s from system */ |
| #endif |
| #ifdef solaris2 |
| init_kernel_sunos5(); |
| #endif |
| #endif |
| } |
| |
| /********************* |
| * |
| * System specific implementation functions |
| * |
| *********************/ |
| |
| #ifdef hpux11 |
| #define TCP_STAT_STRUCTURE int |
| #endif |
| |
| #ifdef linux |
| #define TCP_STAT_STRUCTURE struct tcp_mib |
| #define USES_SNMP_DESIGNED_TCPSTAT |
| #undef TCPSTAT_SYMBOL |
| #endif |
| |
| #ifdef solaris2 |
| #define TCP_STAT_STRUCTURE mib2_tcp_t |
| #define USES_SNMP_DESIGNED_TCPSTAT |
| #endif |
| |
| #ifdef NETBSD_STATS_VIA_SYSCTL |
| #define TCP_STAT_STRUCTURE struct tcp_mib |
| #define USES_SNMP_DESIGNED_TCPSTAT |
| #undef TCP_NSTATS |
| #endif |
| |
| #if defined (WIN32) || defined (cygwin) |
| #include <iphlpapi.h> |
| #define TCP_STAT_STRUCTURE MIB_TCPSTATS |
| #endif |
| |
| #ifdef HAVE_SYS_TCPIPSTATS_H |
| #define TCP_STAT_STRUCTURE struct kna |
| #define USES_TRADITIONAL_TCPSTAT |
| #endif |
| |
| #ifdef dragonfly |
| #define TCP_STAT_STRUCTURE struct tcp_stats |
| #define USES_TRADITIONAL_TCPSTAT |
| #endif |
| |
| #if !defined(TCP_STAT_STRUCTURE) |
| #define TCP_STAT_STRUCTURE struct tcpstat |
| #define USES_TRADITIONAL_TCPSTAT |
| #endif |
| |
| TCP_STAT_STRUCTURE tcpstat; |
| |
| |
| |
| /********************* |
| * |
| * System independent handler (mostly) |
| * |
| *********************/ |
| |
| |
| |
| int |
| tcp_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_FIRST_PROTOCOL) |
| tcp_load(NULL, NULL); |
| #endif |
| |
| |
| /* |
| * |
| * |
| */ |
| DEBUGMSGTL(("mibII/tcpScalar", "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(tcp_oid)]; /* XXX */ |
| |
| DEBUGMSGTL(( "mibII/tcpScalar", "oid: ")); |
| DEBUGMSGOID(("mibII/tcpScalar", requestvb->name, |
| requestvb->name_length)); |
| DEBUGMSG(( "mibII/tcpScalar", "\n")); |
| switch (subid) { |
| #ifdef USES_SNMP_DESIGNED_TCPSTAT |
| case TCPRTOALGORITHM: |
| ret_value = tcpstat.tcpRtoAlgorithm; |
| type = ASN_INTEGER; |
| break; |
| case TCPRTOMIN: |
| ret_value = tcpstat.tcpRtoMin; |
| type = ASN_INTEGER; |
| break; |
| case TCPRTOMAX: |
| ret_value = tcpstat.tcpRtoMax; |
| type = ASN_INTEGER; |
| break; |
| case TCPMAXCONN: |
| ret_value = tcpstat.tcpMaxConn; |
| type = ASN_INTEGER; |
| break; |
| case TCPACTIVEOPENS: |
| ret_value = tcpstat.tcpActiveOpens; |
| break; |
| case TCPPASSIVEOPENS: |
| ret_value = tcpstat.tcpPassiveOpens; |
| break; |
| case TCPATTEMPTFAILS: |
| ret_value = tcpstat.tcpAttemptFails; |
| break; |
| case TCPESTABRESETS: |
| ret_value = tcpstat.tcpEstabResets; |
| break; |
| case TCPCURRESTAB: |
| ret_value = tcpstat.tcpCurrEstab; |
| type = ASN_GAUGE; |
| break; |
| case TCPINSEGS: |
| ret_value = tcpstat.tcpInSegs & 0xffffffff; |
| break; |
| case TCPOUTSEGS: |
| ret_value = tcpstat.tcpOutSegs & 0xffffffff; |
| break; |
| case TCPRETRANSSEGS: |
| ret_value = tcpstat.tcpRetransSegs; |
| break; |
| case TCPINERRS: |
| #ifdef solaris2 |
| ret_value = tcp_load(NULL, (void *)TCPINERRS); |
| if (ret_value == -1) { |
| netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); |
| continue; |
| } |
| break; |
| #elif defined(linux) |
| if (tcpstat.tcpInErrsValid) { |
| ret_value = tcpstat.tcpInErrs; |
| break; |
| } else { |
| netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); |
| continue; |
| } |
| #else /* linux */ |
| netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); |
| continue; |
| #endif /* solaris2 */ |
| case TCPOUTRSTS: |
| #ifdef linux |
| if (tcpstat.tcpOutRstsValid) { |
| ret_value = tcpstat.tcpOutRsts; |
| break; |
| } |
| #endif /* linux */ |
| netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); |
| continue; |
| #elif defined(USES_TRADITIONAL_TCPSTAT) && !defined(_USE_FIRST_PROTOCOL) |
| #ifdef HAVE_SYS_TCPIPSTATS_H |
| /* |
| * This actually reads statistics for *all* the groups together, |
| * so we need to isolate the TCP-specific bits. |
| */ |
| #define tcpstat tcpstat.tcpstat |
| #endif |
| case TCPRTOALGORITHM: /* Assume Van Jacobsen's algorithm */ |
| ret_value = 4; |
| type = ASN_INTEGER; |
| break; |
| case TCPRTOMIN: |
| #ifdef TCPTV_NEEDS_HZ |
| ret_value = TCPTV_MIN; |
| #else |
| ret_value = TCPTV_MIN / PR_SLOWHZ * 1000; |
| #endif |
| type = ASN_INTEGER; |
| break; |
| case TCPRTOMAX: |
| #ifdef TCPTV_NEEDS_HZ |
| ret_value = TCPTV_REXMTMAX; |
| #else |
| ret_value = TCPTV_REXMTMAX / PR_SLOWHZ * 1000; |
| #endif |
| type = ASN_INTEGER; |
| break; |
| case TCPMAXCONN: |
| ret_value = -1; /* Dynamic maximum */ |
| type = ASN_INTEGER; |
| break; |
| case TCPACTIVEOPENS: |
| ret_value = tcpstat.tcps_connattempt; |
| break; |
| case TCPPASSIVEOPENS: |
| ret_value = tcpstat.tcps_accepts; |
| break; |
| /* |
| * NB: tcps_drops is actually the sum of the two MIB |
| * counters tcpAttemptFails and tcpEstabResets. |
| */ |
| case TCPATTEMPTFAILS: |
| ret_value = tcpstat.tcps_conndrops; |
| break; |
| case TCPESTABRESETS: |
| ret_value = tcpstat.tcps_drops; |
| break; |
| case TCPCURRESTAB: |
| #ifdef USING_MIBII_TCPTABLE_MODULE |
| ret_value = TCP_Count_Connections(); |
| #else |
| ret_value = 0; |
| #endif |
| type = ASN_GAUGE; |
| break; |
| case TCPINSEGS: |
| ret_value = tcpstat.tcps_rcvtotal & 0xffffffff; |
| break; |
| case TCPOUTSEGS: |
| /* |
| * RFC 1213 defines this as the number of segments sent |
| * "excluding those containing only retransmitted octets" |
| */ |
| ret_value = (tcpstat.tcps_sndtotal - tcpstat.tcps_sndrexmitpack) & 0xffffffff; |
| break; |
| case TCPRETRANSSEGS: |
| ret_value = tcpstat.tcps_sndrexmitpack; |
| break; |
| case TCPINERRS: |
| ret_value = tcpstat.tcps_rcvbadsum + tcpstat.tcps_rcvbadoff |
| #ifdef STRUCT_TCPSTAT_HAS_TCPS_RCVMEMDROP |
| + tcpstat.tcps_rcvmemdrop |
| #endif |
| + tcpstat.tcps_rcvshort; |
| break; |
| case TCPOUTRSTS: |
| ret_value = tcpstat.tcps_sndctrl - tcpstat.tcps_closed; |
| break; |
| #ifdef HAVE_SYS_TCPIPSTATS_H |
| #undef tcpstat |
| #endif |
| #elif defined(hpux11) |
| case TCPRTOALGORITHM: |
| case TCPRTOMIN: |
| case TCPRTOMAX: |
| case TCPMAXCONN: |
| case TCPCURRESTAB: |
| if (subid == TCPCURRESTAB) |
| type = ASN_GAUGE; |
| else |
| type = ASN_INTEGER; |
| case TCPACTIVEOPENS: |
| case TCPPASSIVEOPENS: |
| case TCPATTEMPTFAILS: |
| case TCPESTABRESETS: |
| case TCPINSEGS: |
| case TCPOUTSEGS: |
| case TCPRETRANSSEGS: |
| case TCPINERRS: |
| case TCPOUTRSTS: |
| /* |
| * This is a bit of a hack, to shoehorn the HP-UX 11 |
| * single-object retrieval approach into the caching |
| * architecture. |
| */ |
| if (tcp_load(NULL, (void*)subid) == -1 ) { |
| netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); |
| continue; |
| } |
| ret_value = tcpstat; |
| break; |
| #elif defined (WIN32) || defined (cygwin) |
| case TCPRTOALGORITHM: |
| ret_value = tcpstat.dwRtoAlgorithm; |
| type = ASN_INTEGER; |
| break; |
| case TCPRTOMIN: |
| ret_value = tcpstat.dwRtoMin; |
| type = ASN_INTEGER; |
| break; |
| case TCPRTOMAX: |
| ret_value = tcpstat.dwRtoMax; |
| type = ASN_INTEGER; |
| break; |
| case TCPMAXCONN: |
| ret_value = tcpstat.dwMaxConn; |
| type = ASN_INTEGER; |
| break; |
| case TCPACTIVEOPENS: |
| ret_value = tcpstat.dwActiveOpens; |
| break; |
| case TCPPASSIVEOPENS: |
| ret_value = tcpstat.dwPassiveOpens; |
| break; |
| case TCPATTEMPTFAILS: |
| ret_value = tcpstat.dwAttemptFails; |
| break; |
| case TCPESTABRESETS: |
| ret_value = tcpstat.dwEstabResets; |
| break; |
| case TCPCURRESTAB: |
| ret_value = tcpstat.dwCurrEstab; |
| type = ASN_GAUGE; |
| break; |
| case TCPINSEGS: |
| ret_value = tcpstat.dwInSegs; |
| break; |
| case TCPOUTSEGS: |
| ret_value = tcpstat.dwOutSegs; |
| break; |
| case TCPRETRANSSEGS: |
| ret_value = tcpstat.dwRetransSegs; |
| break; |
| case TCPINERRS: |
| ret_value = tcpstat.dwInErrs; |
| break; |
| case TCPOUTRSTS: |
| ret_value = tcpstat.dwOutRsts; |
| break; |
| #elif defined(_USE_FIRST_PROTOCOL) |
| case TCPRTOALGORITHM: |
| ret_value = 4; |
| type = ASN_INTEGER; |
| break; |
| case TCPRTOMIN: |
| ret_value = 0; |
| type = ASN_INTEGER; |
| break; |
| case TCPRTOMAX: |
| ret_value = 0; |
| type = ASN_INTEGER; |
| break; |
| case TCPMAXCONN: |
| ret_value = -1; |
| type = ASN_INTEGER; |
| break; |
| case TCPACTIVEOPENS: |
| ret_value = ps_proto.u.tcp.initiated; |
| break; |
| case TCPPASSIVEOPENS: |
| ret_value = ps_proto.u.tcp.accepted; |
| break; |
| case TCPATTEMPTFAILS: |
| ret_value = ps_proto.u.tcp.dropped; |
| break; |
| case TCPESTABRESETS: |
| ret_value = ps_proto.u.tcp.dropped; |
| break; |
| case TCPCURRESTAB: |
| /* this value is currently missing */ |
| ret_value = 0; /*ps_proto.u.tcp.established;*/ |
| type = ASN_GAUGE; |
| break; |
| case TCPINSEGS: |
| ret_value = ps_proto.u.tcp.ipackets; |
| break; |
| case TCPOUTSEGS: |
| ret_value = ps_proto.u.tcp.opackets; |
| break; |
| case TCPRETRANSSEGS: |
| ret_value = 0; |
| break; |
| case TCPINERRS: |
| ret_value = ps_proto.u.tcp.ierrors; |
| break; |
| case TCPOUTRSTS: |
| ret_value = 0; |
| break; |
| #endif /* USES_SNMP_DESIGNED_TCPSTAT */ |
| |
| case TCPCONNTABLE: |
| /* |
| * This is not actually a valid scalar object. |
| * The table registration should take precedence, |
| * so skip this subtree, regardless of architecture. |
| */ |
| netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); |
| continue; |
| |
| } |
| snmp_set_var_typed_value(request->requestvb, (u_char)type, |
| (u_char *)&ret_value, sizeof(ret_value)); |
| } |
| break; |
| |
| case MODE_GETNEXT: |
| case MODE_GETBULK: |
| 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/tcp: Unsupported mode (%d)\n", |
| reqinfo->mode); |
| break; |
| default: |
| snmp_log(LOG_WARNING, "mibII/tcp: Unrecognised mode (%d)\n", |
| reqinfo->mode); |
| break; |
| } |
| |
| return SNMP_ERR_NOERROR; |
| } |
| |
| |
| |
| /********************* |
| * |
| * Internal implementation functions |
| * |
| *********************/ |
| |
| #ifdef hpux11 |
| int |
| tcp_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/tcpScalar", "Failed to load TCP object %d (hpux11)\n", magic)); |
| return (-1); /* error */ |
| } |
| |
| switch (magic) { |
| case TCPRTOALGORITHM: |
| p.objid = ID_tcpRtoAlgorithm; |
| break; |
| case TCPRTOMIN: |
| p.objid = ID_tcpRtoMin; |
| break; |
| case TCPRTOMAX: |
| p.objid = ID_tcpRtoMax; |
| break; |
| case TCPMAXCONN: |
| p.objid = ID_tcpMaxConn; |
| break; |
| case TCPACTIVEOPENS: |
| p.objid = ID_tcpActiveOpens; |
| break; |
| case TCPPASSIVEOPENS: |
| p.objid = ID_tcpPassiveOpens; |
| break; |
| case TCPATTEMPTFAILS: |
| p.objid = ID_tcpAttemptFails; |
| break; |
| case TCPESTABRESETS: |
| p.objid = ID_tcpEstabResets; |
| break; |
| case TCPCURRESTAB: |
| p.objid = ID_tcpCurrEstab; |
| break; |
| case TCPINSEGS: |
| p.objid = ID_tcpInSegs; |
| break; |
| case TCPOUTSEGS: |
| p.objid = ID_tcpOutSegs; |
| break; |
| case TCPRETRANSSEGS: |
| p.objid = ID_tcpRetransSegs; |
| break; |
| case TCPINERRS: |
| p.objid = ID_tcpInErrs; |
| break; |
| case TCPOUTRSTS: |
| p.objid = ID_tcpOutRsts; |
| break; |
| default: |
| tcpstat = 0; |
| close_mib(fd); |
| return -1; |
| } |
| |
| p.buffer = (void *)&tcpstat; |
| ulen = sizeof(TCP_STAT_STRUCTURE); |
| p.len = &ulen; |
| ret = get_mib_info(fd, &p); |
| close_mib(fd); |
| |
| DEBUGMSGTL(("mibII/tcpScalar", "%s TCP object %d (hpux11)\n", |
| (ret < 0 ? "Failed to load" : "Loaded"), magic)); |
| return (ret); /* 0: ok, < 0: error */ |
| } |
| #elif defined(linux) |
| int |
| tcp_load(netsnmp_cache *cache, void *vmagic) |
| { |
| long ret_value = -1; |
| |
| ret_value = linux_read_tcp_stat(&tcpstat); |
| |
| if ( ret_value < 0 ) { |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP scalar Group (linux)\n")); |
| } else { |
| DEBUGMSGTL(("mibII/tcpScalar", "Loaded TCP scalar Group (linux)\n")); |
| } |
| return ret_value; |
| } |
| #elif defined(solaris2) |
| int |
| tcp_load(netsnmp_cache *cache, void *vmagic) |
| { |
| long ret_value = -1; |
| int magic = (int)vmagic; |
| mib2_ip_t ipstat; |
| |
| /* |
| * tcpInErrs is actually implemented as part of the MIB_IP group |
| * so we need to retrieve this independently |
| */ |
| if (magic == TCPINERRS) { |
| if (getMibstat |
| (MIB_IP, &ipstat, sizeof(mib2_ip_t), GET_FIRST, |
| &Get_everything, NULL) < 0) { |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP object %d (solaris)\n", magic)); |
| return -1; |
| } else { |
| DEBUGMSGTL(("mibII/tcpScalar", "Loaded TCP object %d (solaris)\n", magic)); |
| return ipstat.tcpInErrs; |
| } |
| } |
| |
| /* |
| * Otherwise, retrieve the whole of the MIB_TCP group (and cache it) |
| */ |
| ret_value = getMibstat(MIB_TCP, &tcpstat, sizeof(mib2_tcp_t), |
| GET_FIRST, &Get_everything, NULL); |
| |
| if ( ret_value < 0 ) { |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP scalar Group (solaris)\n")); |
| } else { |
| DEBUGMSGTL(("mibII/tcpScalar", "Loaded TCP scalar Group (solaris)\n")); |
| } |
| return ret_value; |
| } |
| #elif defined(NETBSD_STATS_VIA_SYSCTL) |
| int |
| tcp_load(netsnmp_cache *cache, void *vmagic) |
| { |
| long ret_value = -1; |
| |
| ret_value = netbsd_read_tcp_stat(&tcpstat); |
| |
| if ( ret_value < 0 ) { |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP scalar Group (netbsd)\n")); |
| } else { |
| DEBUGMSGTL(("mibII/tcpScalar", "Loaded TCP scalar Group (netbsd)\n")); |
| } |
| return ret_value; |
| } |
| #elif defined (WIN32) || defined (cygwin) |
| int |
| tcp_load(netsnmp_cache *cache, void *vmagic) |
| { |
| long ret_value = -1; |
| |
| ret_value = GetTcpStatistics(&tcpstat); |
| |
| if ( ret_value < 0 ) { |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP scalar Group (win32)\n")); |
| } else { |
| DEBUGMSGTL(("mibII/tcpScalar", "Loaded TCP scalar Group (win32)\n")); |
| } |
| return ret_value; |
| } |
| #elif defined(_USE_FIRST_PROTOCOL) |
| int |
| tcp_load(netsnmp_cache *cache, void *vmagic) |
| { |
| long ret_value = -1; |
| |
| strcpy(ps_name.name, "tcp"); |
| ret_value = perfstat_protocol(&ps_name, &ps_proto, sizeof(ps_proto), 1); |
| |
| if ( ret_value < 0 ) { |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP scalar Group (AIX)\n")); |
| } else { |
| ret_value = 0; |
| DEBUGMSGTL(("mibII/tcpScalar", "Loaded TCP scalar Group (AIX)\n")); |
| } |
| return ret_value; |
| } |
| #elif (defined(NETSNMP_CAN_USE_SYSCTL) && defined(TCPCTL_STATS)) |
| int |
| tcp_load(netsnmp_cache *cache, void *vmagic) |
| { |
| int sname[4] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_STATS }; |
| size_t len = sizeof(tcpstat); |
| long ret_value = -1; |
| |
| ret_value = sysctl(sname, 4, &tcpstat, &len, 0, 0); |
| |
| if ( ret_value < 0 ) { |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP scalar Group (sysctl)\n")); |
| } else { |
| DEBUGMSGTL(("mibII/tcpScalar", "Loaded TCP scalar Group (sysctl)\n")); |
| } |
| return ret_value; |
| } |
| #elif defined(HAVE_SYS_TCPIPSTATS_H) |
| int |
| tcp_load(netsnmp_cache *cache, void *vmagic) |
| { |
| long ret_value = -1; |
| |
| ret_value = sysmp(MP_SAGET, MPSA_TCPIPSTATS, &tcpstat, sizeof(tcpstat)); |
| |
| if ( ret_value < 0 ) { |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP scalar Group (tcpipstats)\n")); |
| } else { |
| DEBUGMSGTL(("mibII/tcpScalar", "Loaded TCP scalar Group (tcpipstats)\n")); |
| } |
| return ret_value; |
| } |
| #elif defined(TCPSTAT_SYMBOL) |
| int |
| tcp_load(netsnmp_cache *cache, void *vmagic) |
| { |
| long ret_value = -1; |
| |
| if (auto_nlist(TCPSTAT_SYMBOL, (char *)&tcpstat, sizeof(tcpstat))) |
| ret_value = 0; |
| |
| if ( ret_value < 0 ) { |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP scalar Group (tcpstat)\n")); |
| } else { |
| DEBUGMSGTL(("mibII/tcpScalar", "Loaded TCP scalar Group (tcpstat)\n")); |
| } |
| return ret_value; |
| } |
| #else /* TCPSTAT_SYMBOL */ |
| int |
| tcp_load(netsnmp_cache *cache, void *vmagic) |
| { |
| long ret_value = -1; |
| |
| DEBUGMSGTL(("mibII/tcpScalar", "Failed to load TCP scalar Group (null)\n")); |
| return ret_value; |
| } |
| #endif /* WIN32 cygwin */ |
| |
| |
| void |
| tcp_free(netsnmp_cache *cache, void *magic) |
| { |
| #if defined(_USE_FIRST_PROTOCOL) |
| memset(&ps_proto, 0, sizeof(ps_proto)); |
| #else |
| memset(&tcpstat, 0, sizeof(tcpstat)); |
| #endif |
| } |
| |