Convert pcapng file to pcap format

Today I met another error related to multiple interfaces in pcapng file:

pcap_next_ex() [an interface has a type 0 different from the type of the first interface]. Trace index = 8122

From my previous post, I wanted to convert it to pcap format by tshark command. But unfortunately it didn’t work:

$ tshark -F pcap -r a.pcapng -w b.pcap
tshark: Frame 8122 of file "a.pcapng" has a network type that differs from the network type of earlier packets, which isn't supported in a "Wireshark/tcpdump/... - pcap" file.

I had no choice but stole code from pcapplusplus to implement a converter, and the final code can be downloaded here. Please note on my macOS system, I did little tweak about PcapPlusPlus.mk:

$ cat /opt/homebrew/Cellar/pcapplusplus/22.11/etc/PcapPlusPlus.mk
......
# libs
PCAPPP_LIBS_DIR := -L/opt/homebrew/Cellar/pcapplusplus/22.11/lib
......

Parse pcapng file

Libpcap can be used to parse pcapng file, but only provides features compatible to pcap file (Please refer pcapng wiki).

PcapPlusPlus is a better choice and it can parse more information about the file and packet (e.g., the comment field of every packet). The following is a simple program which prints the metadata of pcapng file and the first 10 packets’ comments:

#include <iostream>
#include <PcapFileDevice.h>

int
main()
{
    std::cout << pcap_lib_version() << '\n';
    pcpp::PcapNgFileReaderDevice input_file("/Users/nanxiao/Downloads/capture.pcapng");
    if (input_file.open()) {
        std::cout << "Open successfully\n";
    } else {
        std::cerr << "Open failed\n";
        return 1;
    }

    std::cout << input_file.getOS() << '\n';
    std::cout << input_file.getHardware() << '\n';
    std::cout << input_file.getCaptureApplication() << '\n';
    std::cout << input_file.getCaptureFileComment() << '\n';

    pcpp::RawPacket packet;
    std::string comment;
    for (size_t i = 1; i < 10; i++)
    {
        if (input_file.getNextPacket(packet, comment)) {
            std::cout << i << ":" << comment << '\n';
        } else {
            std::cerr << "Get packet failed\n";
            return 1;
        }
    }

}

P.S., the code can be downloaded here.