educoder -- ARP协议的实现

任务描述

本关任务的目标是合成理解arp协议的语法和语义,并实现该协议。

任务1:根据已经给定的缓存表结构及定义,完成初始化函数:
void arp_cache_init(void);
其功能就是全局量
struct arpentry arpcache[ARP_CACHE_SIZE]; /* ARP cache */
进行初始化。

任务2:根据输入参数ip在表中查询对应的mac地址,如果表中没有该ip的地址,则启用arp请求进行解析:
byte *arp_resolve(uint32 ip, byte *mac);

任务3:根据网卡参数及目的ip,构建arp请求帧:
int generate_arp_request(uint32 dstip, struct etherPkt *eth ) ;

任务4:据网卡参数及目的ip,目的mac,构建arp响应帧:
int generate_arp_response(uint32 dstip, byte *dstmac, struct etherPkt *eth ) ;

任务5:根据收到的免费arp请求,更新arp缓存:
void update_arpcache(struct arppacket *arppkt, int curtime);
注意与下面add_arpcache( )的区别,更新只是对记录已经有的记录用新的时间和mac进行替换,而add_arpcache( )除了更新功能外,如果记录中没有该ip对应的记录,还要添加一条记录。

任务6: 根据收到的arp请求或响应,更新或添加arp缓存:
void add_arpcache(struct arppacket *arppkt, int curtime);

任务7:处理收到的arp帧:
当收到arp协议数据单元时启用,它会根据arp类型是请求还是响应做不同的操作,如果是请求,则表示有主机查询自己的mac,此时需要将该请求中的ip和mac添加到缓存中,因此收到请求意味着,该主机要与自己通信,所以预先存储它的mac。如果收到的是响应,表示是自己发出的请求得到了回应,此时也应添加记录。
void arp_in( struct etherPkt *eth);

/* arp.c - arp_init, arp_resolve, arp_in, arp_alloc, arp_ntoh, arp_hton	*/

#include "datalink_arp.h"

struct	arpentry  arpcache[ARP_CACHE_SIZE];	/* ARP cache			*/
struct	network networkdata;
unsigned char out_eth[MAX_ETH_LENTH] = { 0 };
/*------------------------------------------------------------------------
 * init_network  -  网卡初始化
 *------------------------------------------------------------------------
 */
void init_network(char *configfile) {
    get_local_netdata(configfile);
    arp_cache_init();
}
void print_arpcache(void) {
	printf("打印arpchae列表:\n");
    char str[100];
    for (int i = 0; i < ARP_CACHE_SIZE; i++) {
        printf("%d   time:%d  ",i,0);
        printf("ip:%s    ",ip2str(arpcache[i].ipaddr,str) );
        printf("mac:");
        print_eth_addr(arpcache[i].macaddr);
        printf("\n");
    }

}
/*------------------------------------------------------------------------
 * get_local_netdata  -  获取本地网络参数
 *------------------------------------------------------------------------
 */
struct	network * get_local_netdata(char *configfile) {
	printf("输出主机配置信息:\n");
    struct	network *NetData = &networkdata;
    char ip[100] = { 0 }, mask[100] = { 0 }, gate[100] = { 0 }, dns[100] = { 0 };
    getconfig(configfile, ip, mask, gate, dns);
    printf("ip:%s\nmask:%s\ngate:%s\ndns:%s\n", ip, mask, gate, dns);

    uint32 uip = str2ip(ip), umask = str2ip(mask), ugate = str2ip(gate), udns = str2ip(dns);

    if (uip == 0) {
        NetData->ipucast = 0;
        return NetData;
    }
    byte bcast[6] = { 0xff,0xff,0xff,0xff,0xff,0xff };
    byte mac[6] = { 0x00,0xf1,0xf3,0x05,0x39,0x4b };
    printf("mac:");
	print_eth_addr(mac);
    printf("\n");

    NetData->dnsserver = udns;
    memcpy(NetData->ethbcast, bcast, 6);
    memcpy(NetData->ethucast, mac, 6);
    NetData->ipmask = umask;
    NetData->ipprefix = uip & umask;
    NetData->ipbcast =  NetData->ipprefix | ~NetData->ipmask;

    NetData->iprouter = ugate;
    NetData->ipucast = uip;

    return NetData;
}
/*------------------------------------------------------------------------
 * arp_cache_init  - 初始化arp缓存
 *------------------------------------------------------------------------
 */
void	arp_cache_init(void){
    /**********Begin 1 **********/
    
    /********End 1 **********/
}

/*------------------------------------------------------------------------
 *arp_resolve - 根据ip查找对应的mac,如果没找到有效的mac,则发arp请求
 *------------------------------------------------------------------------
 */
byte * arp_resolve( uint32	ip, byte	*mac)	{
    int validtime = time(NULL) - 60;//超过60秒的,记录无效
    struct	arpentry  *arptr;	/* arp缓存记录指针	*/
    /* 如果ip是广播地址,则返回mac广播地址 */
    if (ip == 0xffffffff || ip == networkdata.ipbcast) {
        memcpy(mac, networkdata .ethbcast, ETH_ADDR_LEN);
        return mac;
    }
    /**************Begin 2 ************/
    
    for(int i = 0 ; i < ARP_CACHE_SIZE; i++){
        if(arpcache[i].ipaddr == ip){
            memcpy(mac, arpcache[i].macaddr, ETH_ADDR_LEN);
            return mac;
        }
    }
    /************End  2 *************/
    int len=generate_arp_request(ip,(struct etherPkt *) out_eth);
    char str[100];
    printf("%s搜索失败,发送arp请求!\n",ip2str(ip,str));
    sendpkt((byte *) out_eth,len);
    return NULL;
}
/*------------------------------------------------------------------------
 *generate_arp_request - 根据网卡参数及目的ip,构建arp请求帧
 *------------------------------------------------------------------------
 */
int generate_arp_request(uint32	dstip,	struct etherPkt *eth	){
    struct	arppacket *arppkt = (struct	arppacket*)eth->data;
    int len = 0;/*帧长,不包含校验码*/
    /************** Begin 3 ***********/
    /* 填充以太网帧的协议字段*/
    memcpy(eth->src, networkdata.ethucast, ETH_ADDR_LEN);
    memcpy(eth->dst, networkdata.ethbcast, ETH_ADDR_LEN);
    eth->type = 0x0608;
    arppkt->htype = 0x0100;
    arppkt->ptype = 0x008;
    arppkt->hlen = 0x06;
    arppkt->plen = 0x04;
    arppkt->op = 0x0100;
    memcpy(arppkt->srcmac, networkdata.ethucast, ETH_ADDR_LEN);
    arppkt->srcip = networkdata.ipucast;
    // memcpy(arppkt->dstmac, eth->dst, ETH_ADDR_LEN);
    arppkt->dstip = dstip;
    len = 60;
     /********** End 3 ************/
     return len;
}
/*------------------------------------------------------------------------
 *generate_arp_response - 根据网卡参数及目的ip,目的mac,构建arp响应帧
 *------------------------------------------------------------------------
 */
int generate_arp_response(uint32	dstip,    byte *dstmac,    struct etherPkt *eth	){
    struct	arppacket *arppkt = (struct	arppacket*)eth->data;
    int len = 0;/*帧长,不包含校验码*/
    /************** Begin 4 ******************/
    memcpy(eth->src, networkdata.ethucast, ETH_ADDR_LEN);
    memcpy(eth->dst, dstmac, ETH_ADDR_LEN);
    eth->type = 0x0608;
    arppkt->htype = 0x0100;
    arppkt->ptype = 0x008;
    arppkt->hlen = 0x06;
    arppkt->plen = 0x04;
    arppkt->op = 0x0200;
    memcpy(arppkt->srcmac, networkdata.ethucast, ETH_ADDR_LEN);
    arppkt->srcip = networkdata.ipucast;
    memcpy(arppkt->dstmac, eth->dst, ETH_ADDR_LEN);
    arppkt->dstip = dstip;
    len = 60;
    /********** End 4 *************/
    return len;
}
/*------------------------------------------------------------------------
 *update_arpcache - 根据收到的免费arp请求,更新arp缓存
 *------------------------------------------------------------------------
 */
void update_arpcache(struct arppacket *arppkt, int curtime) {
    struct	 arpentry *arptr;
    /*****************Begin 5 ***********/
    
    /**********End 5 **************/
}
/*------------------------------------------------------------------------
 *add_arpcache - 根据收到的arp请求和响应,更新或添加arp缓存
 *------------------------------------------------------------------------
 */
void add_arpcache(struct arppacket *arppkt, int curtime) {
    struct	 arpentry *arptr;
    /***************** Begin 6 ***********/
    for(int i = 0; i < ARP_CACHE_SIZE; i++){
        if(arpcache[i].timestampe == 0){
            arpcache[i].timestampe = curtime;
            arpcache[i].ipaddr = arppkt->srcip;
            memcpy(arpcache[i].macaddr, arppkt->srcmac, ETH_ADDR_LEN);
            break;
        }
    }
 
    /********** End 6 **************/
}
/*------------------------------------------------------------------------
 * arp_in  -  处理收到的arp帧
 *------------------------------------------------------------------------
 */
void	arp_in( struct etherPkt *eth){
    int curtime = time(NULL);
    struct arppacket * arppkt = (struct arppacket*)eth->data;

 
    /* 验证 ARP 是 IPv4 和 Ethernet */
    if ((arppkt->htype !=htons( ARP_HTYPE)) ||  (arppkt->ptype != ntohs(ARP_PTYPE)))
        return;

    if (arppkt->dstip == networkdata.ipucast)
        add_arpcache(arppkt, curtime);
    else if(arppkt->dstip == arppkt->srcip)
        update_arpcache(arppkt, curtime);
    /*********** Begin 7 *************/
    /*如果收到的是给本机的arp请求,则需要发送arp响应帧*/
    if (arppkt->dstip == networkdata.ipucast){
        int len = generate_arp_response(arppkt->srcip, arppkt->srcmac, (struct etherPkt *) out_eth);
        char str[100];
        printf("收到arp请求,发送arp响应!\n");
        sendpkt((byte *) out_eth,len);
    }
       /*********** End 7 *************/
    return;
}

/*------------------------------------------------------------------------
 * arp_alloc  -  为新加入的arp记录,分配一个位置
 *------------------------------------------------------------------------
 */
int	arp_alloc(void){
    /*搜索空闲的记录空间 ,如果arpcache满了,踢出时间最早的*/
    int	slot = 0;
    /********** Begin 8 ***********/

    /********** End 8 ************/
    memset((char *)&arpcache[slot], 0, sizeof(struct arpentry));
    return slot;
}

/*------------------------------------------------------------------------
 * sendpkt  -  模拟发送帧
 *------------------------------------------------------------------------
 */
void sendpkt(byte *eth,int len) {
    print_pkt(eth, len);
}
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值