You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C手动向pcap文件添加特定数据,兼容格式并标识InfiniBand接口?

可以在合规前提下用C语言实现需求

要让pyshark识别数据包所属的InfiniBand接口,你需要使用pcapng格式(而非传统pcap旧格式)写入文件——传统pcap格式不支持存储接口元数据,而pcapng是为扩展元数据设计的标准格式,完全符合规范。

核心实现思路

pcapng通过三类关键块关联数据包与接口:

  1. Section Header Block (SHB):文件起始块,定义pcapng版本、字节序等基础信息。
  2. Interface Description Block (IDB):为每个接口创建一个块,存储接口名称(如ib0)、链路类型(InfiniBand对应链路类型值为141,即DLT_INFINIBAND)等元数据,每个IDB分配唯一的interface_id(从0开始递增)。
  3. Enhanced Packet Block (EPB):每个数据包用EPB封装,其中interface_id字段对应IDB的序号,以此关联数据包到具体接口。

C语言手动写入核心代码片段

注意:pcapng所有多字节字段均采用大端字节序:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <arpa/inet.h>

// pcapng块通用头部
typedef struct {
    uint32_t block_type;
    uint32_t block_total_length;
} pcapng_block_hdr;

// 写入Section Header Block
void write_shb(FILE *fp) {
    pcapng_block_hdr hdr = {
        .block_type = htonl(0x0A0D0D0A), // SHB魔法值
        .block_total_length = htonl(28)
    };
    uint32_t ver_major = htonl(1);
    uint32_t ver_minor = htonl(0);
    uint64_t sec_len = htonll(0); // 0表示未知长度
    uint32_t end_len = htonl(28);

    fwrite(&hdr, sizeof(hdr), 1, fp);
    fwrite(&ver_major, sizeof(ver_major), 1, fp);
    fwrite(&ver_minor, sizeof(ver_minor), 1, fp);
    fwrite(&sec_len, sizeof(sec_len), 1, fp);
    fwrite(&end_len, sizeof(end_len), 1, fp);
}

// 写入InfiniBand接口的IDB
void write_idb(FILE *fp, const char *if_name) {
    uint32_t block_type = htonl(0x00000001); // IDB类型标识
    uint16_t link_type = htons(141); // DLT_INFINIBAND
    uint32_t snap_len = htonl(65535);
    size_t opt_len = 4 + strlen(if_name) + 1; // 选项头+接口名字符串+终止符
    uint32_t block_len = htonl(8 + 8 + opt_len + 4);
    uint32_t end_len = block_len;

    // 写块头部
    fwrite(&block_type, sizeof(block_type), 1, fp);
    fwrite(&block_len, sizeof(block_len), 1, fp);
    // 写IDB固定字段
    fwrite(&link_type, sizeof(link_type), 1, fp);
    fwrite("\x00\x00", 2, 1, fp); // 保留字段
    fwrite(&snap_len, sizeof(snap_len), 1, fp);
    // 写接口名选项(选项代码2:IF_NAME)
    uint16_t opt_code = htons(2);
    uint16_t opt_len_field = htons(strlen(if_name) + 1);
    fwrite(&opt_code, sizeof(opt_code), 1, fp);
    fwrite(&opt_len_field, sizeof(opt_len_field), 1, fp);
    fwrite(if_name, strlen(if_name) + 1, 1, fp);
    // 写块尾部
    fwrite(&end_len, sizeof(end_len), 1, fp);
}

// 写入关联接口的EPB
void write_epb(FILE *fp, uint8_t *pkt_data, size_t pkt_len) {
    uint32_t block_type = htonl(0x00000006); // EPB类型标识
    uint32_t if_id = htonl(0); // 关联第一个IDB(序号0)
    uint32_t ts_high = htonl(0); // 可替换为实际捕获时间高位
    uint32_t ts_low = htonl(0);  // 可替换为实际捕获时间低位
    uint32_t cap_len = htonl(pkt_len);
    uint32_t orig_len = htonl(pkt_len);
    uint32_t block_len = htonl(8 + 20 + pkt_len + 4);
    uint32_t end_len = block_len;

    fwrite(&block_type, sizeof(block_type), 1, fp);
    fwrite(&block_len, sizeof(block_len), 1, fp);
    fwrite(&if_id, sizeof(if_id), 1, fp);
    fwrite(&ts_high, sizeof(ts_high), 1, fp);
    fwrite(&ts_low, sizeof(ts_low), 1, fp);
    fwrite(&cap_len, sizeof(cap_len), 1, fp);
    fwrite(&orig_len, sizeof(orig_len), 1, fp);
    fwrite(pkt_data, pkt_len, 1, fp);
    fwrite(&end_len, sizeof(end_len), 1, fp);
}

int main() {
    FILE *fp = fopen("ib_capture.pcapng", "wb");
    if (!fp) return 1;

    write_shb(fp);
    write_idb(fp, "ib0"); // 指定InfiniBand接口名

    // 示例:写入模拟的InfiniBand数据包
    uint8_t dummy_pkt[] = {0x00, 0x01, 0x02, 0x03, 0x04};
    write_epb(fp, dummy_pkt, sizeof(dummy_pkt));

    fclose(fp);
    return 0;
}

pyshark解析验证

打开生成的pcapng文件后,可直接获取接口信息:

import pyshark

cap = pyshark.FileCapture('ib_capture.pcapng')
for pkt in cap:
    print(f"数据包来自接口: {pkt.interface.name}")

注意事项

  • 必须严格遵循pcapng规范(字节序、块长度计算、选项格式),否则解析工具可能无法识别。
  • 传统pcap格式无法存储接口元数据,若需兼容旧工具,只能通过文件名或外部文档标注接口,但pyshark无法自动读取这类信息。

内容的提问来源于stack exchange,提问作者Yaakov Goldsmith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 10:10:01