一、ARP Broadcast Enable简介
ARP Broadcast Enable是一种网络协议,它允许一个网络通信设备(如交换机或路由器)通告它所管理的每个端口的MAC地址。
默认情况下,当一个网络设备接入网络时,它会向所有其他设备广播一个ARP请求以验证自己的MAC地址。当其他设备回复时,设备之间会通过识别来获取一些信息,最终建立网络连接,以实现数据传输。
int arpBroadcastEnable=1;
ioctl(socket_fd, SIOCSARP, &arpBroadcastEnable);
二、ARP Broadcast Enable的作用
ARP Broadcast Enable只在一些特定的网络环境下非常有用,其中包括:
- 需要和其他位于同一网络中的设备通信的DevOps工程师能够利用ARP Broadcast Enable,跟踪设备到其物理地址的映射。
- 在排查网络问题时使用ARP Broadcast Enable,诊断网络设备是否能够接收来自其他设备的信息。
- 需要在网络上自动配置设备的MAC地址时使用ARP Broadcast Enable。
三、如何配置ARP Broadcast Enable
在C语言中,可以借助系统调用来配置ARP Broadcast Enable。例如,在Linux系统中,我们可以使用SIOCSARP命令来设置ARP Broadcast功能。下面是一个简单的示例代码:
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
int setArpBroadcastEnable(int socket_fd)
{
int arpBroadcastEnable=1;
int result=0;
result=ioctl(socket_fd, SIOCSARP, &arpBroadcastEnable);
if(result<0)
{
printf("ARP Broadcast Enable failed");
return -1;
}
return 0;
}
四、如何使用ARP Broadcast Enable
借助于ARP Broadcast Enable,我们可以轻松地获取所有与我们设备相连的MAC地址的映射关系。接下来是获取ARP表的示例代码:
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <ifaddrs.h>
#define MAX_IFACES 64
#define MAX_ADDR_LEN 6
#define ETH_P_ARP 0x0806
struct arpheader
{
uint16_t htype;
uint16_t ptype;
uint8_t hlen;
uint8_t plen;
uint16_t oper;
uint8_t sha[MAX_ADDR_LEN];
uint8_t spa[4];
uint8_t tha[MAX_ADDR_LEN];
uint8_t tpa[4];
};
struct arpentry
{
uint8_t macAddress[MAX_ADDR_LEN];
struct in_addr ipAddress;
};
struct arpentry arpTable[256];
int arpTableIndex=0;
int getARPTableFromDevice(const char* device, struct arpentry* arpTable, int maxEntries)
{
struct ifreq ifr;
struct ifconf ifc;
if(maxEntries>256) maxEntries=256;
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) return -1;
ifc.ifc_len = sizeof(struct ifreq) * MAX_IFACES;
ifc.ifc_req = (struct ifreq*) malloc(ifc.ifc_len);
if(ioctl(fd, SIOCGIFCONF, &ifc)<0) return -1;
int interfaceIndex=-1;
int i;
for (i = 0; i < ifc.ifc_len; i += sizeof(struct ifreq))
{
strcpy(ifr.ifr_name, ifc.ifc_req[i].ifr_name);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
{
if (strcmp(ifr.ifr_name, device) == 0)
{
interfaceIndex=ifr.ifr_ifindex;
break;
}
}
}
if(interfaceIndex==-1) return -1;
struct sockaddr_ll socket_address;
memset(&socket_address, 0, sizeof(socket_address));
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_ARP);
socket_address.sll_ifindex = interfaceIndex;
// Bind the interface to the raw socket
if (bind(fd, (struct sockaddr*) &socket_address, sizeof(socket_address)) < 0)
{
perror("bind failed\n");
return -1;
}
const int SIOCGARP_BUFFER_SIZE = 4096;
struct arpreq* arpRequest = (struct arpreq*) malloc(SIOCGARP_BUFFER_SIZE);
memset(arpRequest, 0, SIOCGARP_BUFFER_SIZE);
for (i = 0; i < 256; ++i)
{
struct arpreq* arpRequest = (struct arpreq*) (((char*)arpRequest)+i);
struct sockaddr_in* sin = (struct sockaddr_in *)&arpRequest->arp_pa;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = htonl(i);
strncpy ( arpRequest->arp_dev, device, IFNAMSIZ - 1);
if(ioctl(fd, SIOCGARP, arpRequest)<0) continue;
struct sockaddr_in* sin2 = (struct sockaddr_in *)&arpRequest->arp_ha;
struct arpentry* entry=&arpTable[arpTableIndex];
memcpy(entry->macAddress, arpRequest->arp_ha.sa_data, 6);
entry->ipAddress=sin->sin_addr;
arpTableIndex++;
if(arpTableIndex>maxEntries) break;
}
close(fd);
free(arpRequest);
return arpTableIndex;
}
五、ARP Broadcast Enable的缺点与注意事项
使用ARP Broadcast Enable时需要注意一下事项:
- ARP Broadcast Enable在交换机等大型网络设备的环境中使用时会很有用,但在小型网络环境中并不一定能提供什么帮助。
- 在网络通信方面,ARP Broadcast Enable能够为缓存命中率带来显著的提升。但由于一次广播会让所有位于网络上的设备都被激活,所以它也可能成为一种网络干扰源。
- 需要注意交换机上的ARP Broadcast Enable设置可能会对整个网络的性能产生影响。如果网络过于拥挤,就应该谨慎使用ARP Broadcast Enable以避免影响网络性能。