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

📄 ip.c

📁 RTL8019以太网开发板资料
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "ip.h"
#include "tcp.h"
#include "ARP.h"
#include "UDP.h"
#include "ICMP.h"
#include "rtl8019.h"
xdata ST_IP_HEAD_FORMAT gstIphead;

xdata UWORK8 IPLocalAddress_buf[IP_LEN];                    // 本地IP地址 
xdata UWORK8 SubNetMask_buf[IP_LEN];                   // 子网掩码 
xdata UWORK8 GateWay_buf[IP_LEN];                      // 网关 
xdata UWORK8 IPSourceddress_buf[IP_LEN];                    // IP地址
xdata UWORK8 IPDestAddress_buf[IP_LEN];                    /* 目标IP地址 */
UWORK16 SourcePort;			//源端口号
UWORK16 DesPort;				//目标端口号

/*********************************************************************
函数名:       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头校验和
    
//SerialSendbuf((UWORK8 *)&NetSend_buf[0],gstIphead.usTotalLen); 	  //读取IP总的数据长度
	SendEthernetPacket(pIpHeadBuff->usTotalLen);
}
/*********************************************************************
函数名:       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,&IPLocalAddress_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 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;
						    case TCP:		//TCP协议
		                        TCPReceive();
		                        break;
							case IGMP:		//IGMP协议
		//                        IGMPReceive();
		                        break;
                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
}


/*********************************************************************
函数名:       UWORK16 CheckSum(UWORK16 *pusPointer,UWORK16 usDataLen)
功能:         计算校验和
输入:         十六位的数据指针,数据长度 
输出:         计算校验和
返回:         校验和的反码
日期:         2004/12/20
*********************************************************************/
UWORK16 CheckSum(UWORK16 *pusPointer,UWORK16 usDataLen)
{
    UWORK8 ucDataLen,ucNum,ucLoop,ucLoopNum;
    UWORK16 usRealDataLen;
    UWORK32 ulCheckSum = 0;

    usRealDataLen = usDataLen >> 1;                         // 8位长度变为16位长度
    ucNum = usRealDataLen / 255;
    ucDataLen = usRealDataLen % 255;
    for(ucLoopNum = 0; ucLoopNum < ucNum; ucLoopNum++)		  // 将循环变量换成8位,提高运行速度 
    {
        for(ucLoop = 0; ucLoop < 255; ucLoop++)
        {
            ulCheckSum += *pusPointer;
            pusPointer++;
        }
    }
    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 RcvEthernetData(void)
功能:         接收以太网数据
输入:         None 
输出:         None
返回:         OK, ERROR
日期:         2007/03/13
*********************************************************************/
void RcvEthernetData(void)
{
    UWORK16 ucTemp,ucResult;
    
    EX0 = FALSE;      // 禁止外部中断0
	if(0 != RTL8019asRcvNum)                            // 以太网芯片缓存中是否有以太网包 
    {
        EX0 = FALSE;      // 禁止外部中断0
        ucTemp = RevEthernetPacket();				   //解析网络包
 //   SerialSendbuf((UWORK8 *)&gstaRevEthernet.usprotocol,sizeof(ST_RECEIVE_ETHERNET));
		EX0 = TRUE;    // 外部中断0使能
        if(OK == ucTemp)                            // 正确接收了数据,记录的缓存减1 
        {
		   
		    RTL8019asRcvNum--;
            EthernetNoDataFlag = FALSE;
            switch(gstaRevEthernet.usprotocol)			   // 劈以太网帧 
		    {
		        case IP_type:			  //IP协议
		             IpReceive();
		            break;
		        case ARP_type:			 //ARP协议
		             ArpProcess();
		            break;
		        default:
		            break;
		    } 
        } 
    }
    else                                               // 可能中断未被及时执行 
    {
       if(FALSE == EthernetNoDataFlag)                 // 可能有没有及时中断造成数据没有读完 
        {
            EX0 = FALSE;      // 禁止外部中断0
            Page1();
            RTL8019asRead(RW1_CURR,ucTemp);              // 比较读指针和写指针,判断是否有数据            
            Page0();
           if((ucTemp < 0x80) && (ucTemp > 0x4b))      // 读的过程是否出错,CUUR处于0x4c~0x7f 
            {
                RTL8019asRead(RW0_BNRY,ucResult);
                ucResult++;
               if(ucResult > 0x7f)
                {
                    ucResult = 0x4c;
                }
               if(ucTemp != ucResult)                  // 是否有没有读完的数据 
                {
                    ucTemp = RevEthernetPacket();
                    EX0 = TRUE;    // 外部中断0使能
                   if(OK == ucTemp)                 // 正确接收了数据,记录的缓存减1 
                    {
                        switch(gstaRevEthernet.usprotocol)			   // 劈以太网帧 
					    {
					        case IP_type:
					             IpReceive();
					            break;
					        case ARP_type:
					             ArpProcess();
					            break;

⌨️ 快捷键说明

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