下载LightPcapNg
GitHub - hyh19962008/LightPcapNg: PcapNg read, write and manipulation API.
编译
cd src
make
或者
mkdir build
cd build
cmake ..
make
编译后可以在目录下找到liblight_pcapng.so和liblight_pcapng.a两个文件
pcapng文件格式
1. 文件整体结构
pcapng文件是由一个一个的Block组成的:
2. Block结构
每个Block有四个部分,其中Block Type指定了这个Block的类型
3. Block类型
必要的Block类型, 它们在每个文件中至少应出现一次:
- Section Header Block: it defines the most important characteristics of the capture file.
- Interface Description Block: it defines the most important characteristics of the interface(s) used for capturing traffic.
可选的Block类型:
- Enhanced Packet Block: it contains a single captured packet, or a portion of it. It represents an evolution of the original Packet Block.
- Simple Packet Block: it contains a single captured packet, or a portion of it, with only a minimal set of information about it.
- Name Resolution Block: it defines the mapping from numeric addresses present in the packet dump and the canonical name counterpart.
- Interface Statistics Block: it defines how to store some statistical data (e.g. packet dropped, etc) which can be useful to undestand the conditions in which the capture has been made.
Block Type Code | Description |
---|---|
0x00000000 | Reserved ??? |
0x00000001 | Interface Description Block |
0x00000002 | Packet Block |
0x00000003 | Simple Packet Block |
0x00000004 | Name Resolution Block |
0x00000005 | Interface Statistics Block |
0x00000006 | Enhanced Packet Block |
0x0A0D0D0A | Section Header Block |
4. 文件逻辑结构
4.1 Section Header块
Section Header中的属性为所有出现在其之后的Block所共享,你可以使用一个SHB来配置整个文件的属性:
你也可以使用多个SHB分别配置不同的属性段:
4.2 Interface Description块
在同一个Section中可以配置多个Interface Description块,按照在Section中出现的顺序,他们分别拥有一个Interface ID,这个ID从0开始。
在Enhanced Packet Block中有一个Interface ID的字段,在其中填入相应的ID便可以使用对应的IDB的属性。
4.3 Section逻辑结构
4.4 文件逻辑结构示例1 - 最简单的数据报文组成
4.5 文件逻辑结构示例2 - 复杂组成
5. Option属性
在每一个Block中都可以嵌入可选的Option属性,它们出现的位置在Block Body中,据此可以将Block Body分成两部分:Main和Option。其中Main是必须的,而Option是可选的。
> 注:草案中并没有使用Block Body Main这个称呼。
程序代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include "include/light_internal.h"
#include "include/light_pcapng.h"
#define LINKTYPE_ETHERNET 1
#define PCAPNG_OPTION_LEN_VARIABLE -1 // length is variable
enum global_option_code_e {
global_option_opt_code_endofopt,
global_option_opt_code_comment
};
enum global_option_len_e {
global_option_opt_len_endofopt = 0,
global_option_opt_len_comment = PCAPNG_OPTION_LEN_VARIABLE
};
enum inface_desc_option_code_e {
inface_desc_option_code_if_name = 2,
inface_desc_option_code_if_description = 3,
inface_desc_option_code_if_IPv4addr = 4,
inface_desc_option_code_if_IPv6addr = 5,
inface_desc_option_code_if_MACaddr = 6,
inface_desc_option_code_if_EUIaddr = 7,
inface_desc_option_code_if_speed = 8,
inface_desc_option_code_if_ts_resol = 9,
inface_desc_option_code_if_tzone = 10,
inface_desc_option_code_if_filter = 11,
inface_desc_option_code_if_os = 12,
inface_desc_option_code_if_fcseln = 13,
inface_desc_option_code_tsoffset = 14
};
enum inface_desc_option_len_e {
inface_desc_option_len_if_name = PCAPNG_OPTION_LEN_VARIABLE,
inface_desc_option_len_if_description = PCAPNG_OPTION_LEN_VARIABLE,
inface_desc_option_len_if_IPv4addr = 8,
inface_desc_option_len_if_IPv6addr = 17,
inface_desc_option_len_if_MACaddr = 6,
inface_desc_option_len_if_EUIaddr = 8,
inface_desc_option_len_if_speed = 8,
inface_desc_option_len_if_ts_resol = 1,
inface_desc_option_len_if_tzone = 4,
inface_desc_option_len_if_filter = PCAPNG_OPTION_LEN_VARIABLE,
inface_desc_option_len_if_os = PCAPNG_OPTION_LEN_VARIABLE,
inface_desc_option_len_if_fcseln = 1,
inface_desc_option_len_tsoffset = 8
};
// 4 * 32bit = 16B
typedef struct {
uint32_t byte_order;
uint16_t major_ver;
uint16_t minor_ver;
uint64_t section_length;
}pcapng_section_header_body;
// 2 * 32bit = 8B
typedef struct {
uint16_t linktype;
uint16_t reserved;
uint32_t snaplen;
// options
}pcapng_inface_desc_body;
// 5 * 32bit = 20B
typedef struct {
uint32_t interface_id;
uint32_t ts_high;
uint32_t ts_low;
uint32_t caplen;
uint32_t len;
// data PAD to 32bit
}pcapng_enhanced_packet_body;
/**
* return a pointer to newly allocated memory,
* putting pkt_hdr and packet_data in sequence
*
*/
uint32_t *get_full_packet_block(pcapng_enhanced_packet_body *hdr, uint8_t *data, int data_len) {
int size = sizeof(pcapng_enhanced_packet_body) + data_len;
uint8_t *block = (uint8_t *)malloc(size);
memset(block, 0, size);
memcpy(block, hdr, sizeof(pcapng_enhanced_packet_body));
memcpy(block + sizeof(pcapng_enhanced_packet_body), data, data_len);
return (uint32_t *)block;
}
// 2 * block_len + block_type = 12B
// opt_header = 4B
// opt_ending = 4B
int main() {
uint8_t packet[] = {0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x08, 0x00, 0x45, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xf6, 0x63, 0xc0, 0xa8, 0x01, 0x01, 0xc0, 0xa8, 0x02, 0x02, 0xc0, 0x00, 0x0e, 0xc8, 0x00, 0x22, 0xa9, 0x49, 0x20, 0x40, 0x01, 0x18, 0x00, 0x00, 0x09, 0xcf, 0x00, 0x00, 0x11, 0x2f, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x0f, 0x42, 0x40, 0x00, 0x00};
uint32_t option_value = 0;
clock_t time = clock();
pcapng_enhanced_packet_body pkt_hdr = {0, 0, clock(), sizeof(packet), sizeof(packet)};
uint32_t *pkt_block;
char option_str[255] = {};
// pointer
light_pcapng pcapng_file = NULL;
light_pcapng prev_block = NULL;
light_pcapng current_block = NULL;
light_option option = NULL;
// SHB
pcapng_section_header_body section_body = {BYTE_ORDER_MAGIC, 1, 0, 200};
pcapng_file = light_alloc_block(LIGHT_SECTION_HEADER_BLOCK, (uint32_t *)§ion_body, sizeof(pcapng_section_header_body));
prev_block = pcapng_file;
light_add_block(prev_block, current_block);
// printf("%d\n", pcapng_file->block_total_lenght);
// IDB
pcapng_inface_desc_body inface_body = {LINKTYPE_ETHERNET, 0, 65535};
current_block = light_alloc_block(LIGHT_INTERFACE_BLOCK, (uint32_t *)&inface_body, sizeof(pcapng_inface_desc_body));
option_value = 6; // ts_resolution 10^-6
option = light_create_option(inface_desc_option_code_if_ts_resol, inface_desc_option_len_if_ts_resol, &option_value);
light_add_option(pcapng_file, current_block, option, LIGHT_FALSE);
light_add_block(prev_block, current_block);
prev_block = current_block;
// printf("%d\n", current_block->block_total_lenght);
// Packets
pkt_block = get_full_packet_block(&pkt_hdr, packet, sizeof(packet));
current_block = light_alloc_block(LIGHT_ENHANCED_PACKET_BLOCK, (uint32_t *)pkt_block, sizeof(packet) + sizeof(pcapng_enhanced_packet_body));
free(pkt_block);
strcpy(option_str, "hello world"); // option 字段可用于输出调试信息
option = light_create_option(global_option_opt_code_comment, strlen(option_str), &option_str);
light_add_option(pcapng_file, current_block, option, LIGHT_FALSE);
light_add_block(prev_block, current_block);
prev_block = current_block;
// printf("%d\n", current_block->block_total_lenght);
pkt_hdr.ts_low = clock();
pkt_block = get_full_packet_block(&pkt_hdr, packet, sizeof(packet));
current_block = light_alloc_block(LIGHT_ENHANCED_PACKET_BLOCK, (uint32_t *)pkt_block, sizeof(packet) + sizeof(pcapng_enhanced_packet_body));
free(pkt_block);
light_add_block(prev_block, current_block);
prev_block = current_block;
// auto calc section lenght
light_pcapng_to_file("output.pcapng", pcapng_file);
light_pcapng_release(pcapng_file);
return 0;
}
参考资料
.pcapng文件格式和.pcap文件格式_书伯的博客-CSDN博客_pcapng
PCAP Next Generation Dump File Format
GitHub - pcapng/pcapng: PCAP next generation file format specification