试验代码3:
#include <pcap.h>
#include <remote-ext.h>
int main() {
pcap_if_t* alldevs;
pcap_if_t* d;
int inum;
int i = 0;
pcap_t* adhandle;
int res;
char errbuf[PCAP_ERRBUF_SIZE];
struct tm* ltime;
char timestr[16];
struct pcap_pkthdr* header;
u_char* pkt_data;
/* Retrieve the device list on the local machine */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
fprintf(stderr, "Error in pcap_findalldevs: %s/n", errbuf);
exit(1);
}
/* Print the list */
for (d = alldevs; d; d = d->next)
{
printf("%d. %s", ++ i, d->name);
if (d->description)
{
printf(" (%s)/n", d->description);
}
else
{
printf(" (No description available)/n");
}
}
if (i == 0)
{
printf("/nNo interfaces found! Make sure Winpcap is installed./n");
return -1;
}
/* Select an adapter */
printf("Enter the interface number (1 - %d):", i);
scanf("%d", &inum);
if (inum < 1 || inum > i)
{
printf("/nInterface number out of range./n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
/* Jump to the selected adpater */
for (d = alldevs, i = 0; i < inum - 1; d = d->next, ++ i);
/* Open the device */
if ((adhandle = pcap_open(d->name, /* name of the device */
65536, /* portion of the packet to capture */
/* 65536 guarantees that the whole packet will be captured on all the link layers */
PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
1000, /* read timeout */
NULL, /* authentication on the remote machine */
errbuf /* error buffer */
)) == NULL)
{
fprintf(stderr, "/nUnable to open the adapter. %s is not supported by Winpcap/n", d->name);
/* Free the devices list */
pcap_freealldevs(alldevs);
return -1;
}
printf("/nlistening on %s .../n",d->description);
/* At this point, we don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
/* Retrieve the packets */
while ((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0)
{
if (res == 0)
{
/* Timeout elapsed */
continue;
}
/* convert the timestamp to readable format */
ltime = localtime(&header->ts.tv_sec);
strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);
printf("%s, %.6d len:%d/n", timestr, header->ts.tv_usec, header->len);
}
if (res == -1)
{
printf("Error reading the packets: %s/n", pcap_geterr(adhandle));
return -1;
}
return 1;
}
函数1:
pcap_next_ex(pcap_t* p,
struct pcap_pkthdr** pkt_header,
const u_char* pkt_data
)
从一个网络接口或离线捕获方式(例如读文件)读取一个数据包。该函数被用来重新获得下一个可用的数据包,没有使用libpcap提供的传统的回调方法。pcap_next_ex用指向头和下一个被捕获的数据包的指针为pkt_header和pkt_data参数赋值。
返回值有下列几种情况:
1,数据包被正确读取
0,pcap_open_live()设置的超时时间到。在这种情况下pkt_header和pkt_data不指向有效数据包
-1,发生错误
-2,离线捕获的时候读取到EOF
我们通常使用pcap_next_ex()而不是pcap_next(),因为pcap_next()有些缺点。首先,pcap_next()效率低,因为它隐藏了回调方法但是还是依赖于pcap_dispatch;第二,它不能检测EOF,所以当从一个文件获取数据包时它不是很有用。
函数2:
u_char* pcap_next(pcap_t* p,
struct pcap_pkthdr* h
)
返回下一个可用的数据包并且返回一个u_char指向该数据包数据部分的指针。如果发生错误或者活动的抓包没有读取到数据包(例如:数据包不能通过包过滤器而被丢弃,或者在支持读超时(read timeout)的平台上在任何数据包到来之前就超时终止,又或者是抓包设备的文件描述符在非阻塞(non-blocking)模式下并且没有数据包可以被读取),或者文件已被读完时返回NULL。不幸的是,没有办法检测是否发生错误。