829 lines
21 KiB
C
829 lines
21 KiB
C
|
|
/*
|
|
* TCP MIB group implementation - tcp.c
|
|
*
|
|
*/
|
|
|
|
#include <net-snmp/net-snmp-config.h>
|
|
#include <net-snmp/net-snmp-features.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 <net-snmp/agent/sysORTable.h>
|
|
|
|
#include "util_funcs/MIB_STATS_CACHE_TIMEOUT.h"
|
|
#include "tcp.h"
|
|
#include "tcpTable.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(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_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
|
|
|
|
/*********************
|
|
*
|
|
* 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
|
|
|
|
#ifdef HAVE_IPHLPAPI_H
|
|
#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;
|
|
}
|
|
#elif defined(solaris2)
|
|
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 NETSNMP_FEATURE_CHECKING
|
|
netsnmp_feature_want(tcp_count_connections)
|
|
#endif
|
|
#ifndef NETSNMP_FEATURE_REMOVE_TCP_COUNT_CONNECTIONS
|
|
ret_value = TCP_Count_Connections();
|
|
#else
|
|
ret_value = 0;
|
|
#endif /* NETSNMP_FEATURE_REMOVE_TCP_COUNT_CONNECTIONS */
|
|
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 HAVE_STRUCT_TCPSTAT_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:
|
|
#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/tcp: Unsupported mode (%d)\n",
|
|
reqinfo->mode);
|
|
break;
|
|
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
|
|
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
|
|
}
|
|
|