LibPCap pcap_loop() 不返回任何数据包
我的C程序有问题,一切都很好,直到我开始捕获数据包为止。它应该登录,但是PCAP_LOOP()中的处理程序void没有。另外,当传递到PCAP Create void中时,我在第98行上的输入中还有另一个问题,它不会通过名称找到接口。当我对字符串进行编码时,它可以正常工作。
/*
Compile and run it using GCC ->
gcc main.c -o output -L/usr/include -lpcap && ./output
*/
#include <stdio.h>
#include <pcap.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define __NEWLINE__ "\r\r\n"
#define __SEPARATOR__ "------------------------"
/*
Print all flags in human readable string
instead of hexadecimal number
*/
char* get_interface_flags(bpf_u_int32* decimal_flags) {
char* flag_string = (char*)malloc(sizeof(char) * 30);
strcpy(flag_string, "\0");
const int flag_names[9] = {
PCAP_IF_LOOPBACK,
PCAP_IF_UP,
PCAP_IF_RUNNING,
PCAP_IF_WIRELESS
};
const char* flag_values[9] = {
"LOOPBACK",
"UP",
"RUNNING",
"WIRELESS"
};
for (size_t i = 0; i < (sizeof(flag_names) / sizeof(flag_names[0])); i++)
{
if(flag_names[i] & *decimal_flags) {
if(strlen(flag_string) != 0) strcat(flag_string, ", ");
strcat(flag_string, flag_values[i]);
}
}
return flag_string;
}
/*
Print available information about network interface
This recursive function can be called again
if there is more than one interface present
*/
void print_interface(pcap_if_t* device) {
// Device parameters
bpf_u_int32* flags = &device->flags;
char* device_name = device->name;
char* device_desc = device->description;
char* flags_string = get_interface_flags(flags);
// Device addresses
pcap_addr_t* addr = device->addresses;
// We'll print devices with only 1 flag or more to avoid interfaces that aren't up
if(strlen(flags_string) != 0) {
fprintf(stdout, "%s: FLAGS(%lu)<%s>%s", device_name, strlen(flags_string), flags_string, __NEWLINE__);
fprintf(stdout, "%s%s", device_desc, __NEWLINE__);
fprintf(stdout, "%s%s", __SEPARATOR__, __NEWLINE__);
}
// Check if there is another device to print, if so call the recursive function again
if(device[0].next != NULL) print_interface(device->next);
free(flags_string);
}
// Let user select the network interface that will capture packets
char* get_selected_interface() {
char* selected_interface = (char*)malloc(sizeof(char) * 20);
char* device_name;
char* ip_addr;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t* alldevs;
// Get all available network interfaces, returns PCAP_ERROR on failure or 0 on success
int devices_succefully_returned = pcap_findalldevs(&alldevs, errbuf);
// If there was an error while fetching interfaces, return empty char
if(devices_succefully_returned == PCAP_ERROR) {
printf("%s", errbuf);
return '\0';
}
print_interface(alldevs);
fprintf(stdout, "Name of the network interface to use: ");
fgets(selected_interface, 20, stdin);
return selected_interface;
}
void captured_packet(u_char *args, const struct pcap_pkthdr *hdr, const u_char *pkt) {
fprintf(stdout, "log");
}
void capture(char* device) {
char* errbuf[PCAP_ERRBUF_SIZE];
/*
Will create a packet capture handle
Returns NULL if handle can't be created, in this case
we'll print out the error buffer and exit the program with 1 status code
*/
pcap_t* created = pcap_create("eth0", *errbuf);
if(created == NULL) {
fprintf(stderr, "%s%s", *errbuf, __NEWLINE__);
return exit(EXIT_FAILURE);
};
int activation_status = pcap_activate(created);
if(activation_status == PCAP_ERROR || activation_status != 0) {
fprintf(stderr, "%s", pcap_geterr(created));
exit(EXIT_FAILURE);
}
/*
Interface was activated so start capturing incoming packets
capture_packet will handle incoming packets.
We'll capture infinite amount of packets unless user provides a count
*/
fprintf(stdout, "Interface activated!%s", __NEWLINE__);
int loop_status = pcap_loop(created, -1, captured_packet, NULL);
switch (loop_status)
{
case PCAP_ERROR_BREAK:
fprintf(stderr, "Loop was finished beacause of breakloop that was called.");
break;
case PCAP_ERROR_NOT_ACTIVATED:
fprintf(stderr, "Device wasn't activated before it started capturing.");
break;
case 0:
fprintf(stderr, "Loop was terminated due to exhaustion of count");
break;
default:
fprintf(stderr, "Some error happened while trying to loop through packets -> %s", pcap_geterr(created));
break;
}
// Program was successfully closed, exit..
pcap_close(created);
exit(0);
}
int main(int argc, char **argv) {
if(getuid() != 0) {
fprintf(stderr, "Please make sure to run this tool as root!%s", __NEWLINE__);
return 1;
}
char* selected = get_selected_interface();
capture(selected);
free(selected);
return 0;
}
我尝试了所有内容,它应该记录“ ETH0”接口上的无限数量数据包,但什么也不会发生。
I have problem with my C program, everything is fine until I start capturing packets. It should log, but the handler void in pcap_loop() isn't. Also I have another problem with the input in fgets on line 98 when it gets passed into the pcap create void it will not find the interface by the name. When I hardcode the string it works.
/*
Compile and run it using GCC ->
gcc main.c -o output -L/usr/include -lpcap && ./output
*/
#include <stdio.h>
#include <pcap.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define __NEWLINE__ "\r\r\n"
#define __SEPARATOR__ "------------------------"
/*
Print all flags in human readable string
instead of hexadecimal number
*/
char* get_interface_flags(bpf_u_int32* decimal_flags) {
char* flag_string = (char*)malloc(sizeof(char) * 30);
strcpy(flag_string, "\0");
const int flag_names[9] = {
PCAP_IF_LOOPBACK,
PCAP_IF_UP,
PCAP_IF_RUNNING,
PCAP_IF_WIRELESS
};
const char* flag_values[9] = {
"LOOPBACK",
"UP",
"RUNNING",
"WIRELESS"
};
for (size_t i = 0; i < (sizeof(flag_names) / sizeof(flag_names[0])); i++)
{
if(flag_names[i] & *decimal_flags) {
if(strlen(flag_string) != 0) strcat(flag_string, ", ");
strcat(flag_string, flag_values[i]);
}
}
return flag_string;
}
/*
Print available information about network interface
This recursive function can be called again
if there is more than one interface present
*/
void print_interface(pcap_if_t* device) {
// Device parameters
bpf_u_int32* flags = &device->flags;
char* device_name = device->name;
char* device_desc = device->description;
char* flags_string = get_interface_flags(flags);
// Device addresses
pcap_addr_t* addr = device->addresses;
// We'll print devices with only 1 flag or more to avoid interfaces that aren't up
if(strlen(flags_string) != 0) {
fprintf(stdout, "%s: FLAGS(%lu)<%s>%s", device_name, strlen(flags_string), flags_string, __NEWLINE__);
fprintf(stdout, "%s%s", device_desc, __NEWLINE__);
fprintf(stdout, "%s%s", __SEPARATOR__, __NEWLINE__);
}
// Check if there is another device to print, if so call the recursive function again
if(device[0].next != NULL) print_interface(device->next);
free(flags_string);
}
// Let user select the network interface that will capture packets
char* get_selected_interface() {
char* selected_interface = (char*)malloc(sizeof(char) * 20);
char* device_name;
char* ip_addr;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t* alldevs;
// Get all available network interfaces, returns PCAP_ERROR on failure or 0 on success
int devices_succefully_returned = pcap_findalldevs(&alldevs, errbuf);
// If there was an error while fetching interfaces, return empty char
if(devices_succefully_returned == PCAP_ERROR) {
printf("%s", errbuf);
return '\0';
}
print_interface(alldevs);
fprintf(stdout, "Name of the network interface to use: ");
fgets(selected_interface, 20, stdin);
return selected_interface;
}
void captured_packet(u_char *args, const struct pcap_pkthdr *hdr, const u_char *pkt) {
fprintf(stdout, "log");
}
void capture(char* device) {
char* errbuf[PCAP_ERRBUF_SIZE];
/*
Will create a packet capture handle
Returns NULL if handle can't be created, in this case
we'll print out the error buffer and exit the program with 1 status code
*/
pcap_t* created = pcap_create("eth0", *errbuf);
if(created == NULL) {
fprintf(stderr, "%s%s", *errbuf, __NEWLINE__);
return exit(EXIT_FAILURE);
};
int activation_status = pcap_activate(created);
if(activation_status == PCAP_ERROR || activation_status != 0) {
fprintf(stderr, "%s", pcap_geterr(created));
exit(EXIT_FAILURE);
}
/*
Interface was activated so start capturing incoming packets
capture_packet will handle incoming packets.
We'll capture infinite amount of packets unless user provides a count
*/
fprintf(stdout, "Interface activated!%s", __NEWLINE__);
int loop_status = pcap_loop(created, -1, captured_packet, NULL);
switch (loop_status)
{
case PCAP_ERROR_BREAK:
fprintf(stderr, "Loop was finished beacause of breakloop that was called.");
break;
case PCAP_ERROR_NOT_ACTIVATED:
fprintf(stderr, "Device wasn't activated before it started capturing.");
break;
case 0:
fprintf(stderr, "Loop was terminated due to exhaustion of count");
break;
default:
fprintf(stderr, "Some error happened while trying to loop through packets -> %s", pcap_geterr(created));
break;
}
// Program was successfully closed, exit..
pcap_close(created);
exit(0);
}
int main(int argc, char **argv) {
if(getuid() != 0) {
fprintf(stderr, "Please make sure to run this tool as root!%s", __NEWLINE__);
return 1;
}
char* selected = get_selected_interface();
capture(selected);
free(selected);
return 0;
}
I tried everything, it should log unlimited number of packets on the "eth0" interface but nothing happens.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
引用PCAP(3PCAP)MAN页面:
以及PCAP_SET_TIMEOUT(3PCAP)MAN PAGE:
您还没有拨打
PCAP_SET_SET_TIMEOUT()
;在某些平台上,这可能导致pcap_loop()
等到整个数据包的完整缓冲区,这可能需要大量时间。将超时设置为100,这意味着100毫秒或十分之一。
引用fgets(3)人页面(这是在MacOS上,您可能会在Linux上使用“ ETH0”名称,但是我从MAN页面引用的所有内容都适用于MacOS,Linux,Linux,和其他Un*Xes):
这里的重要部分是“保留了新线(如果有的话)。 - 这意味着,如果用户键入“ ETH0”然后键入返回键,则读取的字符串将为“ ETH0 \ n”,配备Newline字符。接口的名称是“ eth0”,而不是“ eth0 \ n”;在使用字符串之前,您将必须从字符串中删除任何尾随的新线。
To quote the pcap(3PCAP) man page:
and the pcap_set_timeout(3PCAP) man page:
You haven't called
pcap_set_timeout()
; on some platforms, that can causepcap_loop()
to wait until it gets an entire buffer full of packet, which could take a significant amount of time.Set the timeout to 100, which means 100 milliseconds or a tenth of a second.
To quote the fgets(3) man page (this is on macOS, and you're probably working on Linux, given the "eth0" name, but all of the stuff I'm quoting from the man pages applies to macOS, Linux, and other UN*Xes):
The important part here is "The newline, if any, is retained." - this means that, if the user types "eth0" and then hits the Return key, the string read in will be "eth0\n", complete with a newline character. The name of the interface is "eth0", not "eth0\n"; you will have to remove any trailing newline from the string before using it.