网络协议栈设计(六)---链路层以太网代码实现(接收)

网络协议栈设计(六)

//Ethernet.h
//这里只为上次的Ethernet.h做一补充


int is_accept_ethernet_packet(u_int8_t *packet_content, int len);

void ethernet_protocol_packet_callback(u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content);
//Ethernet.cpp

#include "Network_IPV4_recv.h"
#include "Network_ARP_recv.h "
//这里需要调用上层提供的接收函数接口交付数据包

int is_accept_ethernet_packet(u_int8_t *packet_content, int len)
{
    struct ethernet_header *ethernet_hdr = (struct ethernet_header *)packet_content;
    int i;
    int flag = 0;

    //检查目的MAC地址是否是广播MAC地址
    for (i = 0; i < 6; i++)
    {
        if (ethernet_hdr->destination_mac[i] != 0xff)break;
    }
    if (i == 6)
    {
        flag = 1;
        printf("It's broadcast packet.\n");
    }

    //检查目的MAC地址是否是本地MAC地址
    for (i = 0; i < 6; i++)
    {
        if (ethernet_hdr->destination_mac[i] != local_mac[i])break;
    }
    if (i == 6)
    {
        flag = 1;
        printf("It's sended to my pc.\n");
    }

    //若上边检查均未通过,返回0表示本数据包不需要接收
    if (!flag)
        return 0;

    //否则检查CRC校验码
    u_int32_t crc = calculate_crc((u_int8_t *)packet_content , len - 4 );
    if (crc != *((u_int32_t *)(packet_content + len - 4)))
    {
        printf("The data has changed.\n");
        return 0;
    }

    //CRC无误则本数据包可以接收,返回1
    return 1;
}

//接收数据帧的回环函数
void ethernet_protocol_packet_callback(u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content)
{
    int len = packet_header->len;
    if (!is_accept_ethernet_packet((u_int8_t *)packet_content, len))
    {
        return;
    }

    struct ethernet_header *ethernet_hdr = (struct ethernet_header *)packet_content;
    u_int16_t ethernet_type = ntohs(ethernet_hdr->ethernet_type);

    //去掉MAC帧首部,将数据部分根据上层协议交付给相应的上层接收函数
    u_int8_t *upper_buffer = (u_int8_t *)(packet_content + sizeof(ethernet_header));
    switch (ethernet_type)
    {
    case 0x0800:
        printf("Upper layer protocol: IPV4\n");
        network_ipv4_recv(upper_buffer);
        break;
    case 0x0806:
        printf("Upper layer protocol: ARP\n");
        dest_mac=network_arp_recv(upper_buffer);
        break;
    case 0x8035:
        printf("Upper layer protocol: RARP\n");
        //network_rarp_recv();
        break;
    case 0x814c:
        printf("Upper layer protocol: SNMP\n");
        //network_snmp_recv();
        break;
    case 0x8137:
        printf("Upper layer protocol: IPX(Internet Packet Exchange)\n");
        //network_ipx_recv();
        break;
    case 0x86DD:
        printf("Upper layer protocol: IPV6\n");
        //network_ipv6_recv();
        break;
    case 0x880B:
        printf("Upper layer protocol: PPP\n");
        //network_ppp_recv();
        break;
    default:break;
    }
    //以上注释掉的协议均未实现,有兴趣的伙伴可以在看完我的协议栈设计的基础上在进行追加
}

到这里我们就算介绍完了数据链路层以太网的数据包发送和接收的过程及实现,我们先在此简单总结一下:
我们的数据发送,向上层提供的接口函数是:
int ethernet_send_packet(u_int8_t *upper_buffer,u_int8_t *destination_mac,u_int16_t ethernet_type)
上层调用此函数时需要提供的参数有:
1、上层的数据包,即链路层数据帧的数据部分
2、数据包长度,这里我们用全局变量ethernet_upper_len来获取
2、目的MAC地址
3、调用此函数的上层协议

数据接收时,根据上层协议不同提交时上层提供给我们的接口有:
network_arp_recv(upper_buffer);
network_ipv4_recv(upper_buffer);
//这两个我们后边会慢慢给大家展示出来

下一篇我们就进入网络层的设计。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值