mini2440_arp协议移植

arp.h在这里定义了以太网帧头,arp协议头与ip帧头。
先是一些类型的定义:

typedef unsigned short u16;
typedef unsigned char u8;

以太网头的结构体

typedef struct eth_hdr
{
    /*目的MAC地址*/
    u8 d_mac[6];
    /*源MAC地址*/
    u8 s_mac[6];
    /*上层协议的类型*/
    u16 type;
}ETH_HDR;

arp头的结构体定义

typedef struct arp_hdr
{
    /*以太网头*/
    ETH_HDR ethhdr;
    /*硬件地址的类型,它的值为1表示以太网地址*/
    u16 hwtype;
    /*上层协议的类型*/
    u16 protocol;
    /*硬件地址的长度,通常为6*/
    u8 hwlen;
    /*协议地址的长度,通常为4*/
    u8 protolen;
    /*操作类型,1表示ARP请求,2表示ARP应答*/
    u16 opcode;
    /*发送方的MAC地址*/
    u8 smac[6];
    /*发送方的ip地址*/
    u8 sipaddr[4];
    /*接收方的MAC地址,在arp请求包里通常设为0*/
    u8 dmac[6];
    /*接受方的ip地址*/
    u8 dipaddr[4];
}IP_HDR

同时arp.h中还用extern声明了一些全局变量,这些全局变量实际在dm9000的网卡驱动中定义,具体参见(在文章末尾处定义)http://blog.csdn.net/u011412588/article/details/53549522

/*pc机的MAC地址,初始值全部为全1*/
extern u8 host_mac_addr[6];
/*开发板的MAC地址*/
extern u8 mac_addr[6];
/*开发板的ip地址,主机号可以随意,但是要与pc机的ip处于同一个网段*/
extern u8 ip_addr[4];
/*pc机的ip地址*/
extern u8 host_ip_addr[4];
/*接受到数据包的长度*/
extern u16 packet_len;

/*用来存储arp请求包*/
ARP_HDR arpbuf;

/*arp协议的type编号*/
#define PROTO_ARP 0x086
/*ip协议的type编号*/
#define PROTO_IP 0x0800
/*udp协议的type编号*/
#define PROTO_UDP 0x11

在上一篇博文mini2440_dm9000网卡驱动中,实现了网卡的发送与接受两个API,这篇文章将会使用其中的api进行数据的发送与接收。

arp_request函数,用于构建arp请求包,需要注意的是,因为数据需要在网络上传输,凡是两个字节的字段都需要装换成网络字节序,这里提供了一个转换的宏

#define HON(n) ((((u16)((n)&0xff))<<8)|(((n)&0xff00)>>8))
void arp_request()
{
    /*装填以太网帧头的目的MAC地址,这里被设为全1*/
    memcpy(arpbuf.ethhdr.d_mac,host_mac_addr,6);
    /*装填以太网帧头的源MAC地址*/
    memcpy(arpbuf.ethhdr.s_mac,mac_addr,6);
    /*设置上层协议的类型*/
    arpbuf.ethhdr.type = HON(PROTO_ARP);
    /*设置硬件地址类型,需要转网络字节序*/
    arpbuf.hwtype = HON(1);
    /*设置上层协议的类型*/
    arpbuf.protocol = HON(PROTO_IP);
    /*设置硬件地址的长度*/
    arpbuf.hwlen = 6;
    /*设置协议地址的长度*/
    arpbuf.protolen = 4;

    /*设置arp包的操作类型*/
    arpbuf.opcode = HON(1);

    /*设置源MAC地址*/
    memcpy(arpbuf.smac,mac_addr,6);
    /*设置源ip地址*/
    memcpy(arpbuf.sipaddr,ip_addr,4);
    /*设置目的MAC地址*/
    memcpy(arpbuf.dmac,host_mac_addr,6);
    /*设置目的ip地址*/
    memcpy(arpbuf.dipaddr,host_ip_addr,4);

    /*以太网帧头长度为14(byte),arp头长度为28(byte)*/
    packet_len = 14+28;
    /*调用网卡的发送api*/
    dm9000_tx(&arpbuf,packet_len);
}

下面介绍的是arp_process函数,用于处理其他机器发来的arp请求或者接受arp回应

u8 arp_process(u8 * buf,u32 len)
{
    u32 i;
    APR_HDR *arp_p=(ARP_HDR *)buf;
    /*如果数据包小于28则不可能是arp包*/
    if(len < 28)
        return 0;
    /*此处需要把原来的包内的网络字节序转换成主机字节序*/
    switch(HON(arp_p->opcode))
    {
        /*若为1,arp请求包,回以应答包*/
        case 1:
            memcpy(arpbuf.ethhdr.d_mac,arp_p->ethhdr.s_mac,6);
            memcpy(arpbuf.ethhdr.s_mac,mac_addr,6);
            arpbuf.ethhdr.type = HON(PROTO_ARP);

            arpbuf.hwtype = HON(1);
            arpbuf.protocol = HON(PROTO_IP);
            arpbuf.hwlen = 6;
            arpbuf.protolen = 4;
            /*op设为2,回应arp请求*/
            arpbuf.opcode = HON(2);
            memcpy(arpbuf.smac,mac_addr,6);
            memcpy(arpbuf.sipaddr,ip_addr,4);
            memcpy(arpbuf.dmac,arp_p->smac,6);
            memcpy(arpbuf.dipaddr,arp_p->sipaddr,4);

            packet_len = 14+28;
            dm9000_tx(&arpbuf,packet_len);
            break;
        /*接收到arp回应包*/
        case 2:
            memcpy(host_mac_addr,arp_p->smac,6);
            printf("host_mac_addr is:");
            for(i=0;i<6;i++)
                printf("%02x ",host_mac_addr[i]);
            printf("\n");
            memcpy(host_ip_addr,arp_p->sipaddr,4);
            printf("host_ip_addr is:");
            for(i=0;i<3;i++)
                printf("%03d ",host_ip_addr[i]);
            printf("\n");
            break;
        default:
            break;                  
    }   
}

void net_handle(u8 * buf,_u32 len)函数在上篇博文中已经出现过,用途是根据以太网帧头(ETH_HDR)中的type确定数据包的协议,并调用相应的处理函数

void net_handle(u8 *buf,u32 len)
{
    ETH_HDR *p = (ETH_HDR*)buf;
    /*需要网络字节序转主机字节序*/
    switch(HON(p->type))
    {
        case PROTO_IP:
            ip_process(buf,len);
            break;
        case PROTP_ARP:
            arp_process(buf,len);
            break;
        default:
            break;
    }
}

其中的ip_process()函数声明为:
void ip_process(u8 *buf,u32 len);
作用是解析基于ip协议的数据包,并调用相应的处理函数,将会在下篇博文mini2440_TFTP客户端移植中给出实现。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值