diff packages/net/snmp/agent/current/src/mibgroup/mibII/tcp.c @ 103:95f3e12a6327 ecos-sw-2000-06-23

Merge from eCos master repository on 2000-06-23-16:41:10-BST
author jlarmour
date Fri, 23 Jun 2000 17:06:31 +0000
parents
children e0c0827131d1
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/tcp.c
@@ -0,0 +1,646 @@
+//==========================================================================
+//
+//      snmp/snmpagent/current/src/mibgroup/mibII/tcp.c
+//
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//####UCDSNMPCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from the UCD-SNMP
+// project,  <http://ucd-snmp.ucdavis.edu/>  from the University of
+// California at Davis, which was originally based on the Carnegie Mellon
+// University SNMP implementation.  Portions of this software are therefore
+// covered by the appropriate copyright disclaimers included herein.
+//
+// The release used was version 4.1.2 of May 2000.  "ucd-snmp-4.1.2"
+// -------------------------------------------
+//
+//####UCDSNMPCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    hmt
+// Contributors: hmt
+// Date:         2000-05-30
+// Purpose:      Port of UCD-SNMP distribution to eCos.
+// Description:  
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+/********************************************************************
+       Copyright 1989, 1991, 1992 by Carnegie Mellon University
+ 
+                          Derivative Work -
+Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
+ 
+                         All Rights Reserved
+ 
+Permission to use, copy, modify and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appears in all copies and
+that both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of CMU and The Regents of
+the University of California not be used in advertising or publicity
+pertaining to distribution of the software without specific written
+permission.
+ 
+CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL CMU OR
+THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
+INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*********************************************************************/
+/* This file was generated by mib2c and is intended for use as a mib module
+   for the ucd-snmp snmpd agent. */
+
+
+/* This should always be included first before anything else */
+#include <config.h>
+
+
+/* minimal include directives */
+#include "mibincl.h"
+#include "mibgroup/util_funcs.h"
+#include "mibgroup/mibII/tcp.h"
+
+#include <sys/protosw.h>
+
+#define _KERNEL
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+//#define	TCPOUTFLAGS
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_debug.h>
+
+/* 
+ * tcp_variables_oid:
+ *   this is the top level oid that we want to register under.  This
+ *   is essentially a prefix, with the suffix appearing in the
+ *   variable below.
+ */
+
+
+oid tcp_variables_oid[] = { 1,3,6,1,2,1,6 };
+
+
+/* 
+ * variable4 tcp_variables:
+ *   this variable defines function callbacks and type return information 
+ *   for the tcp mib section 
+ */
+
+
+struct variable4 tcp_variables[] = {
+/*  magic number        , variable type , ro/rw , callback fn  , L, oidsuffix */
+#define   TCPRTOALGORITHM       1
+  { TCPRTOALGORITHM     , ASN_INTEGER   , RONLY , var_tcp, 1, { 1 } },
+#define   TCPRTOMIN             2
+  { TCPRTOMIN           , ASN_INTEGER   , RONLY , var_tcp, 1, { 2 } },
+#define   TCPRTOMAX             3
+  { TCPRTOMAX           , ASN_INTEGER   , RONLY , var_tcp, 1, { 3 } },
+#define   TCPMAXCONN            4
+  { TCPMAXCONN          , ASN_INTEGER   , RONLY , var_tcp, 1, { 4 } },
+#define   TCPACTIVEOPENS        5
+  { TCPACTIVEOPENS      , ASN_COUNTER   , RONLY , var_tcp, 1, { 5 } },
+#define   TCPPASSIVEOPENS       6
+  { TCPPASSIVEOPENS     , ASN_COUNTER   , RONLY , var_tcp, 1, { 6 } },
+#define   TCPATTEMPTFAILS       7
+  { TCPATTEMPTFAILS     , ASN_COUNTER   , RONLY , var_tcp, 1, { 7 } },
+#define   TCPESTABRESETS        8
+  { TCPESTABRESETS      , ASN_COUNTER   , RONLY , var_tcp, 1, { 8 } },
+#define   TCPCURRESTAB          9
+  { TCPCURRESTAB        , ASN_GAUGE     , RONLY , var_tcp, 1, { 9 } },
+#define   TCPINSEGS             10
+  { TCPINSEGS           , ASN_COUNTER   , RONLY , var_tcp, 1, { 10 } },
+#define   TCPOUTSEGS            11
+  { TCPOUTSEGS          , ASN_COUNTER   , RONLY , var_tcp, 1, { 11 } },
+#define   TCPRETRANSSEGS        12
+  { TCPRETRANSSEGS      , ASN_COUNTER   , RONLY , var_tcp, 1, { 12 } },
+#define   TCPCONNSTATE          15
+  { TCPCONNSTATE        , ASN_INTEGER   , RWRITE, var_tcpConnTable, 3, { 13,1,1 } },
+#define   TCPCONNLOCALADDRESS   16
+  { TCPCONNLOCALADDRESS , ASN_IPADDRESS , RONLY , var_tcpConnTable, 3, { 13,1,2 } },
+#define   TCPCONNLOCALPORT      17
+  { TCPCONNLOCALPORT    , ASN_INTEGER   , RONLY , var_tcpConnTable, 3, { 13,1,3 } },
+#define   TCPCONNREMADDRESS     18
+  { TCPCONNREMADDRESS   , ASN_IPADDRESS , RONLY , var_tcpConnTable, 3, { 13,1,4 } },
+#define   TCPCONNREMPORT        19
+  { TCPCONNREMPORT      , ASN_INTEGER   , RONLY , var_tcpConnTable, 3, { 13,1,5 } },
+#define   TCPINERRS             20
+  { TCPINERRS           , ASN_COUNTER   , RONLY , var_tcp, 1, { 14 } },
+#define   TCPOUTRSTS            21
+  { TCPOUTRSTS          , ASN_COUNTER   , RONLY , var_tcp, 1, { 15 } },
+//#define   IPV6TCPCONNSTATE      29
+//  { IPV6TCPCONNSTATE    , ASN_INTEGER   , RWRITE, var_ipv6TcpConnTable, 3, { 16,1,6 } },
+
+};
+/*    (L = length of the oidsuffix) */
+
+
+/*
+ * init_tcp():
+ *   Initialization routine.  This is called when the agent starts up.
+ *   At a minimum, registration of your variables should take place here.
+ */
+void init_tcp(void) {
+
+
+  /* register ourselves with the agent to handle our mib tree */
+  REGISTER_MIB("tcp", tcp_variables, variable4,
+               tcp_variables_oid);
+
+
+  /* place any other initialization junk you need here */
+}
+
+
+/*
+ * var_tcp():
+ *   This function is called every time the agent gets a request for
+ *   a scalar variable that might be found within your mib section
+ *   registered above.  It is up to you to do the right thing and
+ *   return the correct value.
+ *     You should also correct the value of "var_len" if necessary.
+ *
+ *   Please see the documentation for more information about writing
+ *   module extensions, and check out the examples in the examples
+ *   and mibII directories.
+ */
+unsigned char *
+var_tcp(struct variable *vp, 
+                oid     *name, 
+                size_t  *length, 
+                int     exact, 
+                size_t  *var_len, 
+                WriteMethod **write_method)
+{
+    static long long_ret;
+
+    if (header_generic(vp,name,length,exact,var_len,write_method)
+        == MATCH_FAILED )
+        return NULL;
+
+    switch(vp->magic) {
+
+    case TCPRTOALGORITHM:
+        long_ret = 1; // meaning "other"
+        return (unsigned char *) &long_ret;
+
+    case TCPRTOMIN:
+        long_ret = TCPTV_MIN / PR_SLOWHZ * 1000;;
+        return (unsigned char *) &long_ret;
+
+    case TCPRTOMAX:
+        long_ret = TCPTV_REXMTMAX / PR_SLOWHZ * 1000;;
+        return (unsigned char *) &long_ret;
+
+    case TCPMAXCONN:
+        long_ret = -1; // It is dynamic.
+        return (unsigned char *) &long_ret;
+
+    case TCPACTIVEOPENS:
+        long_ret = tcpstat.tcps_connattempt;
+        return (unsigned char *) &long_ret;
+
+    case TCPPASSIVEOPENS:
+        long_ret = tcpstat.tcps_accepts;
+        return (unsigned char *) &long_ret;
+
+    case TCPATTEMPTFAILS:
+        long_ret = tcpstat.tcps_conndrops;
+        return (unsigned char *) &long_ret;
+
+    case TCPESTABRESETS:
+        long_ret = tcpstat.tcps_drops;
+        return (unsigned char *) &long_ret;
+
+    case TCPCURRESTAB: {
+        struct inpcb *inp;
+        long_ret = 0;
+        for (inp = tcbtable.inpt_queue.cqh_first;
+             inp != (struct inpcb *)&tcbtable.inpt_queue;
+             inp = inp->inp_queue.cqe_next) {
+            struct tcpcb *tp = intotcpcb( inp );
+            if ( tp && (TCPS_ESTABLISHED == tp->t_state ||
+                        TCPS_CLOSE_WAIT  == tp->t_state) )
+                long_ret++;
+        }
+        return (unsigned char *) &long_ret;
+    }
+
+    case TCPINSEGS:
+        long_ret = tcpstat.tcps_rcvtotal;
+        return (unsigned char *) &long_ret;
+
+    case TCPOUTSEGS:
+        long_ret = tcpstat.tcps_sndtotal - tcpstat.tcps_sndrexmitpack;
+        if ( long_ret < 0 )
+            long_ret = 0;
+        return (unsigned char *) &long_ret;
+
+    case TCPRETRANSSEGS:
+        long_ret = tcpstat.tcps_sndrexmitpack;
+        return (unsigned char *) &long_ret;
+
+    case TCPINERRS:
+        long_ret = tcpstat.tcps_rcvbadsum
+            + tcpstat.tcps_rcvbadoff
+            + tcpstat.tcps_rcvshort
+            + tcpstat.tcps_rcvmemdrop; // Is that last one an input error?
+        return (unsigned char *) &long_ret;
+
+    case TCPOUTRSTS:
+        long_ret = tcpstat.tcps_sndctrl - tcpstat.tcps_closed;
+        if ( long_ret < 0 )
+            long_ret = 0;
+        return (unsigned char *) &long_ret;
+
+    default:
+      ERROR_MSG("");
+  }
+  return NULL;
+}
+
+
+
+
+/*
+ * var_tcpConnTable():
+ *   Handle this table separately from the scalar value case.
+ *   The workings of this are basically the same as for var_tcpConnTable above.
+ */
+unsigned char *
+var_tcpConnTable(struct variable *vp,
+    	    oid     *name,
+    	    size_t  *length,
+    	    int     exact,
+    	    size_t  *var_len,
+    	    WriteMethod **write_method)
+{
+    static long long_ret;
+    static unsigned char string[SPRINT_MAX_LEN];
+    register struct inpcb *inp;
+    register struct inpcb *low_inp = NULL;
+    oid                    lowest[24];
+    oid                    newname[24];
+    u_char		   *cp;
+    oid			   *op;
+    struct tcpcb *tp;
+
+    // This is indexed by local-address, local-port, remote-address, remport
+    // at 1,3,6,1,2,1,6,13,1
+    // so we get 1,3,6,1,2,1,6,13,1,?,A,B,C,D,lport,P,Q,R,S,rport
+    // initial length is 10, out-length is 20,
+    // Local address is offsets 10-13, port is offset 14.
+    // Remote address is offsets 15-18, port is offset 19.
+    
+    // starting from udbtable, look in
+    //      low_pcb->inp_laddr.s_addr
+    // and  low_pcb->inp_lport
+    // /_l/_f/ for foreign port,address.
+
+    /* fill in object part of name for current (less sizeof instance part) */
+    memcpy((char *)newname, (char *)vp->name, (int)vp->namelen * sizeof(oid));
+
+    for (inp = tcbtable.inpt_queue.cqh_first;
+         inp != (struct inpcb *)&tcbtable.inpt_queue;
+         inp = inp->inp_queue.cqe_next) {
+
+        cp = (u_char *)&inp->inp_laddr.s_addr;
+        op = newname + 10;
+        *op++ = *cp++;
+        *op++ = *cp++;
+        *op++ = *cp++;
+        *op++ = *cp++;
+        
+        newname[14] = ntohs(inp->inp_lport);
+
+        cp = (u_char *)&inp->inp_faddr.s_addr;
+        op = newname + 15;
+        *op++ = *cp++;
+        *op++ = *cp++;
+        *op++ = *cp++;
+        *op++ = *cp++;
+        
+        newname[19] = ntohs(inp->inp_fport);
+
+        if (exact){
+            if (snmp_oid_compare(newname, 20, name, *length) == 0){
+                memcpy( (char *)lowest,(char *)newname, 20 * sizeof(oid));
+                low_inp = inp;
+                break;  /* no need to search further */
+            }
+        } else {
+            if ((snmp_oid_compare(newname, 20, name, *length) > 0) &&
+                (!low_inp || (snmp_oid_compare(newname, 20, lowest, 20) < 0))){
+                /*
+                 * if new one is greater than input and closer to input than
+                 * previous lowest, save this one as the "next" one.
+                 */
+                memcpy( (char *)lowest,(char *)newname, 20 * sizeof(oid));
+                low_inp = inp;
+            }
+        }
+    }
+
+    if ( ! low_inp )
+        return NULL;
+
+    tp = intotcpcb( low_inp );
+    if ( ! tp )
+        return NULL; // Shouldn't happen
+
+    memcpy( (char *)name,(char *)lowest, 20 * sizeof(oid));
+    *length = 20;
+    *var_len = sizeof( long_ret );
+    *write_method = 0;
+    
+    switch(vp->magic) {
+    case TCPCONNSTATE:
+        // NOTSUPPORTED: *write_method = write_tcpConnState;
+        switch ( tp->t_state ) {
+        case TCPS_CLOSED	: // 0	/* closed */
+            long_ret = 1; break;
+        case TCPS_LISTEN	: // 1	/* listening for connection */
+            long_ret = 2; break;
+        case TCPS_SYN_SENT	: // 2	/* active, have sent syn */
+            long_ret = 3; break;
+        case TCPS_SYN_RECEIVED	: // 3	/* have sent and received syn */
+            long_ret = 4; break;
+        case TCPS_ESTABLISHED	: // 4	/* established */
+            long_ret = 5; break;
+        case TCPS_CLOSE_WAIT	: // 5	/* rcvd fin, waiting for close */
+            long_ret = 8; break;
+        case TCPS_FIN_WAIT_1	: // 6	/* have closed, sent fin */
+            long_ret = 6; break;
+        case TCPS_CLOSING	: // 7	/* closed xchd FIN; await ACK */
+            long_ret = 10; break;
+        case TCPS_LAST_ACK	: // 8	/* had fin and close; await FIN ACK */
+            long_ret = 9; break;
+        case TCPS_FIN_WAIT_2	: // 9	/* have closed, fin is acked */
+            long_ret = 7; break;
+        case TCPS_TIME_WAIT	: // 10	/* in 2*msl quiet wait after close */
+            long_ret = 11; break;
+        default:
+            long_ret = 1;
+        }
+        return (unsigned char *) &long_ret;
+
+    case TCPCONNLOCALADDRESS:
+        cp = (u_char *)&low_inp->inp_laddr.s_addr;
+        string[0] = *cp++;
+        string[1] = *cp++;
+        string[2] = *cp++;
+        string[3] = *cp++;
+        *var_len = 4;
+        return (unsigned char *) string;
+
+    case TCPCONNLOCALPORT:
+        long_ret = (long)ntohs(low_inp->inp_lport);
+        return (unsigned char *) &long_ret;
+
+    case TCPCONNREMADDRESS:
+        cp = (u_char *)&low_inp->inp_faddr.s_addr;
+        string[0] = *cp++;
+        string[1] = *cp++;
+        string[2] = *cp++;
+        string[3] = *cp++;
+        *var_len = 4;
+        return (unsigned char *) string;
+
+    case TCPCONNREMPORT:
+        long_ret = (long)ntohs(low_inp->inp_fport);
+        return (unsigned char *) &long_ret;
+
+    default:
+        ERROR_MSG("");
+    }
+    return NULL;
+}
+
+
+#if 0 // NOTSUPPORTED:
+int
+write_tcpConnState(int      action,
+            u_char   *var_val,
+            u_char   var_val_type,
+            size_t   var_val_len,
+            u_char   *statP,
+            oid      *name,
+            size_t   name_len)
+{
+  static long *long_ret;
+  int size;
+
+
+  switch ( action ) {
+        case RESERVE1:
+          if (var_val_type != ASN_INTEGER){
+              fprintf(stderr, "write to tcpConnState not ASN_INTEGER\n");
+              return SNMP_ERR_WRONGTYPE;
+          }
+          if (var_val_len > sizeof(long_ret)){
+              fprintf(stderr,"write to tcpConnState: bad length\n");
+              return SNMP_ERR_WRONGLENGTH;
+          }
+          break;
+
+
+        case RESERVE2:
+          size = var_val_len;
+          long_ret = (long *) var_val;
+
+
+          break;
+
+
+        case FREE:
+             /* Release any resources that have been allocated */
+          break;
+
+
+        case ACTION:
+             /* The variable has been stored in long_ret for
+             you to use, and you have just been asked to do something with
+             it.  Note that anything done here must be reversable in the UNDO case */
+          break;
+
+
+        case UNDO:
+             /* Back out any changes made in the ACTION case */
+          break;
+
+
+        case COMMIT:
+             /* Things are working well, so it's now safe to make the change
+             permanently.  Make sure that anything done here can't fail! */
+          break;
+  }
+  return SNMP_ERR_NOERROR;
+}
+
+#endif
+
+
+
+
+#if 0 // NOTSUPPORTED:
+/*
+ * var_ipv6TcpConnTable():
+ *   Handle this table separately from the scalar value case.
+ *   The workings of this are basically the same as for var_tcp above.
+ */
+unsigned char *
+var_ipv6TcpConnTable(struct variable *vp,
+    	    oid     *name,
+    	    size_t  *length,
+    	    int     exact,
+    	    size_t  *var_len,
+    	    WriteMethod **write_method)
+{
+
+
+  /* variables we may use later */
+  static long long_ret;
+  static unsigned char string[SPRINT_MAX_LEN];
+  static oid objid[MAX_OID_LEN];
+  static struct counter64 c64;
+
+
+  /* 
+   * This assumes that the table is a 'simple' table.
+   *	See the implementation documentation for the meaning of this.
+   *	You will need to provide the correct value for the TABLE_SIZE parameter
+   *
+   * If this table does not meet the requirements for a simple table,
+   *	you will need to provide the replacement code yourself.
+   *	Mib2c is not smart enough to write this for you.
+   *    Again, see the implementation documentation for what is required.
+   */
+//  if (header_simple_table(vp,name,length,exact,var_len,write_method,
+//                          IPV6TCPCONNTABLE_TABLE_SIZE)
+//                                                == MATCH_FAILED )
+    return NULL;
+
+
+  /* 
+   * this is where we do the value assignments for the mib results.
+   */
+  switch(vp->magic) {
+
+
+    case IPV6TCPCONNSTATE:
+        *write_method = write_ipv6TcpConnState;
+        long_ret = 0;
+        return (unsigned char *) &long_ret;
+
+
+    default:
+      ERROR_MSG("");
+  }
+  return NULL;
+}
+
+
+
+
+int
+write_ipv6TcpConnState(int      action,
+            u_char   *var_val,
+            u_char   var_val_type,
+            size_t   var_val_len,
+            u_char   *statP,
+            oid      *name,
+            size_t   name_len)
+{
+  static long *long_ret;
+  int size;
+
+
+  switch ( action ) {
+        case RESERVE1:
+          if (var_val_type != ASN_INTEGER){
+              fprintf(stderr, "write to tcpConnState not ASN_INTEGER\n");
+              return SNMP_ERR_WRONGTYPE;
+          }
+          if (var_val_len > sizeof(long_ret)){
+              fprintf(stderr,"write to tcpConnState: bad length\n");
+              return SNMP_ERR_WRONGLENGTH;
+          }
+          break;
+
+
+        case RESERVE2:
+          size = var_val_len;
+          long_ret = (long *) var_val;
+
+
+          break;
+
+
+        case FREE:
+             /* Release any resources that have been allocated */
+          break;
+
+
+        case ACTION:
+             /* The variable has been stored in long_ret for
+             you to use, and you have just been asked to do something with
+             it.  Note that anything done here must be reversable in the UNDO case */
+          break;
+
+
+        case UNDO:
+             /* Back out any changes made in the ACTION case */
+          break;
+
+
+        case COMMIT:
+             /* Things are working well, so it's now safe to make the change
+             permanently.  Make sure that anything done here can't fail! */
+          break;
+  }
+  return SNMP_ERR_NOERROR;
+}
+
+#endif // NOTSUPPORTED: ipv6
+
+// EOF tcp.c