📄 tcpip.c
字号:
cptEthHdrBuf->EthType = cEthType_Ip;
if ((guwEthLen += 2*cEthHdrLen) < 60){
guwEthLen = 60;
}
send_eth:
ether_Send(); // 发送以太包
guwEthLen = 0; // 释放缓冲区
}
//--------------------------------------------------------------------------------------
#if TCP_ACTIVE_OPEN == 1
UINT16 msip_Connect(UINT16 uwLocalPort, UINT16 *puwRemoteIpAddr, UINT16 uwRemotePort){
Conn_Stru *pConn;
// 检查本地端口是否在本机指定的范围内
if ((uwLocalPort < cLocalPortStart) && (uwLocalPort > cLocalPortEnd)){
return 0;
}
// 检查本地端口是否已经分配或占用
for (pConn = cptConnsStart; pConn < cptConnsEnd; pConn++){
if ((pConn->TcpStateFlags != cTCP_CLOSED) && (pConn->LocalPort == uwLocalPort)){
return 0;
}
}
// 查找TCP事务中的未使用联接(或已经关闭的联接)
for (pConn = cptConnsStart; pConn < cptConnsEnd; pConn++){
if (pConn->TcpStateFlags == cTCP_CLOSED){
// 构造一个主动联接事务
pConn->TcpStateFlags = cTCP_SYN_SENT|cTCP_OUTSTANDING;
pConn->SeqNum[0] = guwISN[0];
pConn->SeqNum[1] = guwISN[1];
pConn->AckNum[0] = guwISN[0];
pConn->AckNum[1] = guwISN[1];
if (++pConn->AckNum[1] == 0){
++pConn->AckNum[0];
}
pConn->NumRetran = 0;
pConn->Timer = 1;
pConn->LocalPort = uwLocalPort;
pConn->RemotePort = uwRemotePort;
pConn->RemoteIpAddr[0] = puwRemoteIpAddr[0];
pConn->RemoteIpAddr[1] = puwRemoteIpAddr[1];
pConn->MaxSegSize = 0; // 远端未知,初始化为:0
return 1;
}
}
// 找不到空闲的TCP联接!
return 0;
}
#endif
//--------------------------------------------------------------------------------------
UINT16 msip_Listen(UINT16 uwPort){
UINT16 index;
for (index = 0; index < cMaxListenPorts; index++){
if (guwListenPorts[index] == 0){
guwListenPorts[index] = uwPort;
return 1;
}
}
return 0;
}
//--------------------------------------------------------------------------------------
UINT16 msip_TcpChkSum(void){
UINT16 SUM , temp;
// 获取TCP段字节长度
temp = cptIpHdrBuf->Len - ((cptIpHdrBuf->Vhl & 0x0f) << 2);
// 计算TCP头和数据段的校验和
SUM = checksum(temp, cpTcpHdrBuf);
// 累加计算伪TCP头的校验和
// 16bit TCP length
if ((SUM += temp) < temp)
++SUM;
// 8bit Protocol
if ((SUM += cptIpHdrBuf->Proto) < cptIpHdrBuf->Proto)
++SUM;
// Source IP Address
if ((SUM += cptIpHdrBuf->SrcIpAddr[0]) < cptIpHdrBuf->SrcIpAddr[0])
++SUM;
if ((SUM += cptIpHdrBuf->SrcIpAddr[1]) < cptIpHdrBuf->SrcIpAddr[1])
++SUM;
// Destination IP Address
if ((SUM += cptIpHdrBuf->DestIpAddr[0]) < cptIpHdrBuf->DestIpAddr[0])
++SUM;
if ((SUM += cptIpHdrBuf->DestIpAddr[1]) < cptIpHdrBuf->DestIpAddr[1])
++SUM;
return SUM;
}
//--------------------------------------------------------------------------------------
void msip_Periodic(){
// 增加初始序号
if (++guwISN[1] == 0){
++guwISN[0];
}
for (gptConn = cptConnsStart; gptConn < cptConnsEnd; gptConn++){
msip_Process(cTCP_TIMER);
}
guwMsg_Route &= ~cM_TCP_PERIODIC; // 清除TCP轮询事件
}
//--------------------------------------------------------------------------------------
void msip_Process(UINT16 uwFlag){
ArpEntries_Stru *pARP = cptArpTabEnd; // 给他一个等价的空指针
UINT16 i,j;
switch (uwFlag){
case cTCP_DATA: // IP输入处理
goto ip_input;
case cTCP_TIMER: // 检验是否TCP事务论询
// goto tcp_Periodic;
}
tcp_Periodic:
guwEthLen = 0;
if ((gptConn->TcpStateFlags == cTCP_TIME_WAIT) ||
(gptConn->TcpStateFlags == cTCP_FIN_WAIT_2)){ // TIMER_WAIT状态:2MSL等待!
if (++gptConn->Timer == cTCP_TIME_WAIT_2MSL){ // 记录等待超时时间,并判断超时
gptConn->TcpStateFlags = cTCP_CLOSED; // 超时关闭联接
}
} else if (gptConn->TcpStateFlags != cTCP_CLOSED){ // 如果是已经关闭的事务,就跳过!
// 如果在OUTSTANDING状态(本地已经发出包,但没有收到回应),需要特殊的重传处理!
if (gptConn->TcpStateFlags & cTCP_OUTSTANDING){
if (--gptConn->Timer == 0){ // 记录等待时间,并校验是否等待时间已过
if (gptConn->NumRetran == cTCP_MAXRTX){ // 记录重传次数,并校验是否到达最大重传次数
// 超过重传次数......
gptConn->TcpStateFlags = cTCP_CLOSED; // 关闭联接
// 通知应用程序时间益出
guwFlags = cTCP_TIMEDOUT;
msip_APPCALL();
// 发RSTACK包通知确认给远端:本地已经异常停止连接!
cptTcpHdrBuf->Flags = cTCP_RST | cTCP_ACK;
goto tcp_send_nodata;
}
// 等待时间的指数退避
gptConn->Timer = cTCP_RTO << (gptConn->NumRetran > 4 ? 4 : gptConn->NumRetran);
++gptConn->NumRetran; // 记录重传次数
// 重传处理变迁
switch (gptConn->TcpStateFlags & cTCP_TS_MASK){
case cTCP_SYN_RCVD: // SYN_RCVD状态:发送SYNACK包
goto tcp_send_synack;
#if TCP_ACTIVE_OPEN == 1
case cTCP_SYN_SENT: // SYN_SENT状态:重发SYN包。
cptTcpHdrBuf->Flags = 0;
goto tcp_send_syn;
#endif
case cTCP_ESTABLISHED: // ESTABLISHED状态:通知应用程序,需要重传上次发出的数据包!!!
guwEthLen = 0;
guwFlags = cTCP_REXMIT;
msip_APPCALL();
goto apprexmit;
case cTCP_CLOSE_WAIT:
case cTCP_LAST_ACK: // LAST_ACK状态,结束当前连接!
goto tcp_send_finack; // 重发FINACK包
case cTCP_FIN_WAIT_1:
goto tcp_send_finack; // 重发FINACK包
case cTCP_FIN_WAIT_2:
case cTCP_CLOSING:
case cTCP_TIME_WAIT:
}
}
} else if ((gptConn->TcpStateFlags & cTCP_TS_MASK) == cTCP_ESTABLISHED){
// ESTABLISHED状态,通知应用程序允许发送数据。
guwEthLen = 0;
guwFlags = cTCP_POLL;
msip_APPCALL();
goto appsend;
}
}
goto drop;
// IP输入处理线程
ip_input:
// IP头校验:IP version and header length. vIP4
if(cptIpHdrBuf->Vhl != cIP_VER_HLEN){
goto drop;
}
// IP分片校验:必须是最后帧才响应(隐含默认:不分片帧)。
if (cptIpHdrBuf->Flags & cIP_MF){
goto drop;
}
// 接收IP包的目标IP地址与本地不相同,丢弃!
if((cptIpHdrBuf->DestIpAddr[0] != guwIpAddr[0]) ||
(cptIpHdrBuf->DestIpAddr[1] != guwIpAddr[1])){
goto drop;
}
// 接收IP包的源地址是与本地相同,丢弃!说明远端在做 DDos 攻击!!!!
if((cptIpHdrBuf->SrcIpAddr[0] == guwIpAddr[0]) &&
(cptIpHdrBuf->SrcIpAddr[1] == guwIpAddr[1])){
goto drop;
}
// IP校验和:错误丢弃!
i = ((cptIpHdrBuf->Vhl & 0x0f) << 2);
if (checksum(i, cpIpHdrBuf) != 0xffff){
goto drop;
}
// 合法IP包:获取IP包缓冲区长度
guwEthLen = cptIpHdrBuf->Len;
// 合法IP包:更新ARP表,并记录更新后的映射表指针位置。
pARP = msip_Arp_Update(cptIpHdrBuf->SrcIpAddr,cptEthHdrBuf->SrcEthAddr);
// IP协议分组
switch(cptIpHdrBuf->Proto){
case cIP_PROTO_ICMP: // 是否是ICMP包?
goto icmp_input;
case cIP_PROTO_TCP: // 是否TCP包?
goto tcp_input;
default: // 不是我们能处理的包,丢弃!
goto drop;
}
// ICMP处理线程
icmp_input:
// ICMP处理:只接受 ping 呼叫,否则丢弃!
if (cptIcmpHdrBuf->Type != cICMP_ECHO){
goto drop;
}
// 校验 ICMP CheckSum
i = cptIpHdrBuf->Len - ((cptIpHdrBuf->Vhl & 0x0f) << 2);
if (checksum(i, cpIcmpHdrBuf) != 0xffff){
goto drop;
}
// 处理ICMP的 ping 回应
cptIcmpHdrBuf->Type = cICMP_ECHO_REPLY;
// 计算 ICMP PING REPLY ChkSum
if((cptIcmpHdrBuf->ChkSum += (cICMP_ECHO << 8)) < (cICMP_ECHO << 8)){
cptIcmpHdrBuf->ChkSum += 1;
}
// Swap IP addresses.
cptIpHdrBuf->SrcIpAddr[0] ^= cptIpHdrBuf->DestIpAddr[0];
cptIpHdrBuf->DestIpAddr[0] ^= cptIpHdrBuf->SrcIpAddr[0];
cptIpHdrBuf->SrcIpAddr[0] ^= cptIpHdrBuf->DestIpAddr[0];
cptIpHdrBuf->SrcIpAddr[1] ^= cptIpHdrBuf->DestIpAddr[1];
cptIpHdrBuf->DestIpAddr[1] ^= cptIpHdrBuf->SrcIpAddr[1];
cptIpHdrBuf->SrcIpAddr[1] ^= cptIpHdrBuf->DestIpAddr[1];
goto send; // 发送IP包
// TCP线程处理
tcp_input:
// 校验 TCP checksum.
if (msip_TcpChkSum() != 0xffff){
goto drop;
}
// 是否是已经存在的TCP事务联接
for (gptConn = cptConnsStart; gptConn < cptConnsEnd; gptConn++){
if ((gptConn->TcpStateFlags != cTCP_CLOSED) &&
(cptIpHdrBuf->SrcIpAddr[0] == gptConn->RemoteIpAddr[0]) &&
(cptIpHdrBuf->SrcIpAddr[1] == gptConn->RemoteIpAddr[1]) &&
(cptTcpHdrBuf->DestPort == gptConn->LocalPort) &&
(cptTcpHdrBuf->SrcPort == gptConn->RemotePort)){
goto found;
}
}
// 如果是不存在的TCP事务:(远端发同步连接请求)
if (cptTcpHdrBuf->Flags & cTCP_SYN){
// 1)如果是SYN请求联接包,就侦听本地联接
for (i = 0; (i < cMaxListenPorts) && (guwListenPorts[i] != 0); i++){
if (cptTcpHdrBuf->DestPort == guwListenPorts[i]){
goto found_listen;
}
}
}
// 2)如果也不是SYN请求联接包,就发送RSTACK,通知远端本地异常终止该连接!!!(半打开状态)
// goto reset; // UIP模式
goto drop; // 采用丢弃,防止不相关DDoS攻击!!!
reset: // 本地异常终止连接处理:发送 RSTACK 包
// 如果接到的是RSTACK包,不响应!
if (cptTcpHdrBuf->Flags & cTCP_RST){
goto drop;
}
// 准备发送RSTACK包
guwEthLen = 2*(cIpHdrLen + cTcpHdrLen);
cptTcpHdrBuf->HdrLen = cTCP_HDR_NOOPT;
cptTcpHdrBuf->Flags = cTCP_RST|cTCP_ACK;
// 直接使用远端的SeqNum和AckNum变换为本地的......
cptTcpHdrBuf->SeqNum[0] ^= cptTcpHdrBuf->AckNum[0];
cptTcpHdrBuf->AckNum[0] ^= cptTcpHdrBuf->SeqNum[0];
cptTcpHdrBuf->SeqNum[0] ^= cptTcpHdrBuf->AckNum[0];
cptTcpHdrBuf->SeqNum[1] ^= cptTcpHdrBuf->AckNum[1];
cptTcpHdrBuf->AckNum[1] ^= cptTcpHdrBuf->SeqNum[1];
cptTcpHdrBuf->SeqNum[1] ^= cptTcpHdrBuf->AckNum[1];
// AckNum加1(SYN逻辑的需要)
if (++cptTcpHdrBuf->AckNum[1] == 0){
++cptTcpHdrBuf->AckNum[0];
}
// 交换端口
cptTcpHdrBuf->SrcPort ^= cptTcpHdrBuf->DestPort;
cptTcpHdrBuf->DestPort ^= cptTcpHdrBuf->SrcPort;
cptTcpHdrBuf->SrcPort ^= cptTcpHdrBuf->DestPort;
// 交换IP
cptIpHdrBuf->SrcIpAddr[0] ^= cptIpHdrBuf->DestIpAddr[0];
cptIpHdrBuf->DestIpAddr[0] ^= cptIpHdrBuf->SrcIpAddr[0];
cptIpHdrBuf->SrcIpAddr[0] ^= cptIpHdrBuf->DestIpAddr[0];
cptIpHdrBuf->SrcIpAddr[1] ^= cptIpHdrBuf->DestIpAddr[1];
cptIpHdrBuf->DestIpAddr[1] ^= cptIpHdrBuf->SrcIpAddr[1];
cptIpHdrBuf->SrcIpAddr[1] ^= cptIpHdrBuf->DestIpAddr[1];
// 发送RSTACK包
goto tcp_send_noconn;
// 如果接收的是SYN请求包,本地又有空闲的TCP事务连接
// 1)创建TCP事务连接
// 2)发送SYNACK,进入cTCP_SYN_RCVD|cTCP_OUTSTANDING状态
found_listen:
// 查找空闲的TCP联接
for (gptConn = cptConnsStart; gptConn < cptConnsEnd; gptConn++){
if ((gptConn->TcpStateFlags == cTCP_CLOSED) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -