?? 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 + -