【转载】cap,pcap文件中的ipv4数据包转成ipv6数据包

来源:https://blog.csdn.net/mincheat/article/details/78180656

cap , pcap文件结构(解析),网上多得是,这里就不写了。  写这个,主要是工作中正好需要大量的ipv6数据包,但是ipv6数据包不太好找,干脆就直接写个简单的工具,把ipv4转成对应的ipv6,可用于测试。 

 

cpp代码:

// Ipv4ToIpv6_pCap.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include <windows.h>
 
#define  DLT_EN10MB 1
 
struct pcap_file_header {
    UINT32 magic;
    UINT16 version_major;
    UINT16 version_minor;
    UINT32 thiszone;    /* gmt to local correction */
    UINT32 sigfigs;    /* accuracy of timestamps */
    UINT32 snaplen;    /* max length saved portion of each pkt */
    UINT32 linktype;    /* data link type (LINKTYPE_*) */
};
 
struct pcap_pkthdr {
    struct timeval ts;    /* time stamp */
    UINT32 caplen;    /* length of portion present */
    UINT32 len;    /* length this packet (off wire) */
};
 
struct EthernetPacket
{
    char MacDst[6];             ///< 目的网卡物理地址
    char MacSrc[6];             ///< 源网卡物理地址
    unsigned short PacketType; ///< 包类型, ip或ARP等
};
 
struct PKT_IP
{
    UINT8 uHeaderLen:4;
    UINT8 uVersion:4;
    UINT8 uServType;
    UINT16 uTotalLen;
    UINT16 uIdent;
    UINT16 uFragOffset;
    UINT8 uTTL;
    UINT8 uProtocol;
    UINT16 uCheckSum;
    UINT32 addSrc;
    UINT32 addDst;
};
 
struct PKT_IPV6
{
    union
    {
        UINT32 Vfc;
        struct
        {
            UINT8 uClass:4;
            UINT8 uVersion:4;
        };
    };
    UINT16 uPayloadLength;
    UINT8 uNextHeader;
    UINT8 uHopLimit;
    UINT8 addrSrc[16];
    UINT8 addrDst[16];
};
 
inline UINT16 NTOH16(const UINT16& nData)
{
    return ((nData & 0xFF00) >> 8) | ((nData & 0x00FF) << 8);
}
 
inline UINT32 NTOH32(const UINT32& nData)
{
    return ((nData & 0xFF000000) >> 24)
        | ((nData & 0x00FF0000) >> 8)
        | ((nData & 0x0000FF00) << 8)
        | ((nData & 0x000000FF) << 24);
}
 
int _tmain(int argc, char* argv[])
{
    if (argc != 3)
    {
        printf("arg: inputfile, outputfile! \n");
        //getchar();
        return -1;
    }
    
 
    FILE* pFileIn = fopen(argv[1], "rb");
    FILE* pFileOut = fopen(argv[2], "wb");
 
    bool bSucces = false;
    do 
    {
        if (NULL == pFileIn || NULL == pFileOut)
        {
            printf("open file fail \n");
            break;
        }
 
        pcap_file_header fileheader;
        memset(&fileheader, 0, sizeof(pcap_file_header));
        fread(&fileheader, 1, sizeof(fileheader), pFileIn);
 
        if (DLT_EN10MB != fileheader.linktype)
        {
            printf("only support enthernet catch packets! \n");
            break;
        }
 
        fwrite(&fileheader, 1, sizeof(fileheader), pFileOut);
 
        pcap_pkthdr pkHdr;
        UINT32 packetTotalCount = 0;
        UINT32 packetTran = 0;
        UINT8  packetBuffer[5*1024] = {};
        do 
        {
            
            if (sizeof(pkHdr) == fread(&pkHdr, 1, sizeof(pkHdr), pFileIn))
            {
                if (pkHdr.caplen != pkHdr.len)
                {
                    // add 
                    //printf("pkHdr.caplen != pkHdr.len     packetNum = %d \n", packetTotalCount+1);
                }
                if (pkHdr.caplen == fread(packetBuffer, 1, pkHdr.caplen, pFileIn) && pkHdr.caplen > sizeof(EthernetPacket))
                {
                    EthernetPacket* pEPacket = (EthernetPacket*)packetBuffer;
                    if (0x08 == pEPacket->PacketType)  // ipv4
                    {
                        // 
                        PKT_IP* pIpHdr = (PKT_IP*)(packetBuffer + sizeof(EthernetPacket));
                        
                        pIpHdr->uTotalLen = NTOH16(pIpHdr->uTotalLen);
                        if (pkHdr.caplen < pIpHdr->uTotalLen + sizeof(EthernetPacket))   // 后面有可能会有补的数据,所以caplen可以会大于后面的值
                        {
                            printf("len error! packetNum = %d \n", packetTotalCount+1);
                            break;
                        }
                        
 
                        pEPacket->PacketType = 0xDD86;
                        PKT_IPV6 pktIpv6Hdr;
                        memset(&pktIpv6Hdr, 0, sizeof(pktIpv6Hdr));
                        pktIpv6Hdr.uVersion = 6;
                        //pktIpv6Hdr.Vfc = CSNTOH32(pktIpv6Hdr.Vfc);
 
                        UINT16 paylen = pIpHdr->uTotalLen - pIpHdr->uHeaderLen*4;
                        pktIpv6Hdr.uPayloadLength = NTOH16(paylen);
 
                        pktIpv6Hdr.uNextHeader = pIpHdr->uProtocol;
 
                        pktIpv6Hdr.uHopLimit = pIpHdr->uTTL;
                        memcpy(pktIpv6Hdr.addrSrc+12, &(pIpHdr->addSrc), 4);
                        memcpy(pktIpv6Hdr.addrDst+12, &(pIpHdr->addDst), 4);
 
                        pkHdr.caplen = sizeof(EthernetPacket) + sizeof(PKT_IPV6) + paylen;
                        pkHdr.len = pkHdr.caplen;
                        fwrite(&pkHdr, 1, sizeof(pkHdr), pFileOut);   // 写pack header
                        fwrite(pEPacket, 1, sizeof(EthernetPacket), pFileOut);  // 写ether
                        fwrite(&pktIpv6Hdr, 1, sizeof(PKT_IPV6), pFileOut);  // 写ipv6头
                        UINT8* pOtherData = packetBuffer + sizeof(EthernetPacket) + pIpHdr->uHeaderLen*4;
                        fwrite(pOtherData, 1, paylen, pFileOut); // 写剩下的数据
 
                        packetTran++;
                    }
                    else
                    {
                        // 其他包,直接写入
                        fwrite(&pkHdr, 1, sizeof(pkHdr), pFileOut);
                        fwrite(packetBuffer, 1, pkHdr.caplen, pFileOut);
                    }
                }
                else
                {
                    printf("read packet caplen less    packetNum = %d \n", packetTotalCount+1);
                    break;
                }
 
                packetTotalCount++;
            }
            else
            {
                if (feof(pFileIn))
                {
                    //printf("read end!  \n");
                    bSucces = true;
                }
                else
                {
                    printf("Read less data! packetTotalCount = %d \n", packetTotalCount);
                }
                break;
            }
            
        } while (true/*!feof(pFileIn)*/);
 
        printf("totalPacket = %d, transPacket = %d\n", packetTotalCount, packetTran);
 
    } while (false);
    
 
    
    if (pFileIn)
    {
        fclose(pFileIn);
    }
    
    if (pFileOut)
    {
        fclose(pFileOut);
    }
    
    if (!bSucces)
    {
        printf("Process %s fail! \n", argv[1]);
        DeleteFileA(argv[2]);
    }
 
    //getchar();
    //pcap_file_header
    return 0;
}

另外还有个批处理文件 .bat

@echo off 
::cd %~dp0 

set inputFolder=E:\work\vsproject\Ipv4ToIpv6_pCap\Debug
set outPutFolder=E:\work\vsproject\Ipv4ToIpv6_pCap\Debug\newFolder
set exepath=E:\work\vsproject\Ipv4ToIpv6_pCap\Debug\Ipv4ToIpv6_pCap.exe
set suffix=_ipv6.cap


for /f "delims=\" %%s in ('dir /b /a-d /o-d %inputFolder%\*.pcap,*.cap') do (
    echo -------------handle filename = %%s ------------
    %exepath% %inputFolder%\%%s  %outPutFolder%\%%s%suffix%
)


pause

 

posted @ 2025-10-23 13:22  wAn9  阅读(10)  评论(0)    收藏  举报