从libpcap捕获的数据包中获取错误的ip和端口号

时间:2012-11-21 22:39:54

标签: c libpcap

我的Ubuntu虚拟机的IP地址是192.168.1.110。其他一切看起来都不错。我不知道代码有什么问题。也许我使用了错误的包头结构? 下面是我的代码和输出。我的主机IP应该是192.168.1.110,现在的端口肯定是错误的。

sudo ./sniffall 0
84.72.137.105:38055  192.168.1.105:56652
192.168.1.105:56652  174.141.213.124:28073
84.72.137.105:38055  192.168.1.105:56652
192.168.1.105:56652  174.141.213.124:28073
84.72.137.105:38055  192.168.1.105:56652


#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ether.h>
#include <sys/socket.h>
#include <netinet/tcp.h>

void getPacket(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *packet){
    struct ip *ip;
    struct tcphdr *tcp;
    ip = (struct ip*)(packet+sizeof(struct ether_header));
    tcp = (struct tcphdr*)(packet+sizeof(struct ether_header)+sizeof(struct ip));

    char* src = inet_ntoa(ip->ip_src);

    printf("%s:%d ",src,tcp->source);
    char* dst = inet_ntoa(ip->ip_dst);
    printf(" %s:%d\n", dst, tcp->dest);

}

int main(int argc, char *argv[]){
    char errbuf[PCAP_ERRBUF_SIZE], *device;
    device = argv[1];
    pcap_t *handle;
    handle = pcap_open_live(device, BUFSIZ, 1, 1000, errbuf);
    if(!handle){
        device = pcap_lookupdev(errbuf);
        handle = pcap_open_live(device, BUFSIZ, 1, 1000, errbuf);
        if(!handle){
                printf("Couldn't open device %s: %s\n", device, errbuf);
        }
    }

    pcap_loop(handle, 5, getPacket, NULL);
    return 0;
}

2 个答案:

答案 0 :(得分:2)

如果您处于混杂模式,Pcap将显示除系统之外的其他一些流量。为什么您看到未从系统发送或接收的特定数据包将依赖于您的网络配置。有些以太网交换机偶尔会泄漏发往其他系统的数据包,如果他们不确定应该去哪里,等等。

您还需要在字节顺序之间进行转换。在现在最常见的情况下,&#34;网络字节顺序&#34;与机器的字节顺序不同。要打印出端口号,您需要执行以下操作:

printf("%s:%d ",src,ntohs(tcp->source));

此外,您可能想尝试struct iphdr而不是struct ip。我之前看到过在标题中有多个名为ip的结构定义的实例,但iphdr始终适合我。

请记住,您始终可以在另一个窗口中运行tcpdump以查看实际进入的数据包,您可能会获得比预期更多的流量。

答案 1 :(得分:0)

首先,在调用pcap_open_live()后,在pcap_datalink()上调用handle,如果它没有返回DLT_EN10MB,请退出或重写您的程序以便它可以处理它返回的值。有关pcap_datalink()支持的值的说明,请参阅the tcpdump.org link-layer header types page

其次, NOT 假设数据包是IPv4数据包,除非您安装了"ip"的过滤器或检查了数据包类型(例如,以太网中的类型字段) header)确保数据包是IPv4数据包。

第三,执行 NOT 假设IPv4数据包的标头长度恰好为sizeof(struct ip)个字节。我假设sizeof(struct ip)将是20,这是IPv4标头的最小长度,但标头可能包含选项 - 检查IPv4标头的“标头长度”字段(在单位为4字节字,所以值为5意味着“20字节”)并将其用作标题的长度(确保它至少为5 - 如果它小于5,则数据包无效 - 然后相乘用4来得到标题的长度。)

第四,做 NOT 假设数据包是TCP数据包,除非你安装了"ip and tcp""tcp"的过滤器(后者,你将会仍然需要检查自己是否是IPv4数据包)或检查IPv4标头的“协议”字段,以确保它的值为6(对于TCP)。

相关问题