#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <stdint.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <pcap.h>
#include <netdb.h>
#include <iostream>
#include <string>
class capature_packet_show {
public:
capature_packet_show() = default;
virtual ~capature_packet_show() = default;
capature_packet_show(const capature_packet_show &) = delete;
capature_packet_show & operator = (const capature_packet_show &) = delete;
public:
bool init() {
return init_pcap_handle();
}
inline unsigned int get_net() const {
return net_;
}
inline unsigned int get_mask() const {
return mask_;
}
inline const char *get_net_string() const {
return net_string_;
}
inline const char *get_mask_string() const {
return mask_string_;
}
inline void set_filter(const char *filter) {
filter_ = filter;
}
private:
inline void init_net_addr() {
struct in_addr addr = { 0 };
addr.s_addr = net_;
net_string_ = inet_ntoa(addr);
std::cout << "网络地址:" << net_string_ << std::endl;
addr.s_addr = mask_;
mask_string_ = inet_ntoa(addr);
std::cout << "网络掩码:" << mask_string_ << std::endl;
}
bool init_pcap_handle() {
char err[PCAP_ERRBUF_SIZE] = "";
char *dev = pcap_lookupdev(err);
if (!dev) {
std::cerr << "查询网络设备错误:" << err << std::endl;
return false;
}
std::cout << "获取网络设备:" << dev << std::endl;
if (pcap_lookupnet(dev, &net_, &mask_, err) < 0) {
std::cerr << "查询网络号和掩码失败:" << err << std::endl;
return false;
}
std::cout << "网络号:" << net_ << " 掩码:" << mask_ << std::endl;
init_net_addr();
handle_ = pcap_open_live(dev, BUFSIZ, 1, 1000, err); // 1 -- 混杂模式 1000 - 1000毫秒超时
if (!handle_) {
std::cerr << "打开网络设备失败:" << err << std::endl;
return false;
}
struct bpf_program fp = { 0 };
if (pcap_compile(handle_, &fp, filter_, 1, mask_) < 0) {
std::cerr << "过滤器解析失败" << pcap_geterr(handle_) << std::endl;
pcap_close(handle_);
return false;
}
if (pcap_setfilter(handle_, &fp) < 0) {
std::cerr << "过滤器安装失败" << pcap_geterr(handle_) << std::endl;
pcap_close(handle_);
return false;
}
std::cout << "开始循环抓包..." << std::endl;
int id = 0;
if (pcap_loop(handle_, -1, get_packet, (u_char *)(&id)) < 0) {
std::cerr << "循环抓包失败" << pcap_geterr(handle_) << std::endl;
pcap_close(handle_);
return false;
}
pcap_close(handle_);
return true;
}
private:
static void print_mac(const unsigned char* mac_addr) {
int i = 0;
for (;i < 5;i++) {
printf("%.2x:", mac_addr[i]); // 16进制,两位宽度
}
printf("%.2x", mac_addr[i]);
}
static void print_ip(const unsigned char* ip_addr) {
int i = 0;
for (;i < 3;++i) {
printf("%d.", ip_addr[i]);
}
printf("%d", ip_addr[i]);
}
static void print_protocol_type(unsigned int protocol_type) {
switch (protocol_type) {
case ETHERTYPE_IP:
std::cout << "IPV4" << std::endl;
break;
case ETHERTYPE_PUP:
std::cout << "PUP" << std::endl;
break;
case ETHERTYPE_ARP:
std::cout << "ARP" << std::endl;
break;
default:
std::cout << "unknow protocal." << std::endl;
break;
}
}
static void process_ip_packet(const struct pcap_pkthdr *pkthdr, const u_char *packet) {
struct ip *ip_header = nullptr;
struct icmphdr *icmp_header = nullptr;
struct tcphdr *tcp_header = nullptr;
struct udphdr *udp_header = nullptr;
struct ether_arp *arp_packet = nullptr;
ip_header = (struct ip *)(packet + sizeof(struct ether_header));
std::cout << "源IP地址:";
print_ip((unsigned char *)&(ip_header->ip_src));
std::cout << std::endl;
std::cout << "目的IP地址:";
print_ip((unsigned char *)&(ip_header->ip_dst));
std::cout << std::endl;
switch (ip_header->ip_p) {
case 1:
std::cout << "传输层协议是ICMP" << std::endl;
break;
case 2:
std::cout << "传输层协议是IGMP" << std::endl;
break;
case 6:
std::cout << "传输层协议是TCP" << std::endl;
tcp_header = (struct tcphdr*)(packet + sizeof(struct ether_header) + sizeof(struct ip));
std::cout << "目的端口:" << ntohs(tcp_header->dest) << std::endl;
std::cout << "源端口:" << ntohs(tcp_header->source) << std::endl;
std::cout << "Payload:" << std::endl;
std::cout << "字节数:" << pkthdr->len << std::endl;
print_payload(packet, pkthdr->len);
break;
case 7:
std::cout << "传输层协议是UDP" << std::endl;
udp_header = (struct udphdr*)(packet + sizeof(struct ether_header) + sizeof(struct ip));
std::cout << "目的端口:" << ntohs(udp_header->dest) << std::endl;
std::cout << "源端口:" << ntohs(udp_header->source) << std::endl;
std::cout << "Payload:" << std::endl;
std::cout << "字节数:" << pkthdr->len << std::endl;
print_payload(packet, pkthdr->len);
break;
default:
std::cerr << "未知协议." << std::endl;
break;
}
}
static void print_payload(const unsigned char *payload, int len, int text) {
for (int i = 0;i < len;i++) {
if (1 == text) {
printf("%c", payload[i]);
}
else {
printf("%.2x", payload[i]);
}
if (0 == (i + 1) % 16) {
std::cout << std::endl;
}
}
}
static void print_payload(const unsigned char *payload, int len) {
print_payload(payload, len, 0);
print_payload(payload, len, 1);
}
static void get_packet(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet) {
static uint64_t packet_num_ = 0;
std::cout << "收到包的时间:" << ctime((const time_t*)&(pkthdr->ts).tv_sec) << std::endl;
std::cout << "收到包的数量:" << ++packet_num_ << std::endl;
std::cout << "收到包的字节数:" << pkthdr->len << std::endl;
struct ether_header *eth = (struct ether_header *)(packet);
std::cout << "源MAC地址:";
print_mac(eth->ether_shost);
std::cout << std::endl;
std::cout << "目的MAC地址:";
print_mac(eth->ether_dhost);
std::cout << std::endl;
unsigned int protocol_type = ntohs(eth->ether_type);
print_protocol_type(protocol_type);
if (ETHERTYPE_IP == ETHERTYPE_IP) {
process_ip_packet(pkthdr, packet);
}
}
private:
bpf_u_int32 net_ = 0;
bpf_u_int32 mask_ = 0;
const char *net_string_ = "";
const char *mask_string_ = "";
const char *filter_ = "ip";
pcap_t *handle_ = nullptr; // libpcap设备描述符号
};
int main() {
capature_packet_show cps;
if (false == cps.init()) {
std::cerr << "init failed." << std::endl;
return -1;
}
return 0;
}
g++ -std=c++11 -g -o test capture_packet_show.cpp -I ./ -lpcap