⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udp.c

📁 RTL8019以太网开发板资料
💻 C
📖 第 1 页 / 共 4 页
字号:
    }
                // 计算剩余的数据 
    for(ucLoop = 0; ucLoop < ucDataLen; ucLoop++)
    {
        ulCheckSum += *pusPointer;
        pusPointer++;
    }
            // 数据是单数还要将最后一个数据加上,低8位补零 
    if(usDataLen & 0x0001)
    {
        ulCheckSum += (*pusPointer & 0xff00);
    }
              // 加上进位部分 
    ulCheckSum = (ulCheckSum >> 16) + (ulCheckSum & 0x0000ffff);
              // 可能再次进位,再加上进位部分,之后不可能再进位 
    ulCheckSum += (ulCheckSum >> 16);

    usRealDataLen = (UWORK16)ulCheckSum;
    usRealDataLen = (~usRealDataLen);
    return usRealDataLen;
}
/*********************************************************************
函数名:       void ArpRequest(UWORK8 *pucaIP)
功能:         ARP请求
输入:         ARP请求需要 
输出:         组ARP请求包
返回:         None
日期:         2004/12/19
修改:         2006/6/01
*********************************************************************/
void ArpRequest(UWORK8 *pucaIP)
{                                                                // 以太网头     
    memset(&MAC_Remote_buf[0],0xff,MAC_LEN);                   // 发广播包 
    MAC_Remote_buf[12] = 0x08;
    MAC_Remote_buf[13] = 0x06;
	  ArpRequestFormat.usOPER  = OPER_REQUEST;                        // ARP请求 
	  memcpy(&ArpRequestFormat.ucaTPA[0],pucaIP,IP_LEN);              // 目的IP 
    
    memcpy(&ArpRequestFormat.ucaSPA[0],&IPAddress_buf[0],IP_LEN);   // 源IP    
    memcpy(&NetSend_buf[0],&ArpRequestFormat,sizeof(ArpRequestFormat));
    SendEthernetPacket(28);

    if(IPConflitTestFlag)                                          // IP冲突测试 
    {
        StartTimer(5,501);                                       // 启动IP冲突超时 
    }
}
/*********************************************************************
函数名:       void ArpProcess(void)
功能:         ARP应答,因为是接收一帧处理一帧,不用返回成功失败
输入:         接收的帧是ARP帧 
输出:         回应ARP查询
返回:         None
日期:         2004/12/11
*********************************************************************/
void ArpProcess(void)
{
    xdata ST_ARP_FORMAT *pArpRcv;
    UWORK8 ucLoop;

    pArpRcv = (ST_ARP_FORMAT *)&gstaRevEthernet.ucaPacket[0];              // 指向ARP数据包内容                                                                    
    if((HTYPE == pArpRcv->usHTYPE) && (PTYPE == pArpRcv->usPTYPE)          // 验证是否是以太网ARP 
        &&(HLEN == pArpRcv->ucHLEN) && (PLEN == pArpRcv->ucPLEN))
     {
       if((0 == memcmp(&pArpRcv->ucaSHA[0],&NetParameter.MAC_Local_buf[0],MAC_LEN))  //发送端的IP或MAC与本地IP或MAC相同则表示有冲突 
           || (0 == memcmp(&pArpRcv->ucaSPA[0],&IPAddress_buf[0],IP_LEN)))
         {
            IPOrMacConfiltFlag = TRUE;
            ARPFinishFlag = FALSE;                                       // 清ARP完成标志
            StopArpCounter();                                              // 检测到冲突,停止ARP相关计数器 
            StartTimer(12,400);                                            // 4秒种后再次检测 
         }                                  
       switch(pArpRcv->usOPER)
        {
            case OPER_REQUEST:                                             // 收到ARP请求帧 
                memcpy(&ArpAnswerFormat.ucaTHA[0],&pArpRcv->ucaSHA[0],MAC_LEN);  // ARP应答
                memcpy(&ArpAnswerFormat.ucaTPA[0],&pArpRcv->ucaSPA[0],IP_LEN);
                memcpy(&ArpAnswerFormat.ucaSPA[0],&IPAddress_buf[0],IP_LEN);
                memcpy(&NetSend_buf[0],&ArpAnswerFormat,sizeof(ArpAnswerFormat));
                memcpy(&MAC_Remote_buf[0],&pArpRcv->ucaSHA[0],MAC_LEN);
                MAC_Remote_buf[12] = 0x08;
                MAC_Remote_buf[13] = 0x06;
                SendEthernetPacket(28);
                break;

            case OPER_APLY:                                                // 收到ARP应答帧  
            	                
               for(ucLoop = 0; ucLoop < IpModeNum; ucLoop++)
                {
                  if(0 == memcmp(&ArpCache_Buf[ucLoop].ucaArpIp[0],&pArpRcv->ucaSPA[0],IP_LEN))
                   {
                        memcpy(&ArpCache_Buf[ucLoop].ucaMAC[0],&pArpRcv->ucaSHA[0],MAC_LEN);                       
                        ARPFinishFlag = TRUE;                           // 置ARP完成标志
                        if('r' != ArpCache_Buf[ucLoop].ucStatus)
                        {
                            ArpCache_Buf[ucLoop].ucStatus = 'r';           
                        }
                        else             // 此时应该是老化阶段,停止了定时器6,需要打开定时器4来启动定时器7 
                         {
                            StopTimer(6);
                            gucARPOddNum = 0;                              // 有了回应,老化计数器清零 
                            StartTimer(4,10);                              // 定时器4来启动定时器7 
                         }
                        break;                      
                   }
                }
                break;

            default:
                
                break;
        }
     }
}
/*********************************************************************
函数名:       void IpOrRouter(void)
功能:         IP路由选择
输入:         初始化或者改变IP的时候 
输出:         判断IP还是路由
返回:         None
日期:         2005/01/24
更新:         2006/05/21
*********************************************************************/
void IpOrRouter(void)
{
    UWORK32 ulLocalIP,ulRemoteIP,ulMask;
    UWORK8 ucaTemp[4],ucLoop;

    memcpy((UWORK8 *)&ulLocalIP,&IPAddress_buf[0],IP_LEN); 
    memcpy((UWORK8 *)&ulMask,&SubNetMask_buf[0],IP_LEN);
   
    for(ucLoop = 0; ucLoop < REMOTE_IP_NUM; ucLoop++)                      // 目的IP地址 /
    {
        memset(&ucaTemp[0],0,4);
        if(0 == memcmp(&ucaTemp[0],&ArpCache_Buf[ucLoop].ucaIP[0],IP_LEN))
        {
            ArpCache_Buf[ucLoop].ucIPValible = 0;                          // 没有合法的IP,规定0.0.0.0为非法IP 
        }
        else
        {
            ArpCache_Buf[ucLoop].ucIPValible = 1;

            memcpy((UWORK8 *)&ulRemoteIP,&ArpCache_Buf[ucLoop].ucaIP[0],IP_LEN);

            if((ulLocalIP & ulMask) == (ulRemoteIP & ulMask))
            {
                ArpCache_Buf[ucLoop].ucIpOrRouter = 0;                     // 网络号相同,直接交付 
                memcpy(&ArpCache_Buf[ucLoop].ucaArpIp[0],&ArpCache_Buf[ucLoop].ucaIP[0],IP_LEN); 
            }
            else
            {
                ArpCache_Buf[ucLoop].ucIpOrRouter = 1;                     // 网络号不相同,使用路由间接交付         
                memcpy(&ArpCache_Buf[ucLoop].ucaArpIp[0],&GateWay_buf[0],IP_LEN);
            }           
        }
        ArpCache_Buf[ucLoop].ucStatus = 'f';
    }
}
/*********************************************************************
函数名:       void StopArpCounter(void)
功能:         停止ARP相关的计数器
输入:         检测到了IP或MAC冲突 
输出:         停止ARP
返回:         None
日期:         2006/06/22
*********************************************************************/
void StopArpCounter(void)
{
    StopTimer(5);
    StopTimer(6);
    StopTimer(7);
}
/*********************************************************************
函数名:       void IpReceive(void)
功能:         Ip处理,因为是接收一帧处理一帧,不用返回成功失败
输入:         接收的帧是Ip帧 
输出:         处理IP分组
返回:         None
日期:         2004/12/20
*********************************************************************/
void IpReceive(void)
{
    ST_IP_HEAD_FORMAT *pIpHead;
    ST_UDP_HEAD_FORMAT *pUdpHead;
    UWORK16 usFragmentOffset;

    
    pIpHead = (ST_IP_HEAD_FORMAT *)&gstaRevEthernet.ucaPacket[0];          // 指向IP头 
    pUdpHead = (ST_UDP_HEAD_FORMAT *)&gstaRevEthernet.ucaPacket[20];        
                     // IP数据需满足3个条件 1.广播包 2.本地IP地址 
                     // 只处理IPV4和基本长度的IP包 
    if(0x45 == pIpHead->ucVerAndLen)
    {
        if(0x0000 == CheckSum((UWORK16 *)&gstaRevEthernet.ucaPacket[0],20))   // 计算IP校验头 
        {
            if(0 == (pIpHead->usSegOffset & 0x3fff))             // 没有分片的处理,直接从接收缓冲拷贝数据 
            {
                if(pIpHead->usTotalLen > 1514)                   // 不能超过以太网的最大包长度,防止恶意攻击
                {
                    return;
                }
                gbHaveFragment = FALSE;                        // 清分片标志 
                switch(pIpHead->ucprotocol)
                {
                    case ICMP:					  //网间网控制报文协议,PING命令
                        IcmpReceive(pIpHead->usTotalLen - 20);
                        break;

                    case UDP:
                        UdpReceive();
                        break;
				    case TCP:		//TCP协议
//                        TCPReceive();
                        break;
					case IGMP:		//IGMP协议
//                        IGMPReceive();
                        break;
                    default:
                        break;
                }
            }
            else                 // 建立一个缓冲,用于组装分散包 
            {
                usFragmentOffset = (pIpHead->usSegOffset & 0x1fff) * 8;
                if(pIpHead->usSegOffset & MORE_FRAGMENT)                                // 有更多的分片 
                {
                    if( 0 == usFragmentOffset)                                          // 第一个分片 
                    {
                        memcpy(&NetSend_buf[0],&gstaRevEthernet.ucaPacket[0],20);   // ICMP需要 
                        memcpy(&gucaSegTemp[0],&gstaRevEthernet.ucaPacket[0],pIpHead->usTotalLen);
                        RevIpID = pIpHead->usID;
                        gbHaveFragment = TRUE;
                    }
                    else                       //中间分片 
                    {
                        if(RevIpID != pIpHead->usID)                                 // 是否为同一个ID /
                        {
                            return;
                        }
                        if((usFragmentOffset + pIpHead->usTotalLen) <= SEGMENT_DATA)    // 只有5K的缓存 
                        {
                            memcpy(&gucaSegTemp[usFragmentOffset + 20],&gstaRevEthernet.ucaPacket[20],pIpHead->usTotalLen - 20);
                        }
                    }
                }
                else                // 最后一个分片 
                {
                    if(RevIpID != pIpHead->usID)                                     // 是否为同一个ID 
                    {
                        return;
                    }
                    if((usFragmentOffset + pIpHead->usTotalLen) <= SEGMENT_DATA)        // 只有5K的缓存 
                    {
                        memcpy(&gucaSegTemp[usFragmentOffset + 20],&gstaRevEthernet.ucaPacket[20],pIpHead->usTotalLen - 20);
                              // 还需要判断数据是否完全到齐????? 
                        switch(NetSend_buf[9])
                        {
                            case ICMP:
                                IcmpReceive(usFragmentOffset + pIpHead->usTotalLen - 20);
                                break;
                            
                            case UDP:
                                UdpReceive();
                                break;

                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
}
/*********************************************************************
函数名:       void IpSend(void)
功能:         Ip发送数据
输入:         发送数据的长度 
输出:         将数据打包成IP包
返回:         None
日期:         2004/12/28
*********************************************************************/
void IpSend(void)
{
    ST_IP_HEAD_FORMAT *pIpHeadBuff;
    MAC_Remote_buf[12] = 0x08;                                           // IP协议 
    MAC_Remote_buf[13] = 0x00;
    pIpHeadBuff = (ST_IP_HEAD_FORMAT *)&NetSend_buf[0];                // IP头 
    memcpy(&NetSend_buf[0],&gstIphead,20);
    pIpHeadBuff->usCheckSum = 0;
    pIpHeadBuff->usCheckSum = CheckSum((UWORK16 *)&NetSend_buf[0],20); // 计算IP头校验和
    SendEthernetPacket(pIpHeadBuff->usTotalLen);
}
/*********************************************************************
函数名:       void IcmpReceive(UWORK16 usTotalLen)
功能:         Icmp处理,因为是接收一帧处理一帧,不用返回成功失败
输入:         IP包数据长度 
输出:         处理Icmp分组
返回:         None
日期:         2004/12/21
*********************************************************************/
void IcmpReceive(UWORK16 usTotalLen)
{
    ST_ICMP_HEAD_FORMAT *pIcmpHead;
    ST_IP_HEAD_FORMAT *pIpHeadBuff;
    UWORK16 usLoop,usRes,usCheckSum;
    UWORK8 ucNum;

    if(FALSE == gbHaveFragment)
    {
        pIcmpHead = (ST_ICMP_HEAD_FORMAT *)&gstaRevEthernet.ucaPacket[20];      // 指向ICMP头 
        usCheckSum = CheckSum((UWORK16 *)&gstaRevEthernet.ucaPacket[20],usTotalLen);
        pIpHeadBuff = (ST_IP_HEAD_FORMAT *)&gstaRevEthernet.ucaPacket[0];
    }
    else
    {
        pIcmpHead = (ST_ICMP_HEAD_FORMAT *)&gucaSegTemp[20];
        usCheckSum = CheckSum((UWORK16 *)&gucaSegTemp[20],usTotalLen);
        pIpHeadBuff = (ST_IP_HEAD_FORMAT *)&gucaSegTemp[0];
    }
    if(0x0000 != usCheckSum)
    {
        return;                                                                  // 校验和错误,返回 
    }
    
    switch(pIcmpHead->ucType)
    {   
        case ICMP_ECHO:                                                          // 目的端的回送请求 
            
                        // 组帧应答 
            pIcmpHead->ucType = ICMP_ECHO_REPLY;                                 // 应答 
            pIcmpHead->usCheckSum = 0x00;            
                        // IP头            
            gstIphead.usID = ++LocalIpID;
            gstIphead.ucprotocol = 0x01;                                         // ICMP协议            
            memcpy(&gstIphead.ucSourceIP[0],&IPAddress_buf[0],IP_LEN);           // 原IP地址 
            memcpy(&gstIphead.ucDestIP[0],&pIpHeadBuff->ucSourceIP[0],IP_LEN);   // 目的IP地址
            memcpy(&MAC_Remote_buf[0],&gstaRevEthernet.ucaSourceNodID[0],NOD_ID_LENGTH);  // 目的MAC地址 
            
            if(FALSE == gbHaveFragment)                                        // 没有分片的数据 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -