Mercurial > ecos
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
