netkitty
Version:
Network tools kit
124 lines (113 loc) • 4.21 kB
text/typescript
/**
* 由pcap-generator库改写
* @see:https://github.com/onomondo/pcap-generator/tree/master
*/
import BigNumber from 'bignumber.js'
export type GeneratePCAPInputPacket = {
frameBase64Data: string
timestamp?: number
microsecond?: {
seconds: number
microseconds: number
}
}
export type GeneratePCAPPacket = {
buffer: Buffer,
timestamp?: number,
microsecond?: {
seconds: number
microseconds: number
}
}
const headerOptions: {
majorVersion: number//Major version of pcap. Default: 2
minorVersion: number//Minor version of pcap. Default: 4
gmtOffset: number//The GMT offset in pcap. Default: 0
timestampAccuracy: number//The accuracy of the timestamps. Default: 0
snapshotLength: number//The snapshot length of the packets. Default: 65535
linkLayerType: number//The type of packets in the file. E.g. 101 for raw IP packets, or 1 for Ethernet packets. See https://www.tcpdump.org/linktypes.html for more details Default: 101 (Raw IP packets)
} = {
majorVersion: 2,
minorVersion: 4,
gmtOffset: 0,
timestampAccuracy: 0,
snapshotLength: 65535,
linkLayerType: 1
}
function generate(packets: GeneratePCAPPacket[]): Buffer {
const globalHeader: Buffer = GeneratePCAPHeader()
const packetsBuffer: Buffer = Buffer.concat(packets.map((packet: GeneratePCAPPacket): Buffer => GeneratePCAPData(packet)))
return Buffer.concat([globalHeader, packetsBuffer])
}
/**
* Converts a timestamp in milliseconds to an integer of the seconds part and an integer of the microseconds part
*
* @param ms
*/
function convertMillisecond2Microsecond(ms: number): [number, number] {
const [seconds, microseconds] = new BigNumber(ms).dividedBy(1000).toFixed(6).split('.').map(value => parseInt(value))
return [seconds, microseconds]
}
function makeLessThanAMillion(i: number): number {
while (i > 1000000) {
i = Math.floor(i / 10)
}
return i
}
/**
* Generate pcap file header's buffer
* @constructor
*/
export function GeneratePCAPHeader(): Buffer {
const globalHeader: Buffer = Buffer.alloc(24)
globalHeader.writeUInt32BE(2712847316, 0) // 4
globalHeader.writeUInt16BE(headerOptions.majorVersion, 4) // 2
globalHeader.writeUInt16BE(headerOptions.minorVersion, 6) // 2
globalHeader.writeInt32BE(headerOptions.gmtOffset, 8) // 4
globalHeader.writeUInt32BE(headerOptions.timestampAccuracy, 12) // 4
globalHeader.writeUInt32BE(headerOptions.snapshotLength, 16) // 4
globalHeader.writeUInt32BE(headerOptions.linkLayerType, 20) // 4
return globalHeader
}
/**
* Generate single record data in pcap file
* @param packet
* @constructor
*/
export function GeneratePCAPData(packet: GeneratePCAPPacket): Buffer {
const packetHeader: Buffer = Buffer.alloc(16)
let seconds: number
let microseconds: number
if (packet.microsecond) {
seconds = packet.microsecond.seconds
microseconds = packet.microsecond.microseconds
} else {
if (packet.timestamp) {
[seconds, microseconds] = convertMillisecond2Microsecond(packet.timestamp)
} else {
seconds = 0
microseconds = 0
}
}
packetHeader.writeUInt32BE(seconds, 0) // 4
if (packet.microsecond) {
packetHeader.writeUInt32BE(microseconds, 4) // 4 - if in microsecond precision then remove excess of 1,000,000 (see documentation)
} else {
packetHeader.writeUInt32BE(makeLessThanAMillion(microseconds), 4) // 4 - if in microsecond precision then remove excess of 1,000,000 (see documentation)
}
packetHeader.writeUInt32BE(packet.buffer.length, 8) // 4
packetHeader.writeUInt32BE(packet.buffer.length, 12) // 4
return Buffer.concat([packetHeader, packet.buffer])
}
/**
* Generate whole pcap file buffer data
* @param packets
* @constructor
*/
export function GeneratePCAP(packets: GeneratePCAPInputPacket[] = []): Buffer {
return generate(packets.map((packet: GeneratePCAPInputPacket): GeneratePCAPPacket => ({
timestamp: packet.timestamp,
microsecond: packet.microsecond,
buffer: Buffer.from(packet.frameBase64Data, 'base64')
})))
}