tcp.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:19k
- /*
- * 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_SYS_SOCKETVAR_H
- #include <sys/socketvar.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
- /*********************
- *
- * 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)
- */
- #if defined (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;
- /*
- * register ourselves with the agent as a group of scalars...
- */
- DEBUGMSGTL(("mibII/tcpScalar", "Initialising TCP scalar groupn"));
- reginfo = netsnmp_create_handler_registration("tcp", tcp_handler,
- tcp_oid, OID_LENGTH(tcp_oid), HANDLER_CAN_RONLY);
- netsnmp_register_scalar_group(reginfo, TCPRTOALGORITHM, TCPOUTRSTS);
- /*
- * .... 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");
- #ifdef TCPSTAT_SYMBOL
- auto_nlist(TCPSTAT_SYMBOL, 0, 0);
- #endif
- #ifdef TCP_SYMBOL
- auto_nlist(TCP_SYMBOL, 0, 0);
- #endif
- #if freebsd4
- hz = sysconf(_SC_CLK_TCK); /* get ticks/s from system */
- #endif
- #ifdef solaris2
- init_kernel_sunos5();
- #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
- #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
- #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
- */
- #ifndef hpux11
- if (!netsnmp_cache_is_valid(reqinfo, reginfo->handlerName)) {
- netsnmp_assert("cache" == "valid"); /* always false */
- tcp_load( NULL, NULL ); /* XXX - check for failure */
- }
- #endif
- /*
- *
- *
- */
- DEBUGMSGTL(("mibII/tcpScalar", "Handler - mode %sn",
- 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;
- break;
- case TCPOUTSEGS:
- ret_value = tcpstat.tcpOutSegs;
- 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;
- #else /* solaris2 */
- #ifdef 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 /* linux */
- #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;
- #else /* USES_SNMP_DESIGNED_TCPSTAT */
- #ifdef USES_TRADITIONAL_TCPSTAT
- #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;
- 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;
- 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
- #else /* USES_TRADITIONAL_TCPSTAT */
- #ifdef 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;
- #else /* hpux11 */
- #if 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;
- #endif /* WIN32 cygwin */
- #endif /* hpux11 */
- #endif /* USES_TRADITIONAL_TCPSTAT */
- #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 */
- }
- #else /* hpux11 */
- #ifdef 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;
- }
- #else /* linux */
- #ifdef 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;
- }
- #else /* solaris2 */
- #if 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;
- }
- #else /* WIN32 cygwin */
- #if (defined(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;
- }
- #else /* (defined(CAN_USE_SYSCTL) && defined(TCPCTL_STATS)) */
- #ifdef 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;
- }
- #else /* HAVE_SYS_TCPIPSTATS_H */
- #ifdef 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 /* TCPSTAT_SYMBOL */
- #endif /* HAVE_SYS_TCPIPSTATS_H */
- #endif /* (defined(CAN_USE_SYSCTL) && defined(TCPCTL_STATS)) */
- #endif /* hpux11 */
- #endif /* linux */
- #endif /* solaris2 */
- #endif /* WIN32 cygwin */
- void
- tcp_free(netsnmp_cache *cache, void *magic)
- {
- memset(&tcpstat, 0, sizeof(tcpstat));
- }