Convert .txt to .pcap file

This file talks about converting .txt file to .pcap format file for wireshark.

Descriptions

Some time we may get the tcpdump logs, but we can't decode it in details like wireshark. For example.

>> tcpdump -i veip0.1 -s0 -eXxf host 199.71.142.187
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veip0.1, link-type EN10MB (Ethernet), capture size 65535 bytes
16:17:49.019616 d0:72:dc:8a:eb:30 (oui Unknown) > 00:06:31:eb:2d:f2 (oui Unknown), ethertype IPv4 (0x0800), length 74: 199.71.142.187.39117 > 100.74.0.180.30005: Flags [S], seq 1557343732, win 5840, options [mss 1380,sackOK,TS val 3117615132 ecr 0,nop,wscale 7], length 0
        0x0000:  4500 003c d803 0000 0106 26b8 c747 8ebb  E..<......&..G..
        0x0010:  644a 00b4 98cd 7535 5cd3 2df4 0000 0000  dJ....u5\.-.....
        0x0020:  a002 16d0 1bc5 0000 0204 0564 0402 080a  ...........d....
        0x0030:  b9d3 081c 0000 0000 0103 0307            ............
16:17:49.020058 00:06:31:eb:2d:f2 (oui Unknown) > d0:72:dc:8a:eb:30 (oui Unknown), ethertype IPv4 (0x0800), length 74: 100.74.0.180.30005 > 199.71.142.187.39117: Flags [S.], seq 1367236701, ack 1557343733, win 14480, options [mss 1460,sackOK,TS val 4821547 ecr 3117615132,nop,wscale 5], length 0
        0x0000:  4500 003c 0000 4000 4006 7fbb 644a 00b4  E..<..@.@...dJ..
        0x0010:  c747 8ebb 7535 98cd 517e 605d 5cd3 2df5  .G..u5..Q~`]\.-.
        0x0020:  a012 3890 bb2f 0000 0204 05b4 0402 080a  ..8../..........
        0x0030:  0049 922b b9d3 081c 0103 0305            .I.+........

We may want this view

Wireshark
Caption

 

 

 This file talks about the format of .pcap files, and implement it in C code.

Format of .pcap file

Format := [file_header][packet_header_1][packet_data_1][packet_header_2][packet_data_2]...[packet_header_N][packet_data_N]

typedef unsigned long DWORD;/* 4 BYTES*/
typedef unsigned short WORD;/* 2 BYTES*/
typedef unsigned char  BYTE;
  
/* file type */
typedef struct pcap_file_header {
    DWORD   magic;     /* magic number ,The magic number has the value hex a1b2c3d4. */
    WORD    version_major;    /* major version number,The major version number should have the value 2. */
    WORD    version_minor;    /* minor version number,The minor version number should have the value 4. */
    DWORD   thiszone;      /* time zone offset field that actually not used, so you can (and probably should) just make it 0 */
    DWORD   sigfigs;       /* time stamp accuracy field tha not actually used,so you can (and probably should) just make it 0*/
    DWORD   snaplen;       /* snapshot length&quot; field;The snapshot length field should be the maximum number of bytes perpacket that will be captured. If the entire packet is captured, make it 65535; if you only capture, for example, the first 64 bytes of the packet, make it 64.*/
    DWORD   linktype;      /* link layer type field.The link-layer type depends on the type of link-layer header that the packets in the capture file have
                            0            BSD       loopback devices, except for later OpenBSD
                            1            Ethernet, and Linux loopback devices
                            6            802.5 Token Ring
                            7            ARCnet
                            8            SLIP
                            9            PPP
                            10          FDDI
                            100        LLC/SNAP-encapsulated ATM
                            101        raw IP, with no link
                            102        BSD/OS SLIP
                            103        BSD/OS PPP
                            104        Cisco HDLC
                            105        802.11
                            108        later OpenBSD loopback devices (with the AF_value in network byte order)
                            113        special Linux cooked capture
                            114        LocalTalk */
} T_pcap_file_header;
 
  
/* time stamp */
struct tim {
    DWORD   GMTtime;       /* UNIX-format time-in-seconds when the packet was captured. i.e. the number of seconds since January 1,1970, 00:00:00 GMT (that GMT, *NOT* local time!) */
    DWORD   microTime;     /* the number of microseconds since that second when the packet was captured. */
};
 
  
/* Packet header */
typedef struct pcap_pkthdr {
    struct tim  ts;     /* time stamp */
    DWORD   caplen;        /* value giving the number of bytes of packet data that were captured. */
    DWORD   len;       /* value giving the actual length of the packet, in bytes (which may be greater than the previous number, if you are not saving the entire packet).*/
} T_pcap_pkthdr;
  
/* The packet data is the frame date. For example, Ethernet frame. */

Parse the txt file

In the example, there're 2 types of txt lines: 1) descriptions and 2) data.

(I think the script may be easier than C language to parse it.)

To parse the descriptions, a new structure is defined to record these inform we'll uses later.

typedef struct desc_parse {
    struct tim  ts;
    char macSrc[20];
    char macDst[20];
    unsigned int pro;
} T_desc_parse;
int parseDesc(const char *input, T_desc_parse *pDescParse);

To parse data, we also define a structure.

typedef struct pcap_data
{
    T_pcap_pkthdr header;
    BYTE dataBuff[DATA_BUFFER_MAX];
    DWORD dataIndex;/* start from 0 */
} T_pcap_data;
  
int parseData(const char *input, T_pcap_data *pDataBuff);

And the program will read the txt file and output into the pcap file with a small state machine.

All the code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pcap_typedef.h"
  
#define RTN_SUCCESS     0
#define RTN_FILE_ERROR  1
#define RTN_BAD_VALUE   2
  
#define LINE_TYPE_UNKNOWN   0   /* unknown      */
#define LINE_TYPE_DESC      1   /* description  */
#define LINE_TYPE_DATA      2   /* data         */
  
#define LINE_BUFFER_MAX     512
  
T_pcap_file_header pcapHeader = {
    .magic          = 0xa1b2c3d4,
    .version_major  = 0x02,
    .version_minor  = 0x04,
    .thiszone       = 0,
    .sigfigs        = 0,
    .snaplen        = 65535,
    .linktype       = 1/* Ethernet */
};
  
typedef struct desc_parse {
    struct tim  ts;
    char macSrc[20];
    char macDst[20];
    unsigned int pro;
} T_desc_parse;
  
typedef struct pcap_data
{
    T_pcap_pkthdr header;
    BYTE dataBuff[DATA_BUFFER_MAX];
    DWORD dataIndex;/* start from 0 */
} T_pcap_data;
  
T_pcap_data dataBuff; /* The buffer to file out */
T_desc_parse currDecParse; /* the buff for parsing description */
  
void setMac(BYTE *mac, const char *macSrc)
{
    unsigned int macs[6]={0};
    if(6==sscanf(macSrc, "%x:%x:%x:%x:%x:%x", &macs[0],&macs[1],&macs[2],&macs[3],&macs[4], &macs[5]))
    {
        mac[0]=macs[0]&0xFF;
        mac[1]=macs[1]&0xFF;
        mac[2]=macs[2]&0xFF;
        mac[3]=macs[3]&0xFF;
        mac[4]=macs[4]&0xFF;
        mac[5]=macs[5]&0xFF;
    }
}
  
int initPcapFileHeader(FILE *out)
{
    if(1 == fwrite(&pcapHeader, sizeof(T_pcap_file_header), 1, out))
    {
        return RTN_SUCCESS;
    }
    else
    {
        return RTN_FILE_ERROR;
    }
}
  
int setFileLen(FILE *out, DWORD len)
{
    pcapHeader.snaplen = len;
    if(0!=fseek(out, 0, SEEK_SET))
    {
        return RTN_FILE_ERROR;
    }
    if(1 == fwrite(&pcapHeader, sizeof(T_pcap_file_header), 1, out))
    {
        return RTN_SUCCESS;
    }
    else
    {
        return RTN_FILE_ERROR;
    }
}
  
int parseData(const char *input, T_pcap_data *pDataBuff)
{
    int lineIndex = 0;
    int count = 0;
    unsigned short value;
    char tmpBuff[100] = {0};
    char *pEnd;
    char *p;
    int status = 0;/* 0--ready to calculate values, 1--values there*/
     
    if(0 != strncmp(input, "0x", 2))
    {
        //printf("not data\n");
        return RTN_BAD_VALUE;
    }
    int n = sscanf(input,"%x: %[^\r\n]", &lineIndex, tmpBuff);
    if(2 == n)
    {
        pEnd = tmpBuff + strlen(tmpBuff) - 1;
        while((*pEnd != ' ') && (pEnd>tmpBuff))
        {
            pEnd--;
        }/* from the end, skip the last string */
        pEnd++;
/* special, add the Ethernet frame header */
        if(pDataBuff->dataIndex==0)
        {
            pDataBuff->dataIndex=(6*2+2);/* frame MAC+MAC+Protocol*/
        }
        p = tmpBuff;
        while(p<pEnd && count<8)
        {
            /* value*/
            if(*p == ' ')
            {
                if(status == 1)
                {
                    pDataBuff->dataBuff[pDataBuff->dataIndex] = ((value>>8)&0xFF);
                    pDataBuff->dataIndex++;
                    pDataBuff->dataBuff[pDataBuff->dataIndex] = (value&0xFF);
                    pDataBuff->dataIndex++;
                    count++;
                }
                value = 0;
                status = 0;
            }
            else if(*p>='0' && *p<='9')
            {
                value <<= 4;
                value += (*p-'0');
                status = 1;
            }
            else if(*p>='a' && *p<='f')
            {
                value <<= 4;
                value += (*p-'a'+10);
                status = 1;
            }
            else if(*p>='A' || *p<='F')
            {
                value <<= 4;
                value += (*p-'A'+10);
                status = 1;
            }
            else
            {
                 value = 0;
                 status = 0;
            }
            p++;
        }
    }
    else
    {
        printf("len is %d\n",n);
        return RTN_BAD_VALUE;
    }
    return RTN_SUCCESS;
}
  
int parseDesc(const char *input, T_desc_parse *pDescParse)
{
    int hour,minute,sec,msec;
    char macSrc[18] = {0};
    char macDst[18] = {0};
    unsigned int pro = 0;
     
    if(NULL == pDescParse)
    {
        return RTN_BAD_VALUE;
    }
    int n = sscanf(input, "%d:%d:%d.%d %[^( ] %*[^>] > %s %*[^)]), %*[^(] (%x) %*[^\r\n]",&hour,&minute,&sec,&msec, macSrc, macDst, &pro);
  
    if(7 == n)
    {
        memset(pDescParse, 0, sizeof(T_pcap_pkthdr));
        pDescParse->ts.GMTtime = sec+minute*60+hour*3600;
        pDescParse->ts.microTime = msec;
        strcpy(pDescParse->macDst,macDst);
        strcpy(pDescParse->macSrc,macSrc);
        pDescParse->pro = pro;
        //printf("[%s]>[%s]\n", macSrc, macDst);
    }
    else
    {
        return RTN_BAD_VALUE;
    }
    return RTN_SUCCESS;
}
int parseLine(char *pLine, int prevStatus)
{
    char *p = pLine;
    char *pStr;
    while((*p==' ') && (p<(pLine+LINE_BUFFER_MAX)))
    {
        p++;
    } /* skip space */
    if(p>=(pLine+LINE_BUFFER_MAX))
    {
        return LINE_TYPE_UNKNOWN;
    }
    pStr = p;
    if(RTN_SUCCESS == parseData(pStr, &dataBuff))
    {/* data*/
        return LINE_TYPE_DATA;
    }
    pStr = p;
    if(RTN_SUCCESS == parseDesc(pStr, &currDecParse))
    {
        //printf("parseDesc finished \n");
        return LINE_TYPE_DESC;
    }
    return LINE_TYPE_UNKNOWN;
}
  
int parseString2Pcap(FILE *fpIn, FILE *fpOut, DWORD *pLen)
{
    char line[LINE_BUFFER_MAX];
    int status = LINE_TYPE_UNKNOWN;
    int preStatus = LINE_TYPE_UNKNOWN;
    DWORD len = 0;
    int count = 0;
    memset(&dataBuff, 0, sizeof(dataBuff));
    memset(&currDecParse, 0, sizeof(currDecParse));
    while (fgets(line, LINE_BUFFER_MAX, fpIn) > 0)
    {/* read files */
        status = parseLine(line, preStatus);
        switch(status)
        {
            case LINE_TYPE_DATA:
                if(preStatus == LINE_TYPE_DESC)
                {
                    memcpy(&dataBuff.header, &currDecParse, sizeof(struct tim));
                    setMac(&dataBuff.dataBuff[0],currDecParse.macSrc);
                    setMac(&dataBuff.dataBuff[6],currDecParse.macDst);
                    //protocol
                    dataBuff.dataBuff[12]=((currDecParse.pro>>8)&0xFF);
                    dataBuff.dataBuff[13]=(currDecParse.pro&0xFF);
                     
                    memset(&currDecParse, 0, sizeof(currDecParse));
                }
                else if(preStatus == LINE_TYPE_UNKNOWN)
                {
                    printf("LINE_TYPE_UNKNOWN >> LINE_TYPE_DATA.\n");
                    return RTN_BAD_VALUE;
                }
                preStatus = LINE_TYPE_DATA;
                break;
            case LINE_TYPE_DESC:
                /* out put the old one */
                if(preStatus == LINE_TYPE_DATA)
                {
                    dataBuff.header.len = dataBuff.dataIndex;
                    dataBuff.header.caplen = dataBuff.header.len;
                     
                    len = (sizeof(dataBuff.header)+dataBuff.dataIndex);
                    *pLen += len;
                    //printf("write file len %d.\n",len);
                    if(len != fwrite(&dataBuff, sizeof(BYTE), len, fpOut))
                    {
                        printf("write file failed len %d.\n",len);
                        memset(&dataBuff, 0, sizeof(dataBuff));
                        return RTN_FILE_ERROR;
                    }
                    count++;
                    memset(&dataBuff,0,sizeof(dataBuff));
                }
                else if(preStatus == LINE_TYPE_DESC)
                {
                    printf("LINE_TYPE_DESC >> LINE_TYPE_DESC.\n");
                    return RTN_BAD_VALUE;
                }
                preStatus = LINE_TYPE_DESC;
                break;
            default:
                break;
        }
    }
    /* The last one. */
    dataBuff.header.len = dataBuff.dataIndex;
    dataBuff.header.caplen = dataBuff.header.len;
     
    len = (sizeof(dataBuff.header)+dataBuff.dataIndex);
    *pLen += len;
    //printf("write file len %d.\n",len);
    if(len != fwrite(&dataBuff, sizeof(BYTE), len, fpOut))
    {
        printf("write file failed len %d.\n",len);
        memset(&dataBuff, 0, sizeof(dataBuff));
        return RTN_FILE_ERROR;
    }
     
    count++;
    memset(&dataBuff,0,sizeof(dataBuff));
     
    printf("totally parse %d lines.\n", count);
    return RTN_SUCCESS;
}
  
int parse(const char *infile, const char *outfile)
{
    DWORD len = 0;
    int rtn = RTN_SUCCESS;
    FILE *fpIn = NULL;
    FILE *fpOut = NULL;
    if((fpIn = fopen(infile, "r")) == NULL)
    {
        printf("error open file %s!\n", infile);
        rtn = RTN_FILE_ERROR;
        goto exit;
    }
    if((fpOut = fopen(outfile, "wb")) == NULL)
    {
        printf("error open file %s!\n", outfile);
        rtn = RTN_FILE_ERROR;
        goto exit;
    }
    rtn = initPcapFileHeader(fpOut);
    if(RTN_SUCCESS!=rtn)
    {
        printf("error initPcapFileHeader !\n");
        goto exit;
    }
     
    rtn = parseString2Pcap(fpIn, fpOut, &len);
    if(RTN_SUCCESS!=rtn)
    {
        printf("error parseString2Pcap !\n");
        goto exit;
    }
     
    rtn = setFileLen(fpOut, len);
    if(RTN_SUCCESS!=rtn)
    {
        printf("error setFileLen !\n");
        goto exit;
    }
    rtn = RTN_SUCCESS;
exit:
    if(fpIn)
    {
        fclose(fpIn);
    }
    if(fpOut)
    {
        fflush(fpOut);
        fclose(fpOut);
    }
    return rtn;
}

It could be used by calling the function

parse("E:\\text2pcap\\testinput.txt", "E:\\text2pcap\\testoutput.pcap");

If the txt format is changed, the parseDesc may also be changed.

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值