arp(Address Resultion Protocol)地址解析协议,是通过解析网络层地址来找寻数据链路层地址。
arping命令功能类似于ping,能够通过发送arp数据包来查找某网络地址的MAC地址并测试一个IP地址是否是在网络上已经被使用,并能够获取更多设备信息。但不同于ping的是,arping命令基于ARP广播机制,所以arping命令只能测试同一网段或子网的网络主机的连通性,而ping命令则是基于ICMP协议,可以路由,所以使用ping命令可以测试任意网段的主机网络连通性。
需要注意的是,arp是TCP/IP协议族,但不属于IP协议,是独立的网络层协议。
arping源码链接:https://github.com/ThomasHabets/arping。阅读README,arping依赖libnet和libpcap。分别下载libnet和libpcap。
libnet源码链接:https://github.com/libnet/libnet。libnet是一个小型的接口函数库,主要用C语言写成,提供了低层网络数据报的构造、处理和发送功能。arping主要依赖libnet构建arp请求帧并发送。
libpcap源码链接:http://www.tcpdump.org。libpcap(Packet Capture Library)即数据包捕获函数库,是Unix/Linux平台下的网络数据包捕获函数库。它是一个独立于系统的用户层包捕获的API接口,为底层网络监测提供了一个可移植的框架。arping依赖libpcap捕获对端arp回复,获取相应信息。
libnet下载完源码后解压:
配置成功后编译并安装libnet,make install是为了便于移植arping。
编译libpcap命令如下:
在运行./configure时可能会提示“configure: error: Neither flex nor lex was found”,这是由于当前Linux环境未安装flex和bison程序生成工具导致,输入“sudo apt-get install flex”和“sudo apt-get install bison”进行安装即可。其它编译步骤类似,不再赘述。
执行以下命令,在src目录下生成可执行文件arping。
参照表格 3‑1,arping有如下选项。
表格 3‑1 arping选项
arping选项 |
含义 |
-0 |
源IP地址使用0.0.0.0 |
-a |
打印ping结果 |
-A |
只计算与请求的地址匹配的地址 |
-b |
源地址使用255.255.255.255 |
-c |
发送请求数量 |
-d |
重复地址检查 |
-h |
帮助信息 |
-i |
设定网络接口 |
-p |
打开接口的混合模式,当正在使用的MAC地址不是你自己的,请使用此模式。 |
-P |
发送arp答复而不是请求。与-U一起使用 |
-q |
只显示报错信息 |
-Q |
802.1p优先级。与-V一起使用。默认值为0 |
-s |
设定MAC源地址,可能要与-p一起使用 |
-t |
设定MAC目标地址 |
-U |
发送未经请求arp,用于更新邻居的arp缓存 |
-v |
打印等级 |
-V |
设置VLAN标记。默认为无VLAN标记 |
-w |
指定超时时间 |
-W |
ping间隔 |
如图 3‑1所示,执行arping获取虚拟网卡的MAC地址。
图 3‑1 测试arping
根据打印内容,程序捕获到arp回复帧并解析出MAC地址,该地址也与实际一致。至此Linux环境下arping编译完成。
首先构建arm架构的SylixOS base工程。注意到base工程中已有libpcap,只需移植libnet。
在SylixOS开发环境RealEvo-IDE中创建一个动态库工程libnet,移植需要手动修改makefile,设置工程属性为专家模式,如图 4‑1 所示。
为了不破坏源码工程的结构,将整个源码文件libnet_master都拷贝到工程目录,如图 4‑2所示。
参考Linux下makefile文件修改SylixOS工程libnet.mk文件,如图 4‑3所示,添加所需源文件。
并修改依赖的头文件路径,
注意修改libnet.mk时不要使用全局路径,使用相对路径和环境变量来保障代码可移植性。有多平台源文件/头文件时要根据需求选择,如图 4‑4 所示,添加Linux平台libnet_link.c文件。
配置完makefile再对libnet工程进行编译,根据编译报错信息修改工程文件。如图 4‑5 、图 4‑6所示,可使用SYLIXOS宏注释未定义宏。
如图 4‑7所示,编译通过后生成相应的.so和.a文件,upload到SylixOS设备。
考虑arping是一个应用程序,创建一个基于base的APP工程。
参照移植libnet步骤,将arping源码拷贝到工程目录下,根据Linux下生成的makefile修改IDE工程的arping.mk文件,包括头文件路径、源文件、依赖库等信息。
arping需要链接libnet和libpcap,如图 4‑8所示。
编译通过会生成arping可执行文件,upload到SylixOS设备。
运行arping测试。报错信息如图 4‑9所示:找不到hstrerror函数和gethostbyname2函数。
在workspace分别搜索gethostbyname2和hstrerror。
gethostbyname2需要添加SYLIXOS宏,使libnet中gethostbyname2函数定义生效,如图 4‑10所示。
搜索hstrerror,如图 4‑11所示,hstrerror函数在libcextern库中实现。
添加libcextern和相应的库文件路径,如图 4‑12所示。
修改完重新编译libnet并上传。
运行arping,报错信息如图 4‑13所示:设置广播失败,找不到函数定义。
查看libnet_open_link函数,如图4-14所示,设置socket广播使能失败导致报错。
arp协议是基于链路层,socket使用SOCK_RAW类型,而设置SO_BROADCAST接口只对datagram类型socket生效,因此setsockopt广播该函数非必要。
使用SYLIXOS屏蔽这段代码,如图 4‑14所示。
编译libnet并上传调试。报错信息如图 4‑15所示:写数据失败,返回-1(不支持的值)。
查找libnet_write_link函数,根据函数调用关系定位至协议栈packet_sendto。如图 4‑16所示,当socket类型为SOCK_RAW时,sll_hatype只支持ARPHRD_ETHER(1)。而sll_hatype值默认为0导致发送失败。
如图 4‑17所示,在libnet_write_link函数中设置socket为ARPHRD_ETHER类型。
编译libnet并上传测试。如图 4‑18所示,arping本地网卡IP获取到MAC地址,表明arping已成功移植到SylixOS平台。至此整个移植工作结束。
在移植前,需要对移植目标代码的框架、模块、使用方法有尽可能的认识,分析移植目标的可行性分析及相关依赖文件,利于后续移植过程中的功能裁剪、编译错误的解决和移植后的功能验证。
移植不修改内核源码,如有功能SylixOS暂未实现,可根据功能语义重写该函数,或者该功能非主要时可剪裁。