cap,pcap文件中的ipv4数据包转成ipv6数据包
2017-10-09 11:12
986 查看
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
写得比较简单,但是用于测试,还是可以的
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
写得比较简单,但是用于测试,还是可以的
相关文章推荐
- Jnetpcap 官方实例(4)- 将捕获的数据包写入文件
- pcap_dump()所保存.cap文件格式
- cap文件类型的数据包结构分析
- libpcap--GTPv2协议的cap文件解析
- 解析pcap文件,提取具有指定协议的特征字符串的数据包
- 从pcap文件中分析出数据包
- python解析pcap文件中的http数据包
- 承载于以太网帧之上的数据包的解析——ARP、IPv4、IPv6
- [CCIE笔记]IPv6——IPv6与IPv4数据包内容的变化
- 基于 Anaconda3 5.0.0 JupyterLab 0.27.0 使用 ftplib 演示 IPv4 和 IPv6 上传文件和下载文件
- cap数据包文件解析
- Ubuntu16.04安装libpcap开发库对pcap文件中的数据包进行过滤
- cap数据包文件解析
- Centos下网卡配置文件详细参数IPV6 和 IPV4
- 承载于以太网帧之上的数据包的解析——ARP、IPv4、IPv6
- 由pcap文件提取IPv6的flow数据
- IPv4与IPv6数据包格式
- 使用libpcap库过滤pcap文件中的数据包
- cap数据包文件解析
- Jnetpcap 官方案例(3)- 从离线文件捕获数据包