📄 tcp.c
字号:
return(-1);
}
soc = &tcp_socket[sockethandle]; /* Get socket */
buf_start = buf;
if( (dlen + MIN_TCP_HLEN) > soc->send_mtu ) {
TCP_DEBUGOUT("ERROR:Send MTU exceeded\r\n");
return(-1);
}
/* Assemble TCP header to buffer */
*buf++ = (UINT8)(soc->locport >> 8);
*buf++ = (UINT8)soc->locport;
*buf++ = (UINT8)(soc->remport >> 8);
*buf++ = (UINT8)soc->remport;
*buf++ = (UINT8)(soc->send_unacked >>24);
*buf++ = (UINT8)(soc->send_unacked >>16);
*buf++ = (UINT8)(soc->send_unacked >>8);
*buf++ = (UINT8)(soc->send_unacked);
*buf++ = (UINT8)(soc->receive_next >>24);
*buf++ = (UINT8)(soc->receive_next >>16);
*buf++ = (UINT8)(soc->receive_next >>8);
*buf++ = (UINT8)(soc->receive_next);
*buf = MIN_TCP_HLEN >> 2;
*buf <<= 4;
buf++;
*buf++ = soc->myflags;
*buf++ = (UINT8)(TCP_DEF_MTU >> 8);
*buf++ = (UINT8)TCP_DEF_MTU;
*buf++ = 0; /* Checksum */
*buf++ = 0;
*buf++ = 0; /* Urgent */
*buf++ = 0;
/* Calculate checksum */
cs = 0;
cs_cnt = 0;
/* Do it firstly to IP pseudo header */
#if defined (IPv6)
for (i=0; i<(1*sizeof(struct _in6_addr)); i++)
{
cs = ip_checksum(cs, (UINT8)(LocalIP.u.byte[i]), cs_cnt++);
}
for (i=0; i<(1*sizeof(struct _in6_addr)); i++)
cs = ip_checksum(cs, (UINT8)(soc->rem_ip->u.byte[i]), cs_cnt++);
#else
cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 24), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 16), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 8), cs_cnt++);
cs = ip_checksum(cs, (UINT8)localmachine.localip, cs_cnt++);
cs = ip_checksum(cs, (UINT8)(soc->rem_ip >> 24), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(soc->rem_ip >> 16), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(soc->rem_ip >> 8), cs_cnt++);
cs = ip_checksum(cs, (UINT8)soc->rem_ip, cs_cnt++);
#endif
cs = ip_checksum(cs, 0, cs_cnt++);
cs = ip_checksum(cs, (UINT8)IP_TCP, cs_cnt++);
cs = ip_checksum(cs, (UINT8)((dlen + MIN_TCP_HLEN) >> 8), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(dlen + MIN_TCP_HLEN), cs_cnt++);
/* Go to TCP header + data */
buf = buf_start;
cs = ip_checksum_buf(cs, buf, dlen + MIN_TCP_HLEN);
cs = ~ cs;
#if 0
/* Is the padding required? */
if(dlen & 0x01) {
TCP_DEBUGOUT("Padding required\r\n");
*buf = 0;
dlen++;
}
#endif
/* Save checksum in correct place */
buf = buf_start + 16;
*buf++ = (UINT8)(cs >> 8);
*buf = (UINT8)cs;
/* Send it to IP */
TCP_DEBUGOUT("Sending TCP...\r\n");
#ifdef IPv6
process_ip_out(soc->rem_ip, IP_TCP, soc->tos, 100, buf_start, dlen + MIN_TCP_HLEN);
#else
process_ip_out(soc->rem_ip, IP_TCP, soc->tos, 100, buf_start, dlen + MIN_TCP_HLEN);
#endif
TCP_DEBUGOUT("TCP packet sent\r\n");
return(0);
}
/** \brief Send a TCP control packet (no data)
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 17.07.2002
* \param sockethandle handle to socket
*
* This function is used to initiate sending of a control (no data) TCP
* packet. Important thing in these packets are the flags and sequence
* numbers they carry.
*
*/
void tcp_sendcontrol (INT8 sockethandle)
{
// UINT8 i;
TCP_DEBUGOUT("Entering to send TCP control packet\r\n");
kick_WD();
if( sockethandle < 0 ) {
TCP_DEBUGOUT("ERROR:Socket Handle not valid (<0)\r\n");
return;
}
if( sockethandle > NO_OF_TCPSOCKETS ) {
TCP_DEBUGOUT("ERROR:Socket Handle not valid (>NO_OF_TCPSOCKETS)\r\n");
return;
}
process_tcp_out(sockethandle, &tcp_tempbuf[0], MIN_TCP_HLEN + 1, 0);
return;
}
/** \brief Send a reset (RST) packet to remote host
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \li Vladan Jovanovic (vladan.jovanovic@violasystems.com)
* \date 20.08.2002
* \param frame pointer to received TCP packet
* \param remip remote IP address of packet
*
* Uses socket #NO_OF_TCPSOCKETS to send a RESET packet to peer.
* This function is used when we are establishing connection but
* we receive something else than SYN or SYN+ACK when it's
* possible that the peer has still old connection on which
* needs to be resetted without canceling the connection establishment
* on process.
*/
#if defined(IPv6)
void tcp_sendreset (struct tcp_frame *frame, struct _in6_addr remip)
{
}
#else
void tcp_sendreset (struct tcp_frame *frame, UINT32 remip)
{
struct tcb* soc;
soc = &tcp_socket[NO_OF_TCPSOCKETS]; /* Get socket */
/* Is this itself a reset packet? */
if( frame->hlen_flags & TCP_FLAG_RESET )
return;
/* Set temporary tcb variables */
soc->rem_ip = remip;
soc->remport = frame->sport;
soc->locport = frame->dport;
soc->tos = 0;
/* Does the packet have ACK flag set? */
if( frame->hlen_flags & TCP_FLAG_ACK ) {
/* Jup, use it as our seq */
soc->send_unacked = frame->ackno;
soc->myflags = TCP_FLAG_RESET;
soc->receive_next = frame->seqno;
} else {
soc->send_unacked = 0;
soc->myflags = TCP_FLAG_RESET | TCP_FLAG_ACK;
soc->receive_next = frame->seqno+1;
}
soc->send_mtu = TCP_DEF_MTU;
tcp_sendcontrol(NO_OF_TCPSOCKETS);
}
#endif
/** \brief Get and return initial sequence number
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 17.07.2002
* \return UINT32 number containing initial sequence number to be used
*
* This function returns initial sequence number to be used in a TCP
* connection. For now, initial sequence number is selected based on
* base_timer value, which should be solid enough choice.
*
*/
UINT32 tcp_initseq (void)
{
TCP_DEBUGOUT("Calculating initial sequence number\r\n");
return( ( (UINT32)base_timer << 24) | 0x00FFFFFF );
}
/** \brief Try to match received TCP packet to a socket
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 12.07.2002
* \param ipframe pointer to received IP frame
* \param tcpframe pointer to received TCP frame to be mapped
* \return
* \li -1 - Error (no resources or no socket found)
* \li >=0 - Handle to mapped socket
*
* Function iterates through socket table trying to find a socket for
* whom this TCP packet is intended.
*
*/
INT8 tcp_mapsocket (struct ip_frame* ipframe, struct tcp_frame* tcpframe)
{
struct tcb* soc;
UINT8 i;
/* Check if there is already connection on */
for( i=0; i < NO_OF_TCPSOCKETS; i++) {
soc = &tcp_socket[i]; /* Get socket */
if(soc->state == TCP_STATE_LISTENING)
continue; /* No match */
if(soc->remport != tcpframe->sport)
continue;
if(soc->locport != tcpframe->dport)
continue;
#if defined (IPv6)
//if (memcmp(soc->rem_ip, &ipframe->sip, sizeof(struct _in6_addr)))
if(soc->rem_ip != &ipframe->sip)
#else
if(soc->rem_ip != ipframe->sip)
#endif
continue;
/* There is connection on already */
TCP_DEBUGOUT("Active connection socket found\r\n");
return(i);
}
/* Allocate listening one if SYN packet (Connection Request) */
TCP_DEBUGOUT("No active connection, checking if SYN packet\r\n");
/* Is it SYN? */
if( (tcpframe->hlen_flags & TCP_FLAG_SYN) == 0 )
return(-1);
if( tcpframe->hlen_flags & TCP_FLAG_ACK )
return(-1);
if( tcpframe->hlen_flags & TCP_FLAG_RESET )
return(-1);
if( tcpframe->hlen_flags & TCP_FLAG_FIN )
return(-1);
TCP_DEBUGOUT("Trying to allocate listening one for SYN packet\r\n");
/* Search listening sockets */
for( i=0; i < NO_OF_TCPSOCKETS; i++) {
soc = &tcp_socket[i]; /* Get socket */
if(soc->state != TCP_STATE_LISTENING)
continue;
if(soc->locport != tcpframe->dport)
continue;
/* Bind it */
#if defined (IPv6)
//memcpy (soc->rem_ip, &ipframe->sip, sizeof(struct _in6_addr));
soc->rem_ip = &ipframe->sip;
#else
soc->rem_ip = ipframe->sip;
#endif
soc->remport = tcpframe->sport;
TCP_DEBUGOUT("Allocated new socket\r\n");
return(i);
}
/* No success */
TCP_DEBUGOUT("ERROR:No socket found or allocated for TCP packet\r\n");
return(-1);
}
/** \brief Change TCP socket state and reinitialize timers
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 18.07.2002
* \param soc pointer to socket structure we're working with
* \param nstate new socket state
*
* This function is used for every state-change that occurs in the TCP
* sockets so as to provide correct timers/retransmittions that ensure
* TCP connection is lasting.
*/
void tcp_newstate (struct tcb* soc, UINT8 nstate)
{
soc->state = nstate;
soc->retries_left = TCP_DEF_RETRIES;
/* In some states we don't want to wait for many retries (e.g. TIMED_WAIT) */
switch(soc->state) {
case TCP_STATE_TIMED_WAIT:
soc->retries_left = 0;
break;
case TCP_STATE_SYN_SENT:
/* When we are sending SYN it's propably that ARP is not valid */
/* Do retransmit faster on first time */
init_timer(soc->retransmit_timerh, TCP_INIT_RETRY_TOUT*TIMERTIC);
soc->retries_left = TCP_CON_ATTEMPTS;
break;
case TCP_STATE_LAST_ACK:
case TCP_STATE_FINW1:
case TCP_STATE_FINW2:
case TCP_STATE_CLOSING:
soc->retries_left = 1;
break;
default:
break;
}
/* KeepAlive timer */
if(soc->state == TCP_STATE_CONNECTED)
init_timer(soc->persist_timerh, soc->tout);
/* Retransmit timer */
init_timer(soc->retransmit_timerh, TCP_DEF_RETRY_TOUT*TIMERTIC);
return;
}
/** \brief Returns next free (not used) local port number
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 21.07.2002
* \return
* \li 0 - no free ports!
* \li >0 - free local TCP port number
*
* Function attempts to find new local port number that can be used to
* establish a connection.
*/
UINT16 tcp_getfreeport (void)
{
struct tcb* soc;
static UINT16 lastport = 1;
UINT16 start;
UINT16 i;
/* Try with every port to every socket untill free found */
for( start = lastport++; start != lastport; lastport++) {
if(lastport == TCP_PORTS_END)
lastport = 1;
for(i = 0; i < NO_OF_TCPSOCKETS; i++) {
soc = &tcp_socket[i]; /* Get socket */
if( (soc->state > TCP_STATE_CLOSED) && (soc->locport == lastport) ) {
/* Blaah, this socket has reserved the port, go to next one */
break;
}
}
/* Did we found it? */
if( i == NO_OF_TCPSOCKETS)
break;
}
if(lastport == start) {
TCP_DEBUGOUT("Out of TCP ports!!\n\r");
return(0);
}
return(lastport);
}
/** \brief Check if TCP checksum check's out
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 16.07.2002
* \param ipframe pointer to IP frame that carried TCP message
* \param len length of TCP portion
* \return
* \li 0 - checksum corrupted
* \li 1 - checksum OK
*
* Function recalculates TCP checksum (pseudoheader+header+data) and
* compares it to received checksum to see if everything is OK or there
* is a problem with the checksum.
*/
UINT8 tcp_check_cs (struct ip_frame* ipframe, UINT16 len)
{
UINT16 cs;
UINT8 cs_cnt;
#if defined(IPv6)
UINT16 i;
uint8 *ptr = &ipframe->sip.u.byte[0];
#endif
cs = 0;
cs_cnt = 0;
/* Do it firstly to IP pseudo header */
#if defined (IPv6)
for (i=0; i<(2*sizeof(struct _in6_addr)); i++)
{
cs = ip_checksum(cs, (UINT8)(ptr[i]), cs_cnt++);
}
#else
cs = ip_checksum(cs, (UINT8)(ipframe->sip >> 24), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(ipframe->sip >> 16), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(ipframe->sip >> 8), cs_cnt++);
cs = ip_checksum(cs, (UINT8)ipframe->sip, cs_cnt++);
cs = ip_checksum(cs, (UINT8)(ipframe->dip >> 24), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(ipframe->dip >> 16), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(ipframe->dip >> 8), cs_cnt++);
cs = ip_checksum(cs, (UINT8)ipframe->dip, cs_cnt++);
#endif
cs = ip_checksum(cs, 0, cs_cnt++);
cs = ip_checksum(cs, (UINT8)ipframe->protocol, cs_cnt++);
cs = ip_checksum(cs, (UINT8)(len >> 8), cs_cnt++);
cs = ip_checksum(cs, (UINT8)len, cs_cnt++);
/* Go to TCP data */
while(len>15)
{
RECEIVE_NETWORK_BUF(tcp_tempbuf,16);
cs = ip_checksum_buf(cs, tcp_tempbuf,16);
len -= 16;
cs_cnt += 16;
}
while(len--){
cs = ip_checksum(cs, RECEIVE_NETWORK_B(), cs_cnt++);
}
cs = ~ cs;
if(cs != IP_GOOD_CS) {
return (0);
}
/* It's OK */
return(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -