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

📄 ip.c

📁 uccos2的的源码文件
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "test.h"
#include "def.h"
#include "ip.h"


////////////////////////////////////////
int WantNext = 0;

#define DEBUGSTRING(str) //printf("at %d:%s\r\n",__LINE__,str)

#define CONFIRMTONE

U8 nettest;            //定义网络测试0x80,冲突检测0xa0,主机查询0x90
                        //位7表示网络测试中,在查询IP冲突和主机时需要置位
                        //位6用于发送一个包
                        //位5表示查询主机IP
                        //低4位表示测试的次数
U8 nettestaddr;        //网络测试的低位地址

struct nicipAddr myIP,remoteIP,hostIP;
unsigned int localIP = IP_ADDR(192,168,1,100); //IP_ADDR(192,168,0,100);

typedef struct
{
    unsigned int ip;
    char mac[6];
}arp_tbl;

#define MAX_ARP_COUNT 6
int gi_arppos = 0;
arp_tbl gstr_arptbl[MAX_ARP_COUNT];
void AddArpTbl(unsigned int ip,void* mac)
{
    if( FindArp(ip,0) )
        return;
    gstr_arptbl[gi_arppos].ip = ip;
    memcpy(gstr_arptbl[gi_arppos].mac,mac,6);
    gi_arppos++;
    gi_arppos %= MAX_ARP_COUNT;
}


int FindArp(unsigned int ip,void* mac)
{
    int i;
    for( i = 0; i < MAX_ARP_COUNT; i++)
    {
        if( ip == gstr_arptbl[i].ip )
        {
            if( mac )
                memcpy(mac,gstr_arptbl[i].mac,6);
            return 1;
        }
    }
    return 0;
}

extern U16 invert16(U16 w)
{
    UNION16 dt1,dt2;

    dt1.i = w;
    dt2.b[0] = dt1.b[1];
    dt2.b[1] = dt1.b[0];
    return(dt2.i);
}

extern int net_send_packet(char* data,int len);
int NicSendTxFrame(U16 ProtocolType,void *buffer,U16 length)
{
    STR_ETHHEAD* ehead = (STR_ETHHEAD*)buf;

    //数据包的最小长度等于64字节
    if (length < 46)
    {
        length = 46;
    }
    memcpy(ehead->DestMac,remoteIP.Mac,6);
    memcpy(ehead->SrcMac,myIP.Mac,6);
    ehead->Type = ProtocolType;
    memcpy(ehead->buffer,buffer,length);
    return net_send_packet((char*)ehead,12+2+length);
}

void net_open(void);

char mac_addr[] = {0x00,0x11,0x22,0x33,0x44,0x55};
void InitIP(void)
{
    net_open();
    //设置本机的IP地址
    myIP.Ip.l = localIP;
    //设置本机的MAC地址
    memcpy(myIP.Mac,mac_addr,6);
    set_mac_address(myIP.Mac);
    get_mac_address(myIP.Mac);
}


void ReceivedEther(char *buffer,int length)
{
    unsigned short ProtocolType;
    ProtocolType = buffer[12] | (buffer[13]<<8);
    memcpy(remoteIP.Mac,buffer+6,6);
    memcpy(buffer,buffer+14,length-14);
    ReceivedIP(buffer,ProtocolType);
}

extern int IsALLSrc(U8 * dest,U8 src,U16 len)
{
    for( ; len ; len--)
    {
        if((*dest) != src)
        {
            return(FALSE);
        }
        dest++;
    }
    return(TRUE);
}


////////////////////////////////////////

#define headLen     20

//声明使用的外部函数


//内部使用的函数预定义
extern int SendTxFrame(U16 ProtocolType,void *buffer,U16 length);
extern void ArpFun(STR_ARP *arp);
extern void SendArp(STR_ARP *arp,U16 op);
extern void IpFun(STR_IP *ip);
extern void UdpFun(STR_UDP *udp);
extern void IcmpFun(STR_ICMP *icmp,U16 icmplen);
extern int UdpSend(STR_UDP *udp,U16 length);

//定义模块变量
U8 const arpHead[] = {0x00,0x01,0x08,0x00,0x06,0x04,0x00};

U8 const rarpHead[]= {0x00,0x01,0x08,0x00,0x06,0x04,0x00,0x03};

String * PrintIp(void* str,char* ipa)
{
    sprintf((char*)str,"%u.%u.%u.%u",ipa[0],ipa[1],ipa[2],ipa[3]);
    return str;
}

String * PrintMac(void* str,char* mac)
{
    sprintf((char*)str,"%02x:%02x:%02x:%02x:%02x:%02x",
        mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
    return str;
}


// 检查是否内网通讯,
// 内网通讯设置通讯IP为内网IP
// 外网通讯设置通讯IP为外网IP
static void CheckLocalNetWork(void)
{
    myIP.Ip.l = localIP;

    FindArp(remoteIP.Ip.l,remoteIP.Mac);
    if ( IsALLSrc(remoteIP.Mac,0x00,6) )
    {
        LookupMac(remoteIP.Ip.b[3]);
    }
}

/*
函数    TCP/IP的校验和计算方法
输入    buf     要计算的校验和缓冲区首地址
        length  缓冲区大小
*/
U16 GenCheckSum(U8 *buf,U16 length)
{
    U32 checksum;

    checksum = 0;
    while(length > 0)
    {
        checksum += *buf*0x100;
        buf++;
        length--;
        if ( length > 0 )
        {
            checksum += *buf++;
            length--;
        }
    }
    while(checksum >> 16)
    {
        checksum = (checksum & 0xffff) + (checksum >> 16);
    }
#ifdef LITTLE_ENDIAN
    checksum = (~checksum & 0xffff);
    return(ENDIAN16(checksum));
#endif
#ifdef BIG_ENDIAN
    return (~checksum);
#endif
}

/*
函数  处理来自NIC层以及其它底层的数据包
      数据格式如下
*/
void ReceivedIP(void *buffer,U16 ProtocolType)
{
    //判断数据包的类型域
    switch(ProtocolType)
    {
        case P_ARP:     //接收到ARP的数据包
            DEBUGSTRING("arp");
            ArpFun(buffer);
            break;
        case P_RARP:    //接收到RARP的数据包
            DEBUGSTRING("rarp");
#ifdef NET_RARP
            RarpFun(buffer);
#endif
            break;
        case P_IP:      //接收到IP数据包
            DEBUGSTRING("ip");
            IpFun(buffer);
            break;
        default:
            //DEBUGSTRING("default");
            break;
    }
}

void ArpChangeEndian(STR_ARP *arp)
{
#ifdef LITTLE_ENDIAN
    arp->Op = ENDIAN16(arp->Op);
#endif
}

/*
功能  ARP功能函数,主要用于查询和回答相应的MAC地址
      硬件类型(16)            协议类型(16)
      硬件长度(8) 协议长度(8) 操作(16)
              发送站硬件地址
              发送站协议地址
              目标站硬件地址
              目标站协议地址
*/
void ArpFun(STR_ARP *arp)
{
    U32 SrcAddr,DestAddr;

    SetLocalIp();
#ifdef LITTLE_ENDIAN
    ArpChangeEndian(arp);
#endif
    memmove(&SrcAddr,arp->SrcProtocolAddr,4);
    memmove(&DestAddr,arp->DestProtocolAddr,4);
    switch (arp->Op)
    {
        case 1:     //ARP请求操作,这里发送请求应答
            DEBUGSTRING("arp request");
#ifdef DEBUGMODE
            printf("\r\nmyIP:%08x DestIP:%08x ",myIP.Ip.l,DestAddr);
#endif
            if (myIP.Ip.l == DestAddr)
            {
                remoteIP.Ip.l = SrcAddr;    //记录远端的IP
                //在这里添加路由信息
                AddArpTbl(remoteIP.Ip.l,remoteIP.Mac);
                SendArp(arp,2);         //应答IP数据包
            }
            break;
        case 2:     //ARP应答操作
            DEBUGSTRING("arp ack");
            if(myIP.Ip.l == DestAddr)
            {
                if (nettest & 0x80)
                {
                    CONFIRMTONE;
                    nettest = 0;
                }
                nettestaddr = 0;
                //找到远端的IP地址
                remoteIP.Ip.l = SrcAddr;
                //在这里添加路由信息
                AddArpTbl(remoteIP.Ip.l,remoteIP.Mac);
            }
            break;
        default:
            DEBUGSTRING("default");
            break;
    }
}

//功能  ARP数据包的发送函数
//输入  op  ARP的操作码
//输出
//返回
void SendArp(STR_ARP *arp,U16 op)
{
    //网络媒体是以太网
    //填充NIC的头部信息(含包类型)
    memmove(arp,arpHead,sizeof(arpHead));
    //填充操作码
    arp->Op = op;
    //填充发送站硬件地址
    //填充发送站IP地址
    memmove(arp->SrcHardAddr,&myIP.Mac,6);
    memmove(arp->SrcProtocolAddr,&myIP.Ip,4);
    //填充目标站硬件地址
    //填充目标站IP地址
    memmove(arp->DestHardAddr,&remoteIP.Mac,6);
    memmove(arp->DestProtocolAddr,&remoteIP.Ip,4);
    ArpChangeEndian(arp);
    SendTxFrame(P_ARP,(void*)arp,42);                         //ARP的数据长度是42个字节
}

/*
功能    查找对应IP地址的MAC地址
*/
void LookupMac(U8 addr)
{
    STR_ARP arp;

    remoteIP.Ip.l = (myIP.Ip.l & 0x00ffffff) |  (addr << 24);
    memset(remoteIP.Mac,0xff,6);
    SendArp(&arp,1);
}

#ifdef NET_RARP
void RarpFun(void)
{
    if (arp.oph != 0)
    {
        //RARP的高位操作码非法
        return;
    }
    if (arp.oph != 4)
    {
        //不支持的操作
        return;
    }
    //设置本机的IP地址
//    myIP.ip = *(U32 *)&nicRxBuffer[14+8+6];
}

void SendRarp(U8 op)
{
    //网络媒体是以太网
    if (op != 3)
    {
        return;
    }
    //发送广播数据包
    memset(remoteIP.Mac,0xff,6);
//    memcpy(&nicTxBuffer[12],rarpHead,10);
    //发送站的硬件地址
//    memcpy(&nicTxBuffer[22],&myIP.mac,6);
    //发送站IP地址,目标MAC和IP地址未知,不需要填充
//    memset(&nicTxBuffer[28],0x00,14);
    SendTxFrame(42);
}
#endif

void IpChangeEndian(STR_IP *ip)
{
#ifdef LITTLE_ENDIAN
    ip->Len = ENDIAN16(ip->Len);
    ip->Id = ENDIAN16(ip->Id);
    ip->Flag = ENDIAN16(ip->Flag);
#endif
}

/*
函数    IP数据包的处理程序
        处理的数据包包含UDP,ICMP
*/
void IpFun(STR_IP *ip)
{
    //判断校验和是否正确
    if(GenCheckSum((U8 *)ip,headLen) != 0x0000)
    {
        //校验和错误
        DEBUGSTRING("checksum error");
#ifdef DEBUGMODE
        printf("\r\nchecksum: 0x%04x",GenCheckSum((U8 *)ip,headLen));
#endif
        return;
    }
    IpChangeEndian(ip);
   // DEBUGSTRING("IpFun");
   // Tell2(ip->DestIp,localIP);
    if(ip->DestIp == localIP)
    {// 使用本地以太网端口
        SetLocalIp();
    }

⌨️ 快捷键说明

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