linux下libpcap抓包分析一、首先下载libpcap包http://www./#latest-release 然后安装,安装完成后进入安装根目录的tests文件夹,编译运行findalldevstest.c(编译时加上-libpcap),查看是否发现所有网络设备。 二、下载wireshark观察抓包软件的各种功能 三、熟悉libpcap工作原理: 四、了解libpcap抓包基本流程: 五、编程实现 未完待续。。。
PS:整理了一下libpcap常用的数据类型定义
0)、typedef int bpf_int32 1)、typedef u_int bpf_u_int32 32bit 的无类型整形; 2)、typedef pcap pcap_t Descriptor of an open capture instance(一个打开的捕获实例的描述符?)这个结构对用户是不透明的。 3)、typedef pcap_dumper pcap_dumper_t libpcap保存文件的描述符。 4)、typedef pcap_if pcap_if_t 网卡链表的一个元素; 5)、typedef pcap_addr pcap_addr_t 网卡地址的表示; 6)、typedef void (*pcap_handler)(u_char *args, const struct pcap_pkthdr *header, const u_char *packet); 其中agrs是从pcap_dispatch()函数传递过来的第四个形参 ,一般我们自己的包捕捉程序不需要提供它,总是为NULL ;header指向
Libpcap库函数所必须的数据结构定义主要包含在pcap.h和pcap-int.h两个头文件中 1)、pcap结构在pcap-int.h头文件中被定义: int selectable_fd; /* 在 socket 上,可以使用 select() 和 poll() 等 I/O 复用类型函数 */ int snapshot; /* 用户期望的捕获数据包最大长度 */ int linktype; /* 设备类型 */ int tzoff; /* 时区位置,实际上没有被使用 */ int offset; /* 边界对齐偏移量 */ int break_loop; /* 强制从读数据包循环中跳出的标志 */ struct pcap_sf sf; /* 数据包保存到文件的相关配置数据结构 */ struct pcap_md md; /* 具体描述如下 */
int bufsize; /* 读缓冲区的长度 */ u_char buffer; /* 读缓冲区指针 */ u_char *bp; int cc; u_char *pkt; /* 相关抽象操作的函数指针,最终指向特定操作系统的处理函数 */ int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *); int (*setfilter_op)(pcap_t *, struct bpf_program *); int (*set_datalink_op)(pcap_t *, int); int (*getnonblock_op)(pcap_t *, char *); int (*setnonblock_op)(pcap_t *, int, char *); int (*stats_op)(pcap_t *, struct pcap_stat *); void (*close_op)(pcap_t *); /*如果 BPF 过滤代码不能在内核中执行,则将其保存并在用户空间执行 */ struct bpf_program fcode; /* 函数调用出错信息缓冲区 */ char errbuf[PCAP_ERRBUF_SIZE + 1];
/* 当前设备支持的、可更改的数据链路类型的个数 */ int dlt_count; /* 可更改的数据链路类型号链表,在 linux 下没有使用 */ int *dlt_list; /* 数据包自定义头部,对数据包捕获时间、捕获长度、真实长度进行描述 [pcap.h] */ struct pcap_pkthdr pcap_header; };
/* 包含了捕获句柄的接口、状态、过滤信息 [pcap-int.h] */ struct pcap_md { /* 捕获状态结构 [pcap.h] */ struct pcap_stat stat; int use_bpf; /* 如果为1,则代表使用内核过滤*/ u_long TotPkts; u_long TotAccepted; /* 被接收数据包数目 */ u_long TotDrops; /* 被丢弃数据包数目 */ long TotMissed; /* 在过滤进行时被接口丢弃的数据包数目 */ long OrigMissed; /*在过滤进行前被接口丢弃的数据包数目*/ #ifdef linux int sock_packet; /* 如果为 1,则代表使用 2.0 内核的 SOCK_PACKET 模式 */ int timeout; /* pcap_open_live() 函数超时返回时间*/ int clear_promisc; /* 关闭时设置接口为非混杂模式 */ int cooked; /* 使用 SOCK_DGRAM 类型 */ int lo_ifindex; /* 回路设备索引号 */ char *device; /* 接口设备名称 */
/* 以混杂模式打开 SOCK_PACKET 类型 socket 的 pcap_t 链表*/ struct pcap *next; #endif };
(2)bpf_program结构 /* [pcap-bpf.h] */ struct bpf_program { u_int bf_len; /* BPF 代码中谓词判断指令的数目 */ struct bpf_insn *bf_insns; /* 第一个谓词判断指令 */ };
/* 谓词判断指令结构 */ struct bpf_insn { u_short code; u_char jt; u_char jf; bpf_int32 k; }; (3) /usr/include/net/bpf.h /* 内核过滤器每输出一个包,将在输出的数据前加了20字节的数据,这就是 struct bpf_hdr (4)pcap_stat结构
5)、 struct pcap_addr:网卡地址描述 6)、dump文件格式 首先是Dump文件头 struct
pcap_file_header { }; 然后是每一个包的包头和数据 pcap_pkthdr结构 /* struct pcap_pkthdr { struct timeval ts; /* 捕获时间戳 */ bpf_u_int32 caplen; /* 捕获到数据包的长度 */ bpf_u_int32 len; /* 数据包的真正长度 */ }
/* 单个数据包结构,包含数据包元信息和数据信息 */ struct singleton [pcap.c] { struct pcap_pkthdr hdr; /* libpcap 自定义数据包头部 */ const u_char * pkt; /* 指向捕获到的网络数据 */ };
7)、pcap_if (libpcap 自定义的接口信息链表 [pcap.h])
struct pcap_if { struct pcap_if *next; char *name; /* 接口设备名 */ char *description; /* 接口描述 */
/*接口的 IP 地址, 地址掩码, 广播地址,目的地址 */ struct pcap_addr addresses; bpf_u_int32 flags; /* 接口的参数 */ }; |
|