【发布时间】:2016-12-27 10:41:49
【问题描述】:
我用 C 语言做了一个简单的 arp 请求程序。我根据我的 IP 和子网掩码生成一个主机列表,并为每个 ip 发送 arp 请求。最后,我收集结果并将响应的计算机 MAC 地址打印到屏幕上。
前言
我在C中使用libpcap实现来处理发送和接收数据包的过程。
首先我创建一个处理程序。
pcap_t pcapHandler;
if (!(pcapHandler = pcap_create(interfaceName, errorBuffer))) {
error(errorBuffer, EXIT_FAILURE);
}
if ((pcap_set_snaplen(pcapHandler, 64)) < 0) {
error(pcap_geterr(pcapHandler), EXIT_FAILURE);
}
if ((pcap_set_promisc(pcapHandler, 1)) < 0) {
error(pcap_geterr(pcapHandler), EXIT_FAILURE);
}
if ((pcap_set_timeout(pcapHandler, 0)) < 0) {
error(pcap_geterr(pcapHandler), EXIT_FAILURE);
}
if ((pcap_activate(pcapHandler)) < 0) {
error(pcap_geterr(pcapHandler), EXIT_FAILURE);
}
然后我附加一个过滤器以仅接收我的计算机的 arp 响应
struct bpf_program filter;
char *filter_string;
filter_string = makeMessage("ether dst %.2x:%.2x:%.2x:%.2x:%.2x:%.2x and "
"(arp or (ether[14:4]=0xaaaa0300 and "
"ether[20:2]=0x0806) or (ether[12:2]=0x8100 "
"and ether[16:2]=0x0806) or "
"(ether[12:2]=0x8100 and "
"ether[18:4]=0xaaaa0300 and "
"ether[24:2]=0x0806))",
interface_mac[0], interface_mac[1],
interface_mac[2], interface_mac[3],
interface_mac[4], interface_mac[5]);
if ((pcap_compile(pcapHandler, &filter, filter_string, 1, subnet_mask)) < 0) {
error(pcap_geterr(pcapHandler), EXIT_FAILURE);
}
if ((pcap_setfilter(pcapHandler, &filter)) < 0) {
error(pcap_geterr(pcapHandler), EXIT_FAILURE);
}
最后我使用一个用户定义的函数来准备 arp 请求。我只是打电话
sent = pcap_sendpacket(pcapHandler, ARPBuffer, ARPBufferLength);
if (sent < 0) {
error(pcap_geterr(pcapHandler), EXIT_FAILURE);
}
然后发送数据包。
我的问题是在接收 arp 响应的阶段(如果有的话)。
我使用for循环来迭代每个主机地址并发送一个arp数据包。
HE *currHost; // list of my current host informations.
for (currHost = hostListHead; currHost != NULL; currHost = currHost->next) {
printf("Testing: %s\n", inet_ntoa(currHost->addr));
// function that take the handler the current host details and my wireless interface I use to generate and send arp packages
sendARPRequest(pcapHandler, currHost, workingWI);
// dispatcher
pcap_dispatch(pcapHandler, -1, callback, NULL);
}
然后在回调函数中我得到响应并继续它。
问题
我的循环堆栈在每个主机上。假设我在某个不包含任何计算机的地址中发送了一个 arp 请求。我的程序不会继续到下一个主机,而是等待得到响应。只有当我从路由器收到响应时,程序才会继续使用另一台主机(为什么会这样?)
有没有办法设置超时?所以当我没有得到任何回应让我们说20 ms 继续下一个?但我不知道当客户端响应时我是否可以继续发送数据包。我的实现有问题吗?
更新
在 Gil 提出这是我使用的新代码之后,我又遇到了同样的问题:
pcap_t *pcapHandler;
void alarm_handler() {
pcap_breakloop(pcapHandler);
}
void startLocalMode(WI **workingWI) {
HE *hostListHead;
int numberOfHosts = generateHostList(&hostListHead, (*workingWI)->address, (*workingWI)->subnet_mask);
preparePCAPHandler(&pcapHandler, (*workingWI)->name);
setPCAPHandlerFilter(&pcapHandler, (*workingWI)->interface_mac, (*workingWI)->subnet_mask);
HE *currHost;
int i = 0;
for (currHost = hostListHead; i < numberOfHosts; currHost = currHost->next) {
sendARPRequest(pcapHandler, currHost, (*workingWI));
++i;
}
alarm(2);
signal(SIGALRM, alarm_handler);
pcap_loop(pcapHandler, 0, handleARPresponce, (u_char*)hostListHead);
}
这是回调函数:
#define ETHER_HDR_SIZE 14 /* Size of Ethernet frame header in bytes */
#define ARP_PKT_SIZE 28 /* Size of ARP Packet in bytes */
void handleARPresponce(u_char *args, const struct pcap_pkthdr *header, const u_char *packet_in) {
int n = header->caplen;
if (n < ETHER_HDR_SIZE + ARP_PKT_SIZE) {
//printw("%d byte packet too short to decode\n", n);
return;
}
arp_ether_ipv4 arpei;
ether_hdr frame_hdr;
struct in_addr source_ip;
HE *temp_cursor;
unsigned char extra_data[MAX_FRAME];
size_t extra_data_len;
int vlan_id;
int framing;
framing = unpackageARP(packet_in, n, &frame_hdr, &arpei, extra_data, &extra_data_len, &vlan_id);
source_ip.s_addr = arpei.spa;
temp_cursor = findHost((HE *)args, &source_ip);
if (temp_cursor) {
displayARPresponce(temp_cursor, &arpei, &frame_hdr);
}
return;
}
回调函数正确处理响应c(正如我所说,我从路由器收到请求发送到我的计算机)。现在我的代码怎么了?
【问题讨论】:
标签: c network-programming libpcap