查询接口以使用 libpcap 查找设备
Querying Interfaces to find device with libpcap
好的,所以我的系统可以插入目标计算机上任意数量的以太网端口。我的目标是遍历每个设备,收集大约 20 个数据包,或者如果没有数据则跳过它,直到找到我要查找的数据,并且 select 该设备作为我的 "capture device" .看起来很简单。但是,我很快了解到,如果没有数据进入,libpcap 不会简单地超时。因此,我尝试使用 pcap_setnonblock 将我的捕获设备设置为非阻塞模式。但是,这会导致我阅读的目标端口完全崩溃。这是我的代码。愿意接受有关可能发生的事情的建议,或者甚至是更好的方法。谢谢
PS。 Type1 Type2变量名不要敲,是用来混淆的
pcap_if_t *alldevs;
pcap_if_t *d;
pcap_t *fp;
struct pcap_pkthdr *header;
const u_char *pkt_data;
char errbuf[PCAP_ERRBUF_SIZE];
const int FIND_DEVICE_PACKET_LIMIT = 20;
#ifdef WIN32
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
#else
if (pcap_findalldevs(&alldevs, errbuf) == -1)
#endif
{
cerr << "Error in pcap_findalldevs_ex: " << errbuf << endl;
return;
}
// For each device, capture until timeout
// or until a matching packet is found.
for(d=alldevs; d; d=d->next)
{
if ((fp = pcap_open_live(d->name,
1514 /*snaplen*/,
1 /*flags, 1=promiscuous, 0=not promiscuous*/,
20 /*read timeout*/,
errbuf)
) == NULL)
{
cerr << endl << "Unable to open the adapter." << endl;
continue;
}
int res = 0;
int packetCounter = 0;
pcap_setnonblock(fp, true, errbuf);
// Capture at most FIND_DEVICE_PACKET_LIMIT packets
// to determine whether scanner is sending packets
// or no scanner found.
while ((res = pcap_next_ex(fp, &header, &pkt_data)) >=0) {
struct iphdr *iph = (struct iphdr *)(pkt_data + sizeof(struct ethhdr));
struct udphdr *udph = (struct udphdr*)(pkt_data + (iph->ihl*4) + sizeof(struct ethhdr));
u_int destPort = ntohs(udph->dest);
if (destPort==TYPE1_DATA_PORT || destPort==TYPE1_GPS_PORT) {
detectedScanners->type1 = true;
} else if (destPort==TYPE2_DATA_PORT || destPort==TYPE2_STATUS_PORT || destPort==TYPE2_NMEA_PORT) {
detectedScanners->type2 = true;
}
if (++packetCounter > FIND_DEVICE_PACKET_LIMIT) {
break;
}
}
if (detectedScanners->type1==true || detectedScanners->type2==true) {
*interface = d->name;
break;
}
}
在非阻塞模式下,如果没有数据包可读取,pcap_next_ex()
将 return 0,并且将 NOT return任何数据包信息,因此,如果它 returned 为 0,您应该 而不是 查看 header
或 packet_data
指向的任何内容。
即做
while ((res = pcap_next_ex(fp, &header, &pkt_data)) >=0) {
if (res != 0) {
struct iphdr *iph = (struct iphdr *)(pkt_data + sizeof(struct ethhdr));
struct udphdr *udph = (struct udphdr*)(pkt_data + (iph->ihl*4) + sizeof(struct ethhdr));
u_int destPort = ntohs(udph->dest);
if (destPort==TYPE1_DATA_PORT || destPort==TYPE1_GPS_PORT) {
detectedScanners->type1 = true;
} else if (destPort==TYPE2_DATA_PORT || destPort==TYPE2_STATUS_PORT || destPort==TYPE2_NMEA_PORT) {
detectedScanners->type2 = true;
}
if (++packetCounter > FIND_DEVICE_PACKET_LIMIT) {
break;
}
}
}
但是请注意,您的程序将不断旋转,在该循环中消耗 CPU,永远。这意味着您永远不会错过第一台设备。
您可能真正想做的是:
- 打开所有个设备,将它们的
pcap_t *
放入一个数组中,并设置为非阻塞模式;
- 对于每个设备,在 UN*X 上调用
pcap_get_selectable_fd()
并在 Windows 上调用 pcap_getevent()
,并将该调用的结果保存到数组中(您可以使用并行数组, 或以 pcap_t *
和 int
或 HANDLE
作为成员的结构数组);
- 在循环中,对 UN*X 上
pcap_get_selectable_fd()
的所有 int
或对所有 WaitForMultipleObjects()
使用 select()
或 poll()
来自 Windows 上 pcap_getevent()
的 HANDLE
s,当 select()
/poll()
/WaitForMultipleObjects()
returns 时,尝试读取数据包来自每个的pcap_t *
s使用pcap_next_ex()
,如果你得到一个数据包就处理它。
这样,您就可以并行扫描所有设备,并且不会旋转 CPU。
好的,所以我的系统可以插入目标计算机上任意数量的以太网端口。我的目标是遍历每个设备,收集大约 20 个数据包,或者如果没有数据则跳过它,直到找到我要查找的数据,并且 select 该设备作为我的 "capture device" .看起来很简单。但是,我很快了解到,如果没有数据进入,libpcap 不会简单地超时。因此,我尝试使用 pcap_setnonblock 将我的捕获设备设置为非阻塞模式。但是,这会导致我阅读的目标端口完全崩溃。这是我的代码。愿意接受有关可能发生的事情的建议,或者甚至是更好的方法。谢谢
PS。 Type1 Type2变量名不要敲,是用来混淆的
pcap_if_t *alldevs;
pcap_if_t *d;
pcap_t *fp;
struct pcap_pkthdr *header;
const u_char *pkt_data;
char errbuf[PCAP_ERRBUF_SIZE];
const int FIND_DEVICE_PACKET_LIMIT = 20;
#ifdef WIN32
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
#else
if (pcap_findalldevs(&alldevs, errbuf) == -1)
#endif
{
cerr << "Error in pcap_findalldevs_ex: " << errbuf << endl;
return;
}
// For each device, capture until timeout
// or until a matching packet is found.
for(d=alldevs; d; d=d->next)
{
if ((fp = pcap_open_live(d->name,
1514 /*snaplen*/,
1 /*flags, 1=promiscuous, 0=not promiscuous*/,
20 /*read timeout*/,
errbuf)
) == NULL)
{
cerr << endl << "Unable to open the adapter." << endl;
continue;
}
int res = 0;
int packetCounter = 0;
pcap_setnonblock(fp, true, errbuf);
// Capture at most FIND_DEVICE_PACKET_LIMIT packets
// to determine whether scanner is sending packets
// or no scanner found.
while ((res = pcap_next_ex(fp, &header, &pkt_data)) >=0) {
struct iphdr *iph = (struct iphdr *)(pkt_data + sizeof(struct ethhdr));
struct udphdr *udph = (struct udphdr*)(pkt_data + (iph->ihl*4) + sizeof(struct ethhdr));
u_int destPort = ntohs(udph->dest);
if (destPort==TYPE1_DATA_PORT || destPort==TYPE1_GPS_PORT) {
detectedScanners->type1 = true;
} else if (destPort==TYPE2_DATA_PORT || destPort==TYPE2_STATUS_PORT || destPort==TYPE2_NMEA_PORT) {
detectedScanners->type2 = true;
}
if (++packetCounter > FIND_DEVICE_PACKET_LIMIT) {
break;
}
}
if (detectedScanners->type1==true || detectedScanners->type2==true) {
*interface = d->name;
break;
}
}
在非阻塞模式下,如果没有数据包可读取,pcap_next_ex()
将 return 0,并且将 NOT return任何数据包信息,因此,如果它 returned 为 0,您应该 而不是 查看 header
或 packet_data
指向的任何内容。
即做
while ((res = pcap_next_ex(fp, &header, &pkt_data)) >=0) {
if (res != 0) {
struct iphdr *iph = (struct iphdr *)(pkt_data + sizeof(struct ethhdr));
struct udphdr *udph = (struct udphdr*)(pkt_data + (iph->ihl*4) + sizeof(struct ethhdr));
u_int destPort = ntohs(udph->dest);
if (destPort==TYPE1_DATA_PORT || destPort==TYPE1_GPS_PORT) {
detectedScanners->type1 = true;
} else if (destPort==TYPE2_DATA_PORT || destPort==TYPE2_STATUS_PORT || destPort==TYPE2_NMEA_PORT) {
detectedScanners->type2 = true;
}
if (++packetCounter > FIND_DEVICE_PACKET_LIMIT) {
break;
}
}
}
但是请注意,您的程序将不断旋转,在该循环中消耗 CPU,永远。这意味着您永远不会错过第一台设备。
您可能真正想做的是:
- 打开所有个设备,将它们的
pcap_t *
放入一个数组中,并设置为非阻塞模式; - 对于每个设备,在 UN*X 上调用
pcap_get_selectable_fd()
并在 Windows 上调用pcap_getevent()
,并将该调用的结果保存到数组中(您可以使用并行数组, 或以pcap_t *
和int
或HANDLE
作为成员的结构数组); - 在循环中,对 UN*X 上
pcap_get_selectable_fd()
的所有int
或对所有WaitForMultipleObjects()
使用select()
或poll()
来自 Windows 上pcap_getevent()
的HANDLE
s,当select()
/poll()
/WaitForMultipleObjects()
returns 时,尝试读取数据包来自每个的pcap_t *
s使用pcap_next_ex()
,如果你得到一个数据包就处理它。
这样,您就可以并行扫描所有设备,并且不会旋转 CPU。