第十七章 W55MH32 ARP示例

目录

1 MACRAW模式简介

2 ARP协议简介

3 ARP协议特点

4 ARP协议请求的工作流程

5 ARP协议应用场景

6 ARP协议的安全风险及防护措施

7 ARP协议的工作原理

8 ARP报文格式

9 实现过程

10 运行结果

11 总结


本篇文章,我们将详细介绍如何在W55MH32芯片上面实现MAC RAW模式。并通过实战例程,为大家讲解如何使用MAC RAW模式实现ARP解析IP地址为MAC地址。

该例程用到的其他网络协议,例如 DHCP,请参考相关章节。有关 W55MH32 的初始化过程,请参考 Network Install 章节,这里将不再赘述。

1 MACRAW模式简介

MACRAW 模式是W55MH32 TOE提供的一种底层通信模式,芯片会直接接收和发送以太网帧,而无需解析 TCP/IP 层的协议。通过这种模式,用户可以直接操作以太网帧的头部(如目的 MAC 地址、源 MAC 地址、以太类型等)和有效负载数据。

注意:仅Socket0能设置为MACRAW模式。

2 ARP协议简介

ARP(Address Resolution Protocol,地址解析协议)是一个网络协议,用于通过已知的IP地址解析对应的MAC地址,工作于OSI模型的第二层(数据链路层),它是IPv4网络中局域网通信的重要组成部分。

3 ARP协议特点

协议工作范围:ARP协议仅在同一个局域网(LAN)内工作,因为广播请求无法跨越路由器。

缓存机制:为了减少频繁的广播,设备会将IP-MAC的对应关系缓存一段时间。

协议类型:ARP请求(Opcode = 1):用于查询目标设备的MAC地址。

ARP响应(Opcode = 2):用于回复请求方的ARP消息。

4 ARP协议请求的工作流程

当发送方主机A需要与目标主机B通信,但只知道目标主机的IP地址,而不知道目标主机的MAC地址,并且自己的ARP缓存表中也无对应关系,此时会触发ARP请求流程:

  1. 构建ARP请求:发送方需要构建一个ARP请求数据包。
  2. 广播ARP请求:发送方将构建好的ARP请求封装为以太网帧,使用广播方式发送到局域网。
  3. 目标主机接收并处理:网络中的所有主机都会收到广播帧,但只有目标主机(IP地址匹配)会响应。
  4. 发送方接收ARP响应,并更新自己的ARP缓存表。

5 ARP协议应用场景

  1. 地址解析:当设备需要进行链路层通信时,可以使用ARP协议获取对方MAC地址。
  2. 网络调试与诊断:在调试嵌入式设备时,通过发送 ARP 请求验证设备的网络连通性。

6 ARP协议的安全风险及防护措施

尽管ARP协议在局域网通信中非常重要,但它也存在安全风险。例如,ARP欺骗是一种常见的攻击手段,攻击者可以通过伪造ARP回复来误导其他设备,从而窃取敏感信息或中断网络通信。为了防范ARP欺骗攻击,可以采取以下措施:

1.使用静态ARP:通过配置静态ARP表项,可以限制和指定IP地址的设备通信时只使用指定的MAC地址。这样,即使攻击者发送了伪造的ARP报文,也无法修改此表项的IP地址和MAC地址的映射关系。

2.端口安全和静态IP/MAC绑定:在接入交换机上启用端口安全功能,并将用户IP/MAC地址进行静态绑定。这种方法可以防止用户发出假冒网关的ARP信息。

3.动态ARP检查(DAI)与DHCP侦听:结合使用动态ARP检查和DHCP侦听功能,可以对用户发出的ARP报文进行合法性检测,并过滤掉不符合规则的ARP报文。

4.加密通信协议:通过使用加密通信协议,可以防止网络流量被窃听和篡改。

5.防火墙和交换机配置:在防火墙和交换机上设置相应的安全策略,例如启用特殊的ARP报文过滤功能。

6客户端管理:确保所有终端设备都遵循安全策略,并定期更新和打补丁。

7 ARP协议的工作原理

发送ARP请求:

当设备A需要与设备B通信时,首先检查ARP缓存是否存有设备B的MAC地址。如果ARP缓存中没有设备B的MAC地址,设备A会发送一条广播ARP请求消息,格式为:“谁是IP地址 X.X.X.X?请告诉我(设备A的IP地址和MAC地址)。”

接收ARP响应:

设备B收到广播请求后,检查请求中的IP地址是否与自身匹配。如果匹配,设备B发送一条单播ARP响应消息给设备A,告知设备B的MAC地址。设备A收到响应后,将设备B的MAC地址缓存起来,用于后续通信。

8 ARP报文格式

一个标准的ARP报文由以下字段组成,总长度为28字节(不包含链路层帧头):

字段名

长度(字节)

描述

Hardware Type

2

表示硬件类型,常见值为1(以太网)。

Protocol Type

2

表示需要解析的协议类型,常见值为0x0800(IPv4)。

Hardware Address Length

1

硬件地址(MAC地址)的长度,通常为6字节。

Protocol Address Length

1

协议地址(IP地址)的长度,通常为4字节(IPv4)。

Operation Code

2

指示操作类型:1(请求),2(响应)。

Sender Hardware Address

6

请求方的MAC地址。

Sender Protocol Address

4

请求方的IP地址。

Target Hardware Address

6

目标设备的MAC地址。请求中此字段为0。

Target Protocol Address

4

目标设备的IP地址。

报文字段详解

  1. 硬件类型 (Hardware Type):说明所使用的网络类型,例如:
  1. 1:以太网。
  2. 6:IEEE 802网络。

对于以太网的ARP报文,该值始终为0x0001。

  1. 协议类型 (Protocol Type):表示要解析的协议类型,例如:
  1. 0x0800:表示IPv4地址解析。
  2. 0x86DD:表示IPv6(通常由ND协议替代ARP)。
  1. 硬件地址长度 (Hardware Address Length):定义硬件地址(MAC地址)的长度,通常为6字节(以太网)。
  2. 协议地址长度 (Protocol Address Length):定义协议地址(IP地址)的长度,通常为4字节(IPv4)。
  3. 操作码 (Operation Code):说明ARP的操作类型:
  1. 1:ARP请求。
  2. 2:ARP响应。
  1. 发送方硬件地址 (Sender Hardware Address):包含请求方设备的MAC地址。
  2. 发送方协议地址 (Sender Protocol Address):包含请求方设备的IP地址。
  3. 目标硬件地址 (Target Hardware Address):在ARP请求中,这一字段为空(全0)。在ARP响应中,包含目标设备的MAC地址。
  4. 目标协议地址 (Target Protocol Address):包含目标设备的IP地址。

报文内容:

ARP Probe请求报文:

|报文解析|

Address Resolution Protocol (ARP Probe)      (ARP Probe请求报文,用于检测目标IP地址是否冲突)

    Hardware type: Ethernet (1)              (硬件类型:1 表示以太网)

    Protocol type: IPv4 (0x0800)             (协议类型:0x0800 表示IPv4)

    Hardware size: 6                         (硬件地址长度:6字节)

    Protocol size: 4                         (协议地址长度:4字节)

    Opcode: request (1)                      (操作码:1 表示ARP请求)

    [Is probe: True]                         (是否为探测:是,用于检测IP冲突)

    Sender MAC address: Wiznet_12:22:12 (00:08:dc:12:22:12)        (发送方MAC地址:00:08:dc:12:22:12)

    Sender IP address: 0.0.0.0               (发送方IP地址:未分配,用于探测)

    Target MAC address: 00:00:00_00:00:00 (00:00:00:00:00:00)      (目标MAC地址:全0,未指定)

    Target IP address: 192.168.1.105         (目标IP地址:192.168.1.105,探测对象)

|报文原文|

00 01 08 00 06 04 00 01 00 08 dc 12 22 12 00 00 00 00 00 00 00 00 00 00 c0 a8 01 69

ARP请求报文:

|报文解析|

Address Resolution Protocol (request)        (请求报文)

    Hardware type: Ethernet (1)              (硬件类型:1 表示以太网)

    Protocol type: IPv4 (0x0800)             (协议类型:0x0800 表示IPv4)

    Hardware size: 6                         (硬件地址长度:6字节)

    Protocol size: 4                         (协议地址长度:4字节)

    Opcode: request (1)                      (操作码:1 表示ARP请求)

    Sender MAC address: Wiznet_12:22:12 (00:08:dc:12:22:12)        (发送方MAC地址)

    Sender IP address: 192.168.1.105         (发送方IP地址:192.168.1.105)

    Target MAC address: 00:00:00_00:00:00 (00:00:00:00:00:00)      (未知目标设备的物理地址)

    Target IP address: 192.168.1.138         (目标IP地址:192.168.1.138,目标设备的IPv4地址)

|报文原文|

00 01 08 00 06 04 00 01 00 08 dc 12 22 12 c0 a8 01 69 00 00 00 00 00 00 c0 a8 01 8a

ARP响应报文:

|报文解析|

Address Resolution Protocol (reply)          (响应报文)

    Hardware type: Ethernet (1)              (硬件类型:1 表示以太网)

    Protocol type: IPv4 (0x0800)             (协议类型:0x0800 表示IPv4)

    Hardware size: 6                         (硬件地址长度:6字节)

    Protocol size: 4                         (协议地址长度:4字节)

    Opcode: reply (2)                        (操作码:2 表示ARP响应)

    Sender MAC address: HP_b1:37:11 (64:4e:d7:b1:37:11)        (发送方MAC地址:64:4e:d7:b1:37:11)

    Sender IP address: 192.168.1.138         (发送方IP地址:192.168.1.138)

    Target MAC address: Wiznet_12:22:12 (00:08:dc:12:22:12)            (目标MAC地址,ARP请求者的物理地址)

    Target IP address: 192.168.1.105         (目标IP地址:192.168.1.105ARP请求者的IPv4地址)

|报文原文|

00 01 08 00 06 04 00 02 64 4e d7 b1 37 11 c0 a8 01 8a 00 08 dc 12 22 12 c0 a8 01 69

9 实现过程

接下来,我们看看如何在W55MH32上实现ARP请求。

注意:测试实例需要PC端和W55MH32处于同一网段。

步骤1:在主循环中调用do_arp()函数,执行ARP请求流程


    while (1)
    {
        do_arp(SOCKET_ID, ethernet_buf, dest_ip);;
    }

do_arp()函数如下所示:

void do_arp(uint8_t sn, uint8_t *buf, uint8_t *dest_ip)
{
    uint16_t rlen       = 0;
    uint16_t local_port = 5000;
    uint16_t cnt        = 0;

    switch (getSn_SR(sn))
    {
    case SOCK_CLOSED:
        close(sn);
        socket(sn, Sn_MR_MACRAW, local_port, 0x00);
        break;
    case SOCK_MACRAW:
        arp_request(sn, local_port, dest_ip);

        while (1)
        {
            if ((rlen = getSn_RX_RSR(sn)) > 0)
            {
                arp_reply(sn, buf, rlen);
                break;
            }
            if (cnt > 1000)
            {
                printf("Request Time out.\r\n");
                cnt = 0;
                break;
            }
            else
            {
                cnt++;
                delay_ms(5);
            }
        }
        break;
    }
    if (arp_succ_flag)
        while (1);
}

进入该函数后,程序会执行一个状态机,当socket状态为关闭状态时开启一个MACRAW模式的socket。当socket成功打开为MAC RAW模式后,执行arp_request()函数发送ARP请求,然后进入一个循环,当成功接收到响应时,执行arp_reply()函数解析请求。当超过5秒未能得到响应时,则ARP请求失败。当arp_succ_flag标志位为1时,说明ARP请求成功。

arp_request()函数如下所示:

void arp_request(uint8_t sn, uint16_t port, uint8_t *dest_ip)
{
    uint16_t i;
    uint8_t  broadcast_addr[4] = {0xff, 0xff, 0xff, 0xff};

    for (i = 0; i < 6; i++)
    {
        pARPMSG.dst_mac[i] = 0xff; // Broadcast address in an Ethernet frame
        pARPMSG.tgt_mac[i] = 0x00;
        if (i < 4)
        {
            pARPMSG.tgt_ip[i] = dest_ip[i];
        }
    }
    getSHAR(pARPMSG.src_mac);              // Fill in the source MAC address of the link layer
    getSHAR(pARPMSG.sender_mac);           // Fill in the MAC address of the sender in ARP
    getSIPR(pARPMSG.sender_ip);            // Enter the IP address of the sender in ARP
    pARPMSG.msg_type = htons(ARP_TYPE);    // ARP type
    pARPMSG.hw_type  = htons(ETHER_TYPE);  // Ethernet type
    pARPMSG.pro_type = htons(PRO_TYPE);    // IP
    pARPMSG.hw_size  = HW_SIZE;            // 6
    pARPMSG.pro_size = PRO_SIZE;           // 4
    pARPMSG.opcode   = htons(ARP_REQUEST); // request: 0x0001;  reply: 0x0002

    if (sendto(sn, (uint8_t *)&pARPMSG, sizeof(pARPMSG), broadcast_addr, port) != sizeof(pARPMSG))
    {
        printf("Fail to send arp request packet.\r\n");
    }
    else
    {
        if (pARPMSG.opcode == htons(ARP_REQUEST))
        {
            printf("Who has %d.%d.%d.%d ?  Tell %d.%d.%d.%d\r\n", pARPMSG.tgt_ip[0], pARPMSG.tgt_ip[1], pARPMSG.tgt_ip[2], pARPMSG.tgt_ip[3],
                   pARPMSG.sender_ip[0], pARPMSG.sender_ip[1], pARPMSG.sender_ip[2], pARPMSG.sender_ip[3]);
        }
        else
        {
            printf("Opcode has wrong value. check opcode!\r\n");
        }
    }
}

在这个函数中,进行了ARP报文的组包以及发送。

arp_reply()函数如下所示:

void arp_reply(uint8_t sn, uint8_t *buff, uint16_t rlen)
{
    uint8_t  destip[4];
    uint16_t destport;
    uint8_t  ret_arp_reply[128];
    uint8_t  i;

    recvfrom(sn, (uint8_t *)buff, rlen, destip, &destport);

    if (buff[12] == ARP_TYPE_HI && buff[13] == ARP_TYPE_LO)
    {
        aAPRMSG = (ARPMSG *)buff;
        if ((aAPRMSG->opcode) == htons(ARP_REPLY))
        {
            for (i = 0; i < 4; i++)
            {
                if (aAPRMSG->tgt_ip[i] != pARPMSG.tgt_ip[i])
                {
                    break;
                }
                arp_succ_flag = 1;
            }
            memset(ret_arp_reply, 0x00, 128);
            sprintf((char *)ret_arp_reply, "%d.%d.%d.%d is at %.2x.%.2x.%.2x.%.2x.%.2x.%.2x\r\n",
                    aAPRMSG->sender_ip[0], aAPRMSG->sender_ip[1], aAPRMSG->sender_ip[2], aAPRMSG->sender_ip[3],
                    aAPRMSG->sender_mac[0], aAPRMSG->sender_mac[1], aAPRMSG->sender_mac[2], aAPRMSG->sender_mac[3],
                    aAPRMSG->sender_mac[4], aAPRMSG->sender_mac[5]);

            printf("%d.%d.%d.%d is at %.2x.%.2x.%.2x.%.2x.%.2x.%.2x\r\n",
                   aAPRMSG->sender_ip[0], aAPRMSG->sender_ip[1], aAPRMSG->sender_ip[2], aAPRMSG->sender_ip[3],
                   aAPRMSG->sender_mac[0], aAPRMSG->sender_mac[1], aAPRMSG->sender_mac[2], aAPRMSG->sender_mac[3],
                   aAPRMSG->sender_mac[4], aAPRMSG->sender_mac[5]);
        }
        else if ((aAPRMSG->opcode) == htons(ARP_REQUEST))
        {
            printf("Who has %d.%d.%d.%d ? Tell %.2x.%.2x.%.2x.%.2x.%.2x.%.2x\r\n",
                   aAPRMSG->tgt_ip[0], aAPRMSG->tgt_ip[1], aAPRMSG->tgt_ip[2], aAPRMSG->tgt_ip[3],
                   aAPRMSG->sender_mac[0], aAPRMSG->sender_mac[1], aAPRMSG->sender_mac[2], aAPRMSG->sender_mac[3],
                   aAPRMSG->sender_mac[4], aAPRMSG->sender_mac[5]);
        }
    }
    else
    {
        // printf("This message is not ARP reply: opcode is not 0x02!\r\n");
    }
}

在这个函数中,我们会将接收到的ARP报文进行校验,如果ARP报文为回复报文,并且回复的IP地址与我们请求的IP地址匹配时,将arp_succ_flag标志位置一,表示ARP请求成功。

10 运行结果

烧录例程运行后,首先可以看到进行了PHY链路检测,然后打印了设置的网络地址信息,然后是执行ARP请求以及请求结果,如下图所示:

11 总结

文讲解了如何在 W55MH32 芯片上通过 MAC RAW 模式实现 ARP 协议,将 IP 地址解析为 MAC 地址,通过实战例程展示了从发送 ARP 请求到接收并处理响应的完整过程。文章详细介绍了 MAC RAW 模式和 ARP 协议的概念、特点、工作流程、应用场景、安全风险及防护措施和报文格式,帮助读者理解其在局域网通信中的实际应用价值。

下一篇文章将聚焦 FTP 协议服务器模式,解析其核心原理及在文件传输中的应用,同时讲解如何在相关设备上搭建 FTP 服务器,敬请期待!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值