- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想在我的 ubuntu 上执行命令 tcpdump -i eth0 arp
来观察接口(interface) eth0 上的 arp 数据包。我用的是libpcap,但是函数pcap_next_ex
的返回值一直是0。同时配合tcpdump -i eth0 arp
,可以观察到arp包。
/*
* compile(root): gcc test.c -lpcap
* run : ./a.out
* output : time out
* time out
* time out
* ...
*/
#include <pcap.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define ARP_REQUEST 1
#define ARP_REPLY 2
typedef struct arp_hdr_s arp_hdr_t;
struct arp_hdr_s {
u_int16_t htype;
u_int16_t ptype;
u_char hlen;
u_char plen;
u_int16_t oper;
u_char sha[6];
u_char spa[4];
u_char tha[6];
u_char tpa[4];
};
#define MAXBYTES2CAPTURE 2048
int
main(int argc, char **argv)
{
char err_buf[PCAP_ERRBUF_SIZE];
const unsigned char *packet;
int i;
int ret;
arp_hdr_t *arp_header;
bpf_u_int32 net_addr;
bpf_u_int32 mask;
pcap_t *desrc;
struct pcap_pkthdr *pkthdr;
struct bpf_program filter;
net_addr = 0;
mask = 0;
memset(err_buf, 0, PCAP_ERRBUF_SIZE);
desrc = pcap_open_live("eth0", MAXBYTES2CAPTURE, 0, 512, err_buf);
if (desrc == NULL) {
fprintf(stderr, "error: %s\n", err_buf);
exit(-1);
}
ret = pcap_lookupnet("eth0", &net_addr, &mask, err_buf);
if (ret < 0) {
fprintf(stderr, "error: %s\n", err_buf);
exit(-1);
}
ret = pcap_compile(desrc, &filter, "arp", 1, mask);
if (ret < 0) {
fprintf(stderr, "error: %s\n", pcap_geterr(desrc));
exit(-1);
}
ret = pcap_setfilter(desrc, &filter);
if (ret < 0) {
fprintf(stderr, "errnor: %s\n", pcap_geterr(desrc));
exit(-1);
}
while (1) {
ret = pcap_next_ex(desrc, &pkthdr, &packet);
if (ret == -1) {
printf("%s\n", pcap_geterr(desrc));
exit(1);
} else if (ret == -2) {
printf("no more\n");
} else if (ret == 0) { // here
printf("time out\n");
continue;
}
arp_header = (arp_hdr_t *)(packet + 14);
if (ntohs(arp_header->htype) == 1 && ntohs(arp_header->ptype == 0x0800)) {
printf("src IP: ");
for (i = 0; i < 4; i++) {
printf("%d.", arp_header->spa[i]);
}
printf("dst IP: ");
for (i = 0; i < 4; i++) {
printf("%d.", arp_header->tpa[i]);
}
printf("\n");
}
}
return 0;
}
最佳答案
无需深入了解您的代码,我就能看出一个主要问题:
在您使用 pcap_open_live()
时,您没有设置混杂模式:第三个参数应该是非零的。如果 ARP 请求不是针对您的接口(interface) IP,如果没有混杂模式,pcap 将看不到它。 tcpdump
会,除非使用 --no-promiscuous-mode
特别告知不要这样做,否则请使用 promisc(因此需要 CAP_NET_ADMIN
特权,您将通过 sudo
获得,您的程序也需要它)。
旁注:
1/泄漏:您可能想在 pcap_setfilter()
之后使用 pcap_freecode()
释放过滤器。
2/我假设你已经阅读了这里的官方教程:
http://www.tcpdump.org/pcap.html
...如果不是这种情况,您最好先这样做。我引用:
A note about promiscuous vs. non-promiscuous sniffing: The two techniques are very different in style. In standard, non-promiscuous sniffing, a host is sniffing only traffic that is directly related to it. Only traffic to, from, or routed through the host will be picked up by the sniffer. Promiscuous mode, on the other hand, sniffs all traffic on the wire. In a non-switched environment, this could be all network traffic. [... more stuff on promisc vs non-promisc]
编辑:
实际上,与我在生产级别(内部和客户)运行了 +1 年的代码相比,更深入地查看您的代码,我可以看到更多可能出错的地方:
pcap_create()
pcap_set_promisc()
,我们已经讨论过了pcap_activate()
,这可能是这里的核心问题...pcap 对于首先获取 pcap_t 句柄然后对其进行操作的操作顺序非常敏感。
目前,我能给你的最好建议是:否则这将是你我之间的实时调试 session :
1/阅读并使用官方教程中的代码进行调整:
http://www.tcpdump.org/pcap.html
这是强制性的。
2/FWIW,我的 - 绝对有效 - 操作顺序是这样的:
pcap_lookupnet()
pcap_create()
pcap_set_promisc()
pcap_set_snaplen()
,您可能需要也可能不需要pcap_set_buffer_size()
,您可能需要也可能不需要pcap_activate()
附注:非常重要:首先激活,然后从 PCAP_SETNONBLOCK(3PCAP) 设置非阻塞:首次使用 pcap_activate() 激活或使用 pcap_open_live() 打开时,捕获句柄未处于 非阻塞模式'';需要调用 pcap_set-nonblock() 才能将其置于
非阻塞模式。...然后,因为我不使用发臭的阻塞/超时阻塞,忙循环:
pcap_setnonblock()
pcap_get_selectable_fd()
...然后并且只有那时: - pcap_compile()
- 随后是 pcap_setfilter()
- 然后正如我提到的 pcap_freecode()
- 然后是我从 pcap_get_selectable_fd()
到 pcap_dispatch()
的文件'des' 上的 select() 或系列,但这是另一个主题。
pcap
是一个可以追溯到 80 年代的旧 API,它确实非常非常敏感。但不要气馁!太棒了 - 一旦你做对了。
关于linux - 如何使用 libpcap 实现 tcpdump -i interface arp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35809730/
我的程序像这样使用 libpcap: while pcaket = pcap_next() { ... (modify the pcaket and do checksum) ... pcap_sen
我正在为一个流量非常大的网络编写监控程序(高清视频通过网络流式传输)。大多数数据包都非常大,我只想查看 header (仅限 IP 和 UDP/TCP)。当然,我想避免复制整个数据的开销。 libpc
我对原始套接字和 libcap 的使用感到有点困惑。任何人都可以简单地指出使用两者的优点。我读了几个链接,但是,它让我感到困惑。 最佳答案 libpcap 在不同的操作系统上使用不同的机制。在 Lin
我在项目中看到了这种代码: while (1) { l_numPkts = pcap_next_ex( m_pcapHandle, &header, &pkt_data); //do some
我想使用 libpcap 使用 gcc 选项 -m32 将 .c 文件编译为 32 位可执行文件机器是linux 64位 fedora 16 但是,我收到以下错误 [root@fdf source]#
我只想从我的系统中嗅探传出的“TCP-ACK”数据包。因此,我在 lib-pcap 程序中将过滤器表达式设置为: char filter_exp[] = "src host 172.16.0.1 an
我正在尝试使用交叉编译器 arm-linux-gcc 编译 libpcap。当我运行“make”时出现错误: ./pcap-linux.c:254:14: conflicting types for
我正在编写相当简单的pcap“实时”捕获引擎,但是pcap_dispatch的数据包处理回调实现应花费相对较长的时间进行处理。 pcap是否在单独的线程中运行每个“pcap_handler”回调?如果
我正在使用 lib-pcap 库来安装/卸载过滤器。 为了安装 pcap 过滤器,我使用pcap_compile 后接 pcap_setfilter,效果很好。 对于卸载过滤器,我使用 pcap_fr
pcap_next 是否显示已发送的数据包? 例如:如果我在 libpcap 监听数据包时 ping google.com,然后运行 pcap_next 两次,返回的值将都是数据包,还是其中一个为
我正在尝试使用 libpcap 打印确认号。我确实知道我会得到与我在 pcap 文件中看到的不同的确认号。我的问题是,在 pcap 文件中,编号为 10、11 和 12 的数据包具有不同的 ack 编
我是 libpcap 的新手。 我正在使用这个库来捕获数据包,下面是我编写的捕获数据包的代码。 我正在窃听的接口(interface)总是充满arp数据包,因此总是有数据包到达该接口(interfac
使用 pcap,我声明了 rtp 结构,当我尝试指向数据包的这个区域时,我发现根据我的声明,它以不同的方式工作。 我写的是: struct udphdr *udp; struct rtphdr *rt
我想拦截来自用户空间的网络流量,所以我使用了 libpcap API 来捕获 tcp/ip 数据包。现在我只是在注册的回调中捕获有关数据包 header 和有效负载的信息。我如何使用此回调来阻止流量或
有人可以给我指出一个好的起点来了解 libpcap 如何从网络驱动程序获取数据包吗?我打算用快速实现替换接收函数。 最佳答案 “接收函数”是: 标准驱动程序接收函数,与用于接收数据包并将其交给常规网络
我用库 libpcap(Ubuntu, c) 捕获了信标帧 我将 wlan 模式更改为通过以下函数调用进行监控和捕获 // 3000 is large enough number for test p
我正在使用 libpcap 捕获特定端口上的所有数据包。但是我需要分开并清楚地知道我的设备正在发送哪些数据包,以及它正在接收哪些数据包。实际上,我使用 pcap_close() 来捕获数据包,而且效果
我正在尝试用 C 解析一个 pcap 文件。我不想使用 libpcap。但出于某种原因,我无法做到。你知道我该怎么做吗?这是我的尝试: fseek(f,24,0); while(countcaplen
我遇到了以下情况:我用 pcap_open_live() 打开我的网络接口(interface)之一。然后我正在为 pcap 编译一个过滤器,只捕获指定的以太网类型(ether proto 0x123
我正在尝试编写一个 c++ 应用程序 (linux) 来捕获无线数据包以及相关的信号强度(以 dBm 为单位)。捕获部分很简单,但问题是我找不到任何关于如何获取每个数据包信号强度的文档。 它是标题的一
我是一名优秀的程序员,十分优秀!