Files
m241Neelima/components/ip_net2-6.9/vxcompat/src/m2Ipv6TcpLib.c
T
2026-07-30 11:19:44 +05:30

600 lines
20 KiB
C

/* m2Ipv6TcpLib.c - MIB-II IPv6 TCP-group API for SNMP agents */
/*
* Copyright (c) 1984-2005 Wind River Systems, Inc.
*
* The right to copy, distribute or otherwise make use of this software
* may be licensed only pursuant to the terms of an applicable Wind River
* license agreement. No license to Wind River intellectual property rights
* is granted herein. All rights not licensed by Wind River are reserved
* by Wind River.
*/
/*
modification history
--------------------
01n,11apr05,sar Removed hz as it wasn't being used.
01m,25feb05,niq fix compiler warnings
01l,12jan05,vvv osdep.h cleanup
01k,26aug04,niq unified stack merge
01j,02jun04,rp removed extern declaration of fdTable
01i,23apr04,rp ported changes from m2TcpLib.c ver 01u
01h,02feb04,pas fixed header paths
01g,05deco3,xli change include path
01f,20nov03,niq osdep.h cleanup
01d,06nov03,rlm Ran batch header update for header re-org.
01c,08sep03,vvv merged from ACCORDION_BASE6_MERGE_BASELINE
01b,11jul02,qli provide vxworks version guard on fdTable
01a,20mar02,ant taken from m2TcpLib.c
*/
/*
DESCRIPTION
This library provides MIB-II services for the TCP group for IPv6. It provides
routines to initialize the group, read the table of IPv6 TCP connections, and
change the state of a IPv6 TCP connection. For a broader description of IPv6
MIB-II services, see the manual entry for m2Ipv6Lib.
To use this feature, include the following component:
INCLUDE_MIB2_TCPV6
USING THIS LIBRARY
This library can be initialized and deleted by calling m2Ipv6TcpInit() and
m2Ipv6TcpDelete() respectively, if only the IPv6 TCP group's services are needed.
If full IPv6 MIB-II support is used, this group and all other groups can be
initialized and deleted by calling m2Ipv6Init() and m2Ipv6Delete().
The IPv6 TCP table of connections can be accessed in lexicographical order. The
first entry in the table can be accessed by setting the table index to
zero. Every other entry thereafter can be accessed by passing to
m2Ipv6TcpConnEntryGet() the index retrieved in the previous invocation
by giving M2_NEXT_VALUE as the search parameter. For example:
.CS
M2_IPV6TCPCONNTBL tcpEntry;
/@ Specify a zero index to get the first entry in the table @/
/@ Local IPv6 address in host byte order @/
memset (tcpEntry.ipv6tcpConnLocalAddress, 0, sizeof (struct in6_addr));
tcpEntry.ipv6tcpConnLocalPort = 0; /@ local TCP port in host byte order @/
/@ Remote IPv6 address in host byte order @/
memset (tcpEntry.ipv6tcpConnRemAddress, 0, sizeof (struct in6_addr));
tcpEntry.ipv6tcpConnRemPort = 0; /@ remote TCP port in host byte order @/
/@ get the first entry in the table @/
if ((m2Ipv6TcpConnEntryGet (M2_NEXT_VALUE, &tcpEntry) == OK)
/@ values in tcpEntry in the first entry are valid @/
/@ process first entry in the table @/
/@ get the second entry in the table @/
if ((m2Ipv6TcpConnEntryGet (M2_NEXT_VALUE, &tcpEntry) == OK)
/@ values in tcpEntry in the second entry are valid @/
.CE
The IPv6 TCP table of connections allows only for a connection to be deleted as
specified in the MIB-II. For example:
.CS
M2_IPV6TCPCONNTBL tcpEntry;
char tcpLocalAddr[] = "3000::40";
char tcpRemAddr[] = "3000::42";
/@ Fill in the index for the connection to be deleted in the table @/
/@ Local IPv6 address in host byte order, and local port number @/
/@ convert a presentation format address to a network format address @/
inet_pton (AF_INET6, tcpLocalAddr, tcpEntry.ipv6tcpConnLocalAddress);
NTOHL_IPV6ADDR (tcpEntry.ipv6tcpConnLocalAddress);
tcpEntry.ipv6tcpConnLocalPort = 3000;
/@ Remote IPv6 address in host byte order, and remote port number @/
/@ convert a presentation format address to a network format address @/
inet_pton (AF_INET6, tcpRemAddr, tcpEntry.ipv6tcpConnRemAddress);
NTOHL_IPV6ADDR (tcpEntry.ipv6tcpConnRemAddress);
tcpEntry.ipv6tcpConnRemPort = 3000;
tcpEntry.ipv6tcpConnState = 12; /@ MIB-II state value for delete @/
/@ set the entry in the table @/
if ((m2Ipv6TcpConnEntrySet (&tcpEntry) == OK)
/@ tcpEntry deleted successfuly @/
.CE
INCLUDE FILES: m2Ipv6Lib.h
SEE ALSO:
m2Ipv6Lib, m2Ipv6IfLib, m2Ipv6IfIcmpLib, m2Ipv6UdpLib, m2Ipv6MldLib
*/
/* includes */
#include <vxWorks.h>
#include <limits.h>
#include <errnoLib.h>
#include <netconf.h>
#include <m2Lib.h>
#include <sys/socket.h>
#include <net/socketvar.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_timer.h>
#include <netinet/in_pcb.h>
#include <netinet6/in6_pcb.h>
#include <net/protosw.h>
#if _WRS_VXWORKS_MAJOR >= 6
# include <iosLib.h> /* base6 */
# include <sockFunc.h>
#else
# include <private/iosLibP.h> /* pre-base6 */
#endif
#include <m2Ipv6Lib.h>
#ifdef VIRTUAL_STACK
#include <netinet/vsLib.h>
#include <netinet/vsTcp.h>
#include <netinet/vsData.h>
#endif
/* defines */
/* MIB-II TCP state definitions */
#define M2TCP_CLOSED 1
#define M2TCP_LISTEN 2
#define M2TCP_SYNSENT 3
#define M2TCP_SYNRECEIVED 4
#define M2TCP_ESTABLISHED 5
#define M2TCP_FINWAIT1 6
#define M2TCP_FINWAIT2 7
#define M2TCP_CLOSEWAIT 8
#define M2TCP_LASTACK 9
#define M2TCP_CLOSING 10
#define M2TCP_TIMEWAIT 11
#define M2TCP_DELETETCB 12
/* globals */
/* external declarations */
#ifndef VIRTUAL_STACK
extern struct inpcbhead tcb; /* defined in tcp_input.c */
#endif /* VIRTUAL_STACK */
/*
* This table maps the BSD TCP states to the MIB-II TCP specified states. The
* table is indexed using the BSD TCP states.
*/
LOCAL long m2TcpStates [TCP_NSTATES] =
{
M2TCP_CLOSED, /* TCPS_CLOSED -> M2TCP_CLOSED */
M2TCP_LISTEN, /* TCPS_LISTEN -> M2TCP_LISTEN */
M2TCP_SYNSENT, /* TCPS_SYN_SENT -> M2TCP_SYNSENT */
M2TCP_SYNRECEIVED, /* TCPS_SYN_RECEIVED -> M2TCP_SYNRECEIVED */
M2TCP_ESTABLISHED, /* TCPS_ESTABLISHED -> M2TCP_ESTABLISHED */
M2TCP_CLOSEWAIT, /* TCPS_CLOSE_WAIT -> M2TCP_CLOSEWAIT */
M2TCP_FINWAIT1, /* TCPS_FIN_WAIT_1 -> M2TCP_FINWAIT1 */
M2TCP_CLOSING, /* TCPS_CLOSING -> M2TCP_CLOSING */
M2TCP_LASTACK, /* TCPS_LAST_ACK -> M2TCP_LASTACK */
M2TCP_FINWAIT2, /* TCPS_FIN_WAIT_2 -> M2TCP_FINWAIT2 */
M2TCP_TIMEWAIT, /* TCPS_TIME_WAIT -> M2TCP_TIMEWAIT */
};
/*******************************************************************************
*
* m2Ipv6TcpInit - initialize MIB-II IPv6 TCP-group access
*
* This routine allocates the resources needed to allow access to the IPv6 MIB-II
* TCP-group variables. This routine must be called before any IPv6 TCP variables
* can be accessed.
*
* RETURNS: OK, always.
*
* SEE ALSO: m2Ipv6TcpConnEntryGet(), m2Ipv6TcpConnEntrySet(), m2Ipv6TcpDelete()
*/
STATUS m2Ipv6TcpInit (void)
{
return (OK);
}
/******************************************************************************
*
* m2Ipv6AddrCmp - compare two ipv6 addresses
*/
LOCAL int m2Ipv6AddrCmp
(
struct in6_addr * addr1,
struct in6_addr * addr2
)
{
int ix;
for (ix = 0; ix < 4; ix++)
{
if (addr1->s6_addr32[ix] > addr2->s6_addr32[ix])
return (1);
else if (addr1->s6_addr32[ix] < addr2->s6_addr32[ix])
return (-1);
}
return (0);
}
/******************************************************************************
*
* m2Ipv6TcpConnCmp - compare two IPv6 TCP connections in lexicographical order
*
* This routine compares two IPv6 TCP connection control blocks. It compares the
* value 1 with value 2. It returns equal, value 1 greater than
* value 2, or value 1 less than value 2. The comparison is done based on the
* lexicographical order specified by MIB-II.
*
* RETURNS: 0 = equal, 1 > greater than, and -1 < less than.
*
* SEE ALSO: N/A
*/
LOCAL int m2Ipv6TcpConnCmp
(
M2_IPV6TCPCONNTBL * pConnVal1, /* pointer to table entry (Compare against) */
M2_IPV6TCPCONNTBL * pConnVal2 /* pointer to table entry (Second entry) */
)
{
int result;
/* Comparison of two IPv6 addresses */
result = m2Ipv6AddrCmp((struct in6_addr *)pConnVal1->ipv6TcpConnLocalAddress,
(struct in6_addr *)pConnVal2->ipv6TcpConnLocalAddress);
if (result > 0)
{
return 1; /* First Entry is Greater */
}
if (result < 0)
{
return -1; /* First Entry is Smaller */
}
/* Comparison of two signed values */
result = pConnVal1->ipv6TcpConnLocalPort - pConnVal2->ipv6TcpConnLocalPort;
if (result != 0)
return (result); /* Value > 0 or < 0 */
/* Comparison of two ipv6 addresses */
result = m2Ipv6AddrCmp((struct in6_addr *)pConnVal1->ipv6TcpConnRemAddress,
(struct in6_addr *)pConnVal2->ipv6TcpConnRemAddress);
if (result > 0)
{
return 1; /* First Entry is Greater */
}
if (result < 0)
{
return -1; /* First Entry is Smaller */
}
/* Comparison of two signed values */
result = pConnVal1->ipv6TcpConnRemPort - pConnVal2->ipv6TcpConnRemPort;
if (result != 0)
return (result); /* Value > 0 or < 0 */
/* Result will determine Equal, Less than or Greater than */
return (pConnVal1->ipv6TcpConnIfIndex - pConnVal2->ipv6TcpConnIfIndex);
}
/******************************************************************************
*
* m2Ipv6TcpConnEntryGet - get a MIB-II IPV6 TCP connection table entry
*
* This routine traverses the IPv6 TCP table and does an M2_EXACT_VALUE or
* a M2_NEXT_VALUE search based on the <search> parameter (see m2Ipv6Lib). The
* calling routine is responsible for supplying a valid MIB-II entry index in
* the input structure <pReqTcpConnEntry>. The index is made up of the local
* IPv6 address, the local port number, the remote IPv6 address, the remote
* port, and the 'ipv6TcpConnIfIndex'. The first entry in the table is retrieved
* by doing a M2_NEXT_VALUE search with the index fields set to zero.
*
* RETURNS:
* OK, or ERROR if the input parameter <pReqTcpConnEntry> is not specified or a
* match is not found.
*
* ERRNO:
* S_m2Lib_INVALID_PARAMETER
* S_m2Lib_ENTRY_NOT_FOUND
*
* SEE ALSO: m2Ipv6TcpInit(), m2Ipv6TcpConnEntrySet(), m2Ipv6TcpDelete(),
* m2Ipv6TcpLib
*/
STATUS m2Ipv6TcpConnEntryGet
(
int search, /* M2_EXACT_VALUE or M2_NEXT_VALUE */
M2_IPV6TCPCONNTBL * pReqTcpConnEntry /* input = Index, Output = Entry */
)
{
M2_IPV6TCPCONNTBL savedEntry; /* Use to save the table entry to return */
M2_IPV6TCPCONNTBL tableEntry; /* Use to test an entry in the table */
int netLock; /* Use to secure the Network Code Access */
struct inpcb * pPcb; /* Pointer to an entry in TCP Connection List */
/* Validate Pointer to IPv6 TCP Table Entry structure */
if (pReqTcpConnEntry == NULL)
{
errnoSet (S_m2Lib_INVALID_PARAMETER);
return (ERROR);
}
/* Setup structure used in the search for the requested TCP entry */
savedEntry.ipv6TcpConnState = TCP_NSTATES; /* Invalid TCP State */
/* Largest local IPv6 Addr */
memset (savedEntry.ipv6TcpConnLocalAddress, 0xff, sizeof (struct in6_addr));
savedEntry.ipv6TcpConnLocalPort = -1; /* Largest local port */
/* Largest Remote IPv6 Addr */
memset (savedEntry.ipv6TcpConnRemAddress, 0xff, sizeof (struct in6_addr));
savedEntry.ipv6TcpConnRemPort = -1; /* Largest Remote Port */
savedEntry.ipv6TcpConnIfIndex = -1; /* Largest ifIndex */
netLock = splnet (); /* Get exclusive access to Network Code */
/*
* Traverse the circular list of TCP control blocks. The first item in the
* list is a dummy header, skip it and used it as the loop exit condition.
*/
for (pPcb = tcb.lh_first; pPcb != NULL; pPcb = pPcb->inp_list.le_next)
{
if ((pPcb->inp_vflag & INP_IPV6) == 0) /* check only IPv6 blocks */
continue;
/* Convert control block format into a more convenient format */
memcpy (tableEntry.ipv6TcpConnLocalAddress, &pPcb->in6p_laddr,
sizeof (struct in6_addr));
NTOHL_IPV6ADDR(tableEntry.ipv6TcpConnLocalAddress);
tableEntry.ipv6TcpConnLocalPort = ntohs(pPcb->inp_lport);
memcpy (tableEntry.ipv6TcpConnRemAddress, &pPcb->in6p_faddr,
sizeof (struct in6_addr));
NTOHL_IPV6ADDR(tableEntry.ipv6TcpConnRemAddress);
tableEntry.ipv6TcpConnRemPort = ntohs(pPcb->inp_fport);
tableEntry.ipv6TcpConnIfIndex = pPcb->inp6_ifindex;
if (search == M2_EXACT_VALUE &&
(m2Ipv6TcpConnCmp(&tableEntry, pReqTcpConnEntry) == 0))
{
/* Match, map the connection state to MIB-II format and exit */
pReqTcpConnEntry->ipv6TcpConnState =
m2TcpStates [((struct tcpcb *) pPcb->inp_ppcb)->t_state];
splx (netLock); /* Give up exclusive access to Network Code */
return (OK);
}
else
{
/*
* A NEXT search is satisfied by an entry that is lexicographicaly
* greater than the input TCP connection entry. Because the TCP
* connection list is not in order, the list must be traverse
* completly before a selection is made. The rules for a
* lexicographical comparison are built in the routine
* m2Ipv6TcpConnCmp().
*/
if ((m2Ipv6TcpConnCmp(&tableEntry, pReqTcpConnEntry) > 0) &&
(m2Ipv6TcpConnCmp(&tableEntry, &savedEntry) < 0))
{
memcpy (savedEntry.ipv6TcpConnLocalAddress, &pPcb->in6p_laddr,
sizeof (struct in6_addr));
NTOHL_IPV6ADDR(savedEntry.ipv6TcpConnLocalAddress);
savedEntry.ipv6TcpConnLocalPort = ntohs(pPcb->inp_lport);
memcpy (savedEntry.ipv6TcpConnRemAddress, &pPcb->in6p_faddr,
sizeof (struct in6_addr));
NTOHL_IPV6ADDR(savedEntry.ipv6TcpConnRemAddress);
savedEntry.ipv6TcpConnRemPort = ntohs(pPcb->inp_fport);
savedEntry.ipv6TcpConnIfIndex = pPcb->inp6_ifindex;
/* Save the connection state in BSD format */
savedEntry.ipv6TcpConnState =
((struct tcpcb *) pPcb->inp_ppcb)->t_state;
}
}
}
splx (netLock); /* Give up exclusive access to Network Code */
if (savedEntry.ipv6TcpConnState == TCP_NSTATES)
{
errnoSet (S_m2Lib_ENTRY_NOT_FOUND);
return (ERROR); /* Requested Entry Not Found */
}
pReqTcpConnEntry->ipv6TcpConnState = m2TcpStates [savedEntry.ipv6TcpConnState];
memcpy (pReqTcpConnEntry->ipv6TcpConnLocalAddress, savedEntry.ipv6TcpConnLocalAddress,
sizeof (struct in6_addr));
pReqTcpConnEntry->ipv6TcpConnLocalPort = savedEntry.ipv6TcpConnLocalPort;
memcpy (pReqTcpConnEntry->ipv6TcpConnRemAddress, savedEntry.ipv6TcpConnRemAddress,
sizeof (struct in6_addr));
pReqTcpConnEntry->ipv6TcpConnRemPort = savedEntry.ipv6TcpConnRemPort;
pReqTcpConnEntry->ipv6TcpConnIfIndex = savedEntry.ipv6TcpConnIfIndex;
return (OK);
}
/******************************************************************************
*
* m2Ipv6TcpConnEntrySet - set a MIB-II IPv6 TCP connection to the closed state
*
* This routine traverses the IPv6 TCP connection table and searches for the
* connection specified in the input parameter <pReqTcpConnEntry>. The
* calling routine is responsible for providing a valid index as the
* input parameter <pReqTcpConnEntry>. The index is made up of the
* local IPv6 address, the local port number, the remote IPv6 address,
* the remote port, and the 'ipv6TcpConnIfIndex'. This call can only succeed
* if the connection is in the MIB-II state "deleteTCB" (12). If a match is
* found, the socket associated with the IPv6 TCP connection is closed.
*
* RETURNS:
* OK, or ERROR if the input parameter is invalid, the state of the
* connection specified at <pReqTcpConnEntry> is not "closed,"
* the specified connection is not found, a socket is not associated
* with the connection, or the close() call fails.
*
* ERRNO:
* S_m2Lib_INVALID_PARAMETER
* S_m2Lib_ENTRY_NOT_FOUND
* S_m2Lib_TCPCONN_FD_NOT_FOUND
*
* SEE ALSO: m2Ipv6TcpInit(), m2Ipv6TcpConnEntryGet(), m2Ipv6TcpDelete(),
* m2Ipv6TcpLib
*/
STATUS m2Ipv6TcpConnEntrySet
(
M2_IPV6TCPCONNTBL * pReqTcpConnEntry /* pointer to TCP connection to close */
)
{
int fdToClose; /* Selected File Descriptor to close */
int netLock; /* Use to secure the Network Code Access */
struct inpcb * pInp; /* Pointer to BSD PCB list */
struct in6_addr loc_addr; /* Local IPv6 Address structure */
struct in6_addr rem_addr; /* Remote IPv6 Address structure */
unsigned short locPort;
unsigned short remPort;
int maxFd;
#ifndef _WRS_VXWORKS_MAJOR /* pre-base6 */
extern int maxFiles;
#endif
/* Validate Pointer to IPv6 TCP Table Entry structure and operation */
if (pReqTcpConnEntry == NULL ||
pReqTcpConnEntry->ipv6TcpConnState != M2TCP_DELETETCB)
{
errnoSet (S_m2Lib_INVALID_PARAMETER);
return (ERROR);
}
/* Look for the Internet Control Block which maps to the TCP Entry */
locPort = pReqTcpConnEntry->ipv6TcpConnLocalPort;
remPort = pReqTcpConnEntry->ipv6TcpConnRemPort;
memcpy (&loc_addr, pReqTcpConnEntry->ipv6TcpConnLocalAddress,
sizeof (struct in6_addr));
HTONL_IPV6ADDR(&loc_addr);
locPort = htons(locPort);
memcpy (&rem_addr, pReqTcpConnEntry->ipv6TcpConnRemAddress,
sizeof (struct in6_addr));
HTONL_IPV6ADDR(&rem_addr);
remPort = htons(remPort);
netLock = splnet (); /* Get exclusive access to Network Code */
/* ifIndex, ipv6TcpConnIfIndex ??? */
if ((pInp = in6_pcblookup_hash (&tcbinfo, &rem_addr,
remPort, &loc_addr, locPort, 0, NULL)) == NULL)
{
splx (netLock); /* Give up exclusive access to Network Code */
errnoSet (S_m2Lib_ENTRY_NOT_FOUND);
return (ERROR); /* Entry not found */
}
splx (netLock); /* Give up exclusive access to Network Code */
#if _WRS_VXWORKS_MAJOR >= 6
maxFd = iosFdMaxFiles (); /* base6 */
#else
maxFd = maxFiles; /* pre-base6 */
#endif
/* Look for the FD to issue close in the File Descriptor Table */
for (fdToClose = 0; fdToClose < maxFd ; fdToClose++)
{
#if _WRS_VXWORKS_MAJOR >= 6
/* base 6 */
if (iosFdDrvValue(fdToClose, socketDevHdr.drvNum)
== (int)pInp->inp_socket)
break;
#else
/* pre-base6 */
if (fdTable [fdToClose].value == (int) pInp->inp_socket)
break;
#endif
}
if (fdToClose >= maxFd)
{
errnoSet (S_m2Lib_TCPCONN_FD_NOT_FOUND);
return (ERROR);
}
/* Issue Close */
#ifndef _WRS_VXWORKS_MAJOR
fdToClose = STD_FIX(fdToClose);
#endif
return (close (fdToClose));
}
/*******************************************************************************
*
* m2Ipv6TcpDelete - delete all resources used to access the IPv6 TCP group
*
* This routine frees all the resources allocated at the time the group was
* initialized. The IPv6 TCP group should not be accessed after this routine has
* been called.
*
* RETURNS: OK, always.
*
* SEE ALSO: m2Ipv6TcpInit(), m2Ipv6TcpConnEntryGet(), m2Ipv6TcpConnEntrySet(),
* m2Ipv6TcpLib
*/
STATUS m2Ipv6TcpDelete (void)
{
return (OK);
}