📄 tcp.c
字号:
UTL_Checksum (buf_ptr, LONGSWAP(tcp_chk->dest),
LONGSWAP(tcp_chk->source), IP_TCP_PROT) );
/* Send this packet. */
/* Note that the IP source addresses and IP destination addresses are
swapped.*/
stat = IP_Send(buf_ptr, NU_NULL, LONGSWAP(tcp_chk->source),
LONGSWAP(tcp_chk->dest), 0, IP_TIME_TO_LIVE, IP_TCP_PROT,
IP_TYPE_OF_SERVICE, NU_NULL);
if (stat == NU_SUCCESS)
{
/* Increment the number of TCP segments transmitted. */
SNMP_tcpOutSegs_Inc;
/* Increment the number of TCP resets sent. */
SNMP_tcpOutRsts_Inc;
}
else
{
/* The packet was not sent. Dealocate the buffer. If the packet was
transmitted it will be deallocated later by TCP. */
MEM_One_Buffer_Chain_Free (buf_ptr, &MEM_Buffer_Freelist);
}
return (0);
} /* end TCP_Reset_FIN() */
/*************************************************************************
*
* FUNCTION
*
* TCP_Update_Headers
*
* DESCRIPTION
*
* Update the fields in the IP and TCP headers that change from
* packet to packet. Depending on the type parameter, call
* either tcpsend or tcp_sendack.
*
* INPUTS
*
* pport
* buf_ptr
* tcp_hlen
*
* OUTPUTS
*
* INT16 -1
* NU_SUCCESS
*
*************************************************************************/
INT16 TCP_Update_Headers (TCP_PORT *pport, NET_BUFFER *buf_ptr, UINT16 tcp_hlen)
{
TCP_PORT *prt;
TCPLAYER *tcp_ptr;
prt = pport;
/* Overlay the TCP header. */
tcp_ptr = (TCPLAYER *)buf_ptr->data_ptr;
if (prt == NU_NULL)
{
NERRS_Log_Error (NERR_RECOVERABLE, __FILE__, __LINE__);
return (-1);
} /* end if */
/* Set the SEQ and ACK numbers. */
PUT32(tcp_ptr, TCP_SEQ_OFFSET, pport->out.nxt);
PUT32(tcp_ptr, TCP_ACK_OFFSET, pport->in.nxt);
/* Save off the last ACK value that was sent. This will be used to
determine when the next one should be sent in the case of a delayed ACK.
*/
pport->in.ack = pport->in.nxt;
/* Setup the source and destination port numbers. */
PUT16(tcp_ptr, TCP_DEST_OFFSET, prt->out.port);
PUT16(tcp_ptr, TCP_SRC_OFFSET, prt->in.port);
/* Set the tcp header len */
PUT8(tcp_ptr, TCP_HLEN_OFFSET, (UINT8)(tcp_hlen << 4) );
/*
* if the port has some credit limit, use it instead of large
* window buffer. Generally demanded by hardware limitations.
*/
if ((INT32)(prt->credit) < (prt->in.size))
{
PUT16(tcp_ptr, TCP_WINDOW_OFFSET, prt->credit);
}
else
{
PUT16(tcp_ptr, TCP_WINDOW_OFFSET, (UINT16)prt->in.size);
}
/* Set the urgent pointer. */
PUT16(tcp_ptr, TCP_URGENT_OFFSET, 0);
/* Set the flags field. */
PUT8(tcp_ptr, TCP_FLAGS_OFFSET, prt->out.tcp_flags);
/* Clear the checksum filed to 0. It will be computed later. */
PUT16(tcp_ptr, TCP_CHECK_OFFSET, 0);
return NU_SUCCESS;
} /* end TCP_Update_Headers(). */
/*************************************************************************
*
* FUNCTION
*
* TCP_Send_ACK
*
* DESCRIPTION
*
* Transmit an ack packet or a packet that contains options.
* Acks work this way so that we don't have to allocate a buffer
* for a packet that will contain no data.
*
* INPUTS
*
* pport
*
* OUTPUTS
*
* INT16 NU_NULL
* NU_SUCCESS
*
*************************************************************************/
INT16 TCP_Send_ACK(TCP_PORT *pport)
{
TCPLAYER *tcp_ptr;
NET_BUFFER *buf_ptr;
STATUS stat;
/* Clear the PUSH flag if no data to be sent. */
if (!pport->out.contain)
pport->out.tcp_flags &= ~TPUSH;
/* Allocate a buffer to place the ack packet in. */
buf_ptr = MEM_Buffer_Dequeue(&MEM_Buffer_Freelist);
if(buf_ptr == NU_NULL)
{
return (NU_NULL);
}
/* Initialize each field in the allocated buffer, adding on the TCP layer. */
buf_ptr->mem_total_data_len = sizeof (TCPLAYER);
buf_ptr->data_len = sizeof (TCPLAYER);
buf_ptr->next = NU_NULL;
buf_ptr->next_buffer = NU_NULL;
buf_ptr->mem_seqnum = 0;
buf_ptr->mem_dlist = &MEM_Buffer_Freelist;
/* Point to the location within the packet where the TCP header begins. */
buf_ptr->data_ptr = (buf_ptr->mem_parent_packet +
(NET_MAX_TCP_HEADER_SIZE - sizeof (TCPLAYER)));
/* Update the IP and TCP headers with the latest info. The TCP header is
always 5 words in size for an ACK packet. */
TCP_Update_Headers(pport, buf_ptr, 5);
/* Point at the TCP header. */
tcp_ptr = (TCPLAYER *)buf_ptr->data_ptr;
/* Compute and fill in the checksum. */
PUT16(tcp_ptr, TCP_CHECK_OFFSET,
UTL_Checksum(buf_ptr, pport->tcp_laddr, pport->tcp_faddr, IP_TCP_PROT) );
/* Send this packet. */
stat = IP_Send((NET_BUFFER *)buf_ptr, &pport->tp_route, pport->tcp_faddr,
pport->tcp_laddr, 0, IP_TIME_TO_LIVE,
IP_TCP_PROT, IP_TYPE_OF_SERVICE, NU_NULL);
if (stat == NU_SUCCESS)
{
/* Increment the number of TCP segments transmitted. */
SNMP_tcpOutSegs_Inc;
}
else
{
/* The packet was not sent. Dealocate the buffer. If the packet was
transmitted it will be deallocated when transmission is complete. */
MEM_One_Buffer_Chain_Free (buf_ptr, &MEM_Buffer_Freelist);
}
return(NU_SUCCESS);
} /* end TCP_Send_ACK() */
/*************************************************************************
*
* FUNCTION
*
* TCP_Send
*
* DESCRIPTION
*
* Send a tcp packet.
*
* INPUTS
*
* *pport
* *buf_ptr
*
* OUTPUTS
*
* The number of bytes sent.
* NU_HOST_UNREACHABLE
* NU_ACCESS
* NU_MSGSIZE
* NU_SUCCESS
*
*************************************************************************/
STATUS TCP_Send(TCP_PORT *pport, NET_BUFFER *buf_ptr)
{
TCPLAYER *tcp_ptr;
STATUS stat;
INT tcp_hlen;
/* Check to see if there is an ACK timer event set. If so clear it out
because the data packet that is about to be sent will include the ack. */
if(pport->portFlags & ACK_TIMER_SET)
{
/* Delete the ACK timeout timer. */
UTL_Timerunset(TCPACK, (UNSIGNED)pport->pindex, (INT32)1 );
/* Clear the ACK timer flag in the port. */
pport->portFlags &= (~ACK_TIMER_SET);
}
/* Now add the TCP header and options to the size and update the data
pointer to point to the header. */
buf_ptr->data_ptr -= (sizeof (TCPLAYER) + buf_ptr->mem_option_len);
buf_ptr->data_len += (sizeof (TCPLAYER) + buf_ptr->mem_option_len);
buf_ptr->mem_total_data_len += (sizeof (TCPLAYER) + buf_ptr->mem_option_len);
/* Compute the TCP header size in words. */
tcp_hlen = ((sizeof(TCPLAYER) + buf_ptr->mem_option_len - 1) / 4) + 1;
/* Update the header information. */
TCP_Update_Headers(pport, buf_ptr, (UINT16)tcp_hlen);
/* Calculate the next sequence number to be sent. */
pport->out.nxt += buf_ptr->mem_tcp_data_len;
/* Point to the beginning of the TCP header. */
tcp_ptr = (TCPLAYER *)buf_ptr->data_ptr;
/* Compute and fill in the checksum. */
PUT16(tcp_ptr, TCP_CHECK_OFFSET,
UTL_Checksum(buf_ptr, pport->tcp_laddr, pport->tcp_faddr, IP_TCP_PROT) );
/* Initialize the number of times this packet has been retransmitted. */
buf_ptr->mem_retransmits = 0;
/* If there is no timing being performed then time this transmission. */
if (pport->p_rtt == 0)
{
pport->p_rtt = NU_Retrieve_Clock();
pport->p_rtseq = buf_ptr->mem_seqnum;
}
/* Send this packet. */
stat = IP_Send((NET_BUFFER *)buf_ptr, &pport->tp_route, pport->tcp_faddr,
pport->tcp_laddr, 0, IP_TIME_TO_LIVE,
IP_TCP_PROT, IP_TYPE_OF_SERVICE, NU_NULL);
if (stat == NU_SUCCESS)
{
/* Set a retransmit event for this packet. */
UTL_Timerset (TCPRETRANS, (UNSIGNED)pport->pindex,
(UNSIGNED)pport->p_rto, (INT32)pport->out.nxt);
/* Increment the number of TCP segments transmitted. */
SNMP_tcpOutSegs_Inc;
}
else
{
/* The packet was not sent. Dealocate the buffer. If the packet was
transmitted it will be deallocated later by TCP. */
MEM_One_Buffer_Chain_Free (buf_ptr, &MEM_Buffer_Freelist);
}
return(stat);
} /* end TCP_Send() */
/*************************************************************************
*
* FUNCTION
*
* TCP_ACK_Check
*
* DESCRIPTION
*
* Take an incoming packet and see if there is an ACK for the
* outgoing side. Use that ACK to dequeue outgoing data.
*
* INPUTS
*
* prt
* tcp_pkt
*
* OUTPUTS
*
* INT16 1
* TCP_NO_ACK
* TCP_INVALID_ACK
* NU_SUCCESS
*
*************************************************************************/
static INT16 TCP_ACK_Check(TCP_PORT *prt, TCPLAYER *tcp_pkt)
{
INT32 ak;
#if (INCLUDE_SNMP == NU_TRUE)
UINT8 tcp_laddr[4];
UINT8 tcp_faddr[4];
#endif
/* We received a reset and the sequence number is within the current window
then close the connection. */
if((GET8(tcp_pkt, TCP_FLAGS_OFFSET) & TRESET) &&
(INT32_CMP(G
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -