gpt4 book ai didi

linux - 如何使用 libpcap 实现 tcpdump -i interface arp

转载 作者:太空狗 更新时间:2023-10-29 12:28:08 33 4
gpt4 key购买 nike

我想在我的 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/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com