我写了一个包读取器,它使用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
地址不应该相同,端口号也不正确。
我甚至不知道从哪里开始查找错误,因为我的代码(至少对我来说)看起来是正确的。任何帮助、提示或建议都将不胜感激。谢谢:)
最佳答案
两个问题:
inet_ntoa返回指向静态缓冲区的指针。
在同一printf中调用两次时,它会覆盖同一缓冲区。所以你最终会打印相同的数据。
请改用inet-ntop,并为每个调用提供单独的缓冲区。
打印前,应使用ntohs()将端口转换为主机顺序。
关于c - 为什么我的数据包读取程序返回错误的数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8299861/