WinPcap handles offline heap files

1, Foreword

Through the previous study, we are familiar with capturing packets from the network card. Now we will learn how to process packets. WinPcap provides us with many API s to save packets flowing through the network to a heap file and read the contents of the heap. The format of this file is very simple, but it contains the binary content of the captured datagram. This file format is also the standard of many network tools, such as WinDump, Ethereal, Snort, etc.

2, Code explanation

Save packets to file: write packets in LIBPCAP format, capture packets from the specified interface and store them in a specified file.

#include "mainwindow.h"
#include <QApplication>
#include <QDebug>

#define HAVE_REMOTE
#include "pcap.h"

#ifndef WIN32
    #include <sys/socket.h>
    #include <netinet/in.h>
#else
    #include <winsock2.h>
    #include <ws2tcpip.h>
#endif

//Callback function prototype
void packet_handler(u_char* dumpfile, const struct pcap_pkthdr* header, const u_char* pkt_data);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();


    pcap_if_t *alldevs;
    pcap_if_t *d;
    int inum;
    int i=0;
    pcap_t* adhandle;   //Define file handle
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_dumper_t *dumpfile;

    //Check whether the command line parameter has a file name
    if(argc != 2) {
        qDebug()<<"usage: %s filename"<<argv[0];
    }

    //Get the list of native adapters
    if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs, errbuf) == -1)
    {
        qDebug() << "Error in pcap_findalldevs_ex: " <<errbuf;
        exit(1);
    }

    //Print adapter list
    for(d = alldevs; d; d = d->next)
    {
        //Device name
        qDebug()<<"Name: "<<d->name;
        ++i;
        //Device description
        if (d->description) {
            qDebug()<<"Description: "<<d->description;
        }else {
            qDebug()<<"No description available";
        }

        qDebug()<<"====================================================================";
    }

    if(i==0) {
        qDebug()<<"No interfaces found! Make sure WinPcap is installed.";
        return -1;
    }

    qDebug()<<QString("Enter the interface number (1-%1): ").arg(i);
    //scanf("%d",&inum);
    inum = 5;
    qDebug()<<"inum: "<<inum;

    if(inum < 1 || inum > i){
        qDebug()<<"Interface number out of range.";
        //Release adapter list
        pcap_freealldevs(alldevs);
        return -1;
    }

    //Jump to the selected adapter
    for(d=alldevs,i=0; i<inum-1; d=d->next,i++);

    //Open adapter
    if((adhandle = pcap_open(d->name,                       //Device name
                             65536,                         //65535 packet certificate can capture all the contents of each packet on different data link layers
                             PCAP_OPENFLAG_PROMISCUOUS,     //promiscuous mode 
                             1000,                          //Read timeout
                             NULL,                          //Remote machine authentication
                             errbuf                         //Error buffer pool
                             )) == NULL) {
        qDebug()<<"Unable to open the adapter."<<QString("%1 is not support by WinPcap").arg(d->name);

        //Release adapter list
        pcap_freealldevs(alldevs);
        return -1;
    }

    //Open file
    dumpfile = pcap_dump_open(adhandle,argv[1]);
    if(dumpfile == NULL) {
        qDebug()<<stderr<<"Error opening output file";
    }

    qDebug()<<QString("Listening on %1...").arg(d->description);

    //Release adapter list
    pcap_freealldevs(alldevs);

    //Loop to capture data and call packet_ The handler function stores data in a heap file
    pcap_loop(adhandle,0,packet_handler,(unsigned char *)dumpfile);

    return a.exec();
}

//The callback function will be called by libpcap when each packet is received
void packet_handler(u_char* dumpfile, const struct pcap_pkthdr* header, const u_char* pkt_data)
{
    pcap_dump(dumpfile,header,pkt_data);
}

The structure of the program is very similar to that of the previous example. The difference is that once the network card is opened, the program calls pcap_dump_open to open a file. This call associates the file with a network card. packet_handler() calls pcap internally_ Dump() to store the captured datagram in a file, pcap_ Parameters of dump and packer_handler(), so it is convenient to use.

Read data content from file (pcap_loop): open a heap file and print the contents of each package in it

#include "mainwindow.h"
#include <QApplication>
#include <QDebug>

#define HAVE_REMOTE
#include "pcap.h"

#ifndef WIN32
    #include <sys/socket.h>
    #include <netinet/in.h>
#else
    #include <winsock2.h>
    #include <ws2tcpip.h>
#endif

#define LINE_LEN 16

//Callback function prototype
void dispatcher_handler(u_char* temp1, const struct pcap_pkthdr* header, const u_char* pkt_data);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();



    pcap_t* fp;   //Define file handle
    char errbuf[PCAP_ERRBUF_SIZE];

    //Check whether the command line parameter has a file name
    if(argc != 2) {
        qDebug()<<"usage: %s filename"<<argv[0];
    }

    //Open a heap file that stores data
    if((fp = pcap_open_offline(argv[1],errbuf)) == NULL) {
        qDebug()<<stderr<<"Error opening dump file";
    }

    //Read data until EOF flag is encountered
    pcap_loop(fp,0,dispatcher_handler,NULL);

    return a.exec();
}

//The callback function will be called by libpcap when each packet is received
void dispatcher_handler(u_char* temp1, const struct pcap_pkthdr* header, const u_char* pkt_data)
{
    u_int i = 0;

    //Print timestamp and len of pkt
    qDebug()<<"header->ts.tv_sec: "<<header->ts.tv_sec;
    qDebug()<<"header->ts.tv_usec: "<<header->ts.tv_usec;
    qDebug()<<"header->len: "<<header->len;

    //Print newspaper
    for(int i=1; (i<header->caplen+1); ++i) {
        qDebug()<<"pkt_data[i-1]: "<<pkt_data[i-1];
    }
}

Read data content from file (pcap_next_ex): open a heap file and print the contents of each package in it

#include "mainwindow.h"
#include <QApplication>
#include <QDebug>

#define HAVE_REMOTE
#include "pcap.h"

#ifndef WIN32
    #include <sys/socket.h>
    #include <netinet/in.h>
#else
    #include <winsock2.h>
    #include <ws2tcpip.h>
#endif

#define LINE_LEN 16

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();



    pcap_t* fp;   //Define file handle
    char errbuf[PCAP_ERRBUF_SIZE];
    struct pcap_pkthdr* header;
    const u_char* pkt_data;
    u_int i = 0;
    int res;

    //Check whether the command line parameter has a file name
    if(argc != 2) {
        qDebug()<<"usage: %s filename"<<argv[0];
    }

    //Open a heap file that stores data
    if((fp = pcap_open_offline(argv[1],errbuf)) == NULL) {
        qDebug()<<stderr<<"Error opening dump file";
    }

    //Read data until EOF flag is encountered
    while((res = pcap_next_ex(fp,&header,&pkt_data)) >= 0) {
        //Print timestamp and len of pkt
        qDebug()<<"header->ts.tv_sec: "<<header->ts.tv_sec;
        qDebug()<<"header->ts.tv_usec: "<<header->ts.tv_usec;
        qDebug()<<"header->len: "<<header->len;

        //Print newspaper
        for(int i=1; (i<header->caplen+1); ++i) {
            qDebug()<<"pkt_data[i-1]: "<<pkt_data[i-1];
        }
    }

    if(res == -1) {
        qDebug()<<"Error reading the packets: "<<pcap_geterr(fp);
    }

    return a.exec();
}

The latest version of WinPcap provides a further way to store packets to disk, that is, using pcap_live_dump() function, which requires three parameters:

  • A file name;
  • A maximum length allowed for the file;
  • The maximum number of packages allowed by the file;
    For these parameters, 0 means there is no maximum limit

You can call pcap at_ live_ A filter is set before dump() to define which datagrams need to be stored

pcap_live_dump() is non blocking, so it will return immediately: the stored procedure of data will proceed asynchronously until the file reaches the specified maximum length or the maximum number of datagrams.

Applications can use pcap_ live_ dump_ End() to check whether the data is stored. If the maximum length parameter and the number of datagrams you specify are 0, the operation will be blocked forever.

pcap_live_dump() and pcap_ The difference of dump () is the problem of performance from the maximum limit. pcap_live_dump() uses WinPcap NPF driver to write data to the file from the kernel level, so as to minimize the memory copy.

Obviously, these features cannot be realized under other operating systems, pcap_live_dump() is unique to WinPcap and can only be applied to Win32 environment.

Keywords: Linux network TCP/IP

Added by jinwu on Tue, 22 Feb 2022 05:33:49 +0200