我编写了一个使用libpcap读取捕获文件的数据包读取器。它读取捕获文件并将捕获的数据上载到MySQL数据库。有时它似乎工作正常而其他它返回无效数据(例如,源和目标IP将是相同的,tcp端口都是垃圾)。我在虚拟RHEL 5下运行它。这是我的代码(对不起,如果它很长或不必要地复杂,这是我第一次尝试这个)。
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include "npc_tcp.h"
#include "npc_udp.h"
#include <ftw.h>
#include <pcap.h>
#include <stdio.h>
#include <sys/stat.h>
#include <regex.h>
#include <string.h>
#include <time.h>
const int IPTYPE_TCP = 6;
const int IPTYPE_UDP = 17;
struct cap_data {
char ts[64];
u_int16_t ether_type;
u_int16_t proto;
char *srcip;
char *dstip;
char *srcmac;
u_int16_t srcport;
u_int16_t dstport;
u_int8_t flags;
u_int capsize;
};
int main(int argc, char **argv) {
//pcap
struct cap_data data;
struct pcap_pkthdr pkthdr;
const u_char *packet;
pcap_t *handle;
char *fname = argv[1];
printf("%s\n", fname);
char errbuf[PCAP_ERRBUF_SIZE];
handle = pcap_open_offline(fname, errbuf);
char buf[1000];
while (packet = pcap_next(handle, &pkthdr)) {
int ether_flag;
struct ether_header *ether;
u_short ether_type;
ether = (struct ether_header *) packet;
data.ether_type = ntohs(ether->ether_type);
ether_flag = 1;
if (ether_flag) {
if (data.ether_type == ETHERTYPE_IP) {
struct ip *ip_hdr;
u_int length = pkthdr.len;
ip_hdr = (struct ip *)(packet + sizeof(struct ether_header));
data.proto = ip_hdr->ip_p;
data.dstip = inet_ntoa(ip_hdr->ip_dst);
data.srcip = inet_ntoa(ip_hdr->ip_src);
if (data.proto == IPTYPE_TCP) {
struct tcphdr *tcp;
tcp = (struct tcphdr*)(packet + sizeof(struct ether_header) +
sizeof(struct ip));
data.srcport = tcp->th_sport;
data.dstport = tcp->th_dport;
printf("%s %u %s %u\n\n", inet_ntoa(ip_hdr->ip_src), tcp->th_sport, inet_ntoa(ip_hdr->ip_dst), tcp->th_dport);
} else if (data.proto == IPTYPE_UDP) {
struct udphdr *udp;
udp = (struct udphdr *)(packet + sizeof(struct ether_header) +
sizeof(struct ip));
data.srcport = udp->uh_sport;
data.dstport = udp->uh_dport;
printf("%s %u %s %u\n\n", inet_ntoa(ip_hdr->ip_src), udp->uh_sport, inet_ntoa(ip_hdr->ip_dst), udp->uh_dport);
}
}
}
}//while
pcap_close(handle);
return 0;
}
更新:
这输出..
source ip port dest ip port
66.68.236.207 30151 66.68.236.207 47873
172.22.162.235 60920 172.22.162.235 36175
67.207.28.150 23007 67.207.28.150 22038
172.22.162.235 60920 172.22.162.235 36175
67.207.28.151 22038 67.207.28.151 23007
65.55.87.43 20480 65.55.87.43 21764
67.207.28.150 23007 67.207.28.150 22038
地址不应该相同,端口号也是错误的。
我不知道在哪里开始寻找错误,因为我的代码(至少对我而言)看起来是正确的。任何帮助,提示或建议将不胜感激。谢谢:))
答案 0 :(得分:1)
两个问题:
inet_ntoa返回指向静态缓冲区的指针
在同一个printf中调用它两次时,它会覆盖相同的缓冲区。所以你最终打印相同的数据
改为使用inet_ntop,并为每个调用提供一个单独的缓冲区。
在打印之前,您应该使用ntohs()将端口转换为主机顺序。
答案 1 :(得分:0)
如果在调用pcap_open_offline()
后立即执行
if (pcap_datalink(handle) != DLT_EN10MB) {
fprintf(stderr, "This program handles only Ethernet captures\n");
return 2;
}