UNPKG

netkitty

Version:
900 lines (899 loc) 49.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TCP = void 0; const BaseHeader_1 = require("../abstracts/BaseHeader"); const BufferToNumber_1 = require("../../helper/BufferToNumber"); const NumberToBuffer_1 = require("../../helper/NumberToBuffer"); const IPToBuffer_1 = require("../../helper/IPToBuffer"); const StringContentEncodingEnum_1 = require("../lib/StringContentEncodingEnum"); const NumberToHex_1 = require("../../helper/NumberToHex"); const HexToNumber_1 = require("../../helper/HexToNumber"); var TCPOption; (function (TCPOption) { TCPOption["End_of_Option_List"] = "EOL"; TCPOption["No_Operation"] = "NOP"; TCPOption["Maximum_Segment_Size"] = "MSS"; TCPOption["Window_Scale"] = "Window-Scale"; TCPOption["Selective_Acknowledgment_Permitted"] = "SACK-Permitted"; TCPOption["Selective_Acknowledgment"] = "SACK"; TCPOption["Timestamp"] = "TS"; TCPOption["User_Timeout"] = "UTO"; TCPOption["TCP_Authentication_Option"] = "TCP-AO"; })(TCPOption || (TCPOption = {})); class TCP extends BaseHeader_1.BaseHeader { constructor() { super(...arguments); this.SCHEMA = { type: 'object', properties: { srcport: { type: 'integer', label: 'Source Port', minimum: 0, maximum: 65535, decode: () => { this.instance.srcport.setValue((0, BufferToNumber_1.BufferToUInt16)(this.readBytes(0, 2))); }, encode: () => { let srcport = this.instance.srcport.getValue(0, (nodePath) => this.recordError(nodePath, 'Not Found')); if (srcport > 65535) { this.recordError(this.instance.srcport.getPath(), 'Maximum value is 65535'); srcport = 65535; } if (srcport < 0) { this.recordError(this.instance.srcport.getPath(), 'Minimum value is 0'); srcport = 0; } this.instance.srcport.setValue(srcport); this.writeBytes(0, (0, NumberToBuffer_1.UInt16ToBuffer)(srcport)); } }, dstport: { type: 'integer', label: 'Destination Port', minimum: 0, maximum: 65535, decode: () => { this.instance.dstport.setValue((0, BufferToNumber_1.BufferToUInt16)(this.readBytes(2, 2))); }, encode: () => { let dstport = this.instance.dstport.getValue(0, (nodePath) => this.recordError(nodePath, 'Not Found')); if (dstport > 65535) { this.recordError(this.instance.dstport.getPath(), 'Maximum value is 65535'); dstport = 65535; } if (dstport < 0) { this.recordError(this.instance.dstport.getPath(), 'Minimum value is 0'); dstport = 0; } this.instance.dstport.setValue(dstport); this.writeBytes(2, (0, NumberToBuffer_1.UInt16ToBuffer)(dstport)); } }, seq: { type: 'integer', label: 'Sequence Number', minimum: 0, maximum: 4294967295, decode: () => { this.instance.seq.setValue((0, BufferToNumber_1.BufferToUInt32)(this.readBytes(4, 4))); }, encode: () => { let seqNum = this.instance.seq.getValue(0); if (seqNum > 4294967295) { this.recordError(this.instance.seq.getPath(), 'Maximum value is 4294967295'); seqNum = 4294967295; } if (seqNum < 0) { this.recordError(this.instance.seq.getPath(), 'Minimum value is 0'); seqNum = 0; } this.instance.seq.setValue(seqNum); this.writeBytes(4, (0, NumberToBuffer_1.UInt32ToBuffer)(seqNum)); } }, ack: { type: 'integer', label: 'Acknowledgment Number', minimum: 0, maximum: 4294967295, decode: () => { this.instance.ack.setValue((0, BufferToNumber_1.BufferToUInt32)(this.readBytes(8, 4))); }, encode: () => { let ackNum = this.instance.ack.getValue(0); if (ackNum > 4294967295) { this.recordError(this.instance.ack.getPath(), 'Maximum value is 4294967295'); ackNum = 4294967295; } if (ackNum < 0) { this.recordError(this.instance.ack.getPath(), 'Minimum value is 0'); ackNum = 0; } this.instance.ack.setValue(ackNum); this.writeBytes(8, (0, NumberToBuffer_1.UInt32ToBuffer)(ackNum)); } }, hdrLen: { type: 'integer', label: 'Header Length', minimum: 0, maximum: 60, decode: () => { this.instance.hdrLen.setValue(this.readBits(12, 1, 0, 4) * 4); }, encode: () => { let hdrLen = this.instance.hdrLen.getValue(0); if (hdrLen) { this.instance.hdrLen.setValue(hdrLen); this.writeBits(12, 1, 0, 4, hdrLen ? Math.floor(hdrLen / 4) : 0); } else { this.addPostSelfEncodeHandler(() => { this.instance.hdrLen.setValue(Math.floor(this.length / 4) * 4); this.writeBits(12, 1, 0, 4, Math.floor(this.length / 4)); }, 1); } } }, flags: { type: 'object', label: 'Flags', properties: { res: { type: 'integer', label: 'Reserved', minimum: 0, maximum: 7, decode: () => { this.instance.flags.res.setValue(this.readBits(12, 1, 4, 3)); }, encode: () => { let reserved = this.instance.flags.res.getValue(0); if (reserved > 7) { this.recordError(this.instance.flags.res.getPath(), 'Maximum value is 7'); reserved = 7; } if (reserved < 0) { this.recordError(this.instance.flags.res.getPath(), 'Minimum value is 0'); reserved = 0; } this.instance.flags.res.setValue(reserved); this.writeBits(12, 1, 4, 3, reserved); } }, ae: { type: 'boolean', label: 'Accurate ECN', decode: () => { this.instance.flags.ae.setValue(!!this.readBits(12, 1, 7, 1)); }, encode: () => { const accurateECN = !!this.instance.flags.ae.getValue(); this.instance.flags.ae.setValue(accurateECN); this.writeBits(12, 1, 7, 1, accurateECN ? 1 : 0); } }, cwr: { type: 'boolean', label: 'Congestion Window Reduced', decode: () => { this.instance.flags.cwr.setValue(!!this.readBits(13, 1, 0, 1)); }, encode: () => { const congestionWindowReduced = !!this.instance.flags.cwr.getValue(); this.instance.flags.cwr.setValue(congestionWindowReduced); this.writeBits(13, 1, 0, 1, congestionWindowReduced ? 1 : 0); } }, ece: { type: 'boolean', label: 'ECN-Echo', decode: () => { this.instance.flags.ece.setValue(!!this.readBits(13, 1, 1, 1)); }, encode: () => { const ECNEcho = !!this.instance.flags.ece.getValue(); this.instance.flags.ece.setValue(ECNEcho); this.writeBits(13, 1, 1, 1, ECNEcho ? 1 : 0); } }, urg: { type: 'boolean', label: 'Urgent', decode: () => { this.instance.flags.urg.setValue(!!this.readBits(13, 1, 2, 1)); }, encode: () => { const urgent = !!this.instance.flags.urg.getValue(); this.instance.flags.urg.setValue(urgent); this.writeBits(13, 1, 2, 1, urgent ? 1 : 0); } }, ack: { type: 'boolean', label: 'Acknowledgment', decode: () => { this.instance.flags.ack.setValue(!!this.readBits(13, 1, 3, 1)); }, encode: () => { const acknowledgment = !!this.instance.flags.ack.getValue(); this.instance.flags.ack.setValue(acknowledgment); this.writeBits(13, 1, 3, 1, acknowledgment ? 1 : 0); } }, push: { type: 'boolean', label: 'Push', decode: () => { this.instance.flags.push.setValue(!!this.readBits(13, 1, 4, 1)); }, encode: () => { const push = !!this.instance.flags.push.getValue(); this.instance.flags.push.setValue(push); this.writeBits(13, 1, 4, 1, push ? 1 : 0); } }, rst: { type: 'boolean', label: 'Reset', decode: () => { this.instance.flags.rst.setValue(!!this.readBits(13, 1, 5, 1)); }, encode: () => { const reset = !!this.instance.flags.rst.getValue(); this.instance.flags.rst.setValue(reset); this.writeBits(13, 1, 5, 1, reset ? 1 : 0); } }, syn: { type: 'boolean', label: 'Syn', decode: () => { this.instance.flags.syn.setValue(!!this.readBits(13, 1, 6, 1)); }, encode: () => { const syn = !!this.instance.flags.syn.getValue(); this.instance.flags.syn.setValue(syn); this.writeBits(13, 1, 6, 1, syn ? 1 : 0); } }, fin: { type: 'boolean', label: 'Fin', decode: () => { this.instance.flags.fin.setValue(!!this.readBits(13, 1, 7, 1)); }, encode: () => { const fin = !!this.instance.flags.fin.getValue(); this.instance.flags.fin.setValue(fin); this.writeBits(13, 1, 7, 1, fin ? 1 : 0); } } } }, window: { type: 'integer', label: 'Window Size', minimum: 0, maximum: 65535, decode: () => { this.instance.window.setValue((0, BufferToNumber_1.BufferToUInt16)(this.readBytes(14, 2))); }, encode: () => { let windowSize = this.instance.window.getValue(0); if (windowSize > 65535) { this.recordError(this.instance.window.getPath(), 'Maximum value is 65535'); windowSize = 65535; } if (windowSize < 0) { this.recordError(this.instance.window.getPath(), 'Minimum value is 0'); windowSize = 0; } this.instance.window.setValue(windowSize); this.writeBytes(14, (0, NumberToBuffer_1.UInt16ToBuffer)(windowSize)); } }, checksum: { type: 'integer', label: 'Checksum', minimum: 0, maximum: 65535, decode: () => { this.instance.checksum.setValue((0, BufferToNumber_1.BufferToUInt16)(this.readBytes(16, 2))); }, encode: () => { let checksum = this.instance.checksum.getValue(0); if (checksum) { this.instance.checksum.setValue(checksum); this.writeBytes(16, (0, NumberToBuffer_1.UInt16ToBuffer)(checksum)); } else { this.instance.checksum.setValue(checksum); this.writeBytes(16, (0, NumberToBuffer_1.UInt16ToBuffer)(checksum)); this.addPostPacketEncodeHandler(() => { //Calculate checksum after packet encoded let startPos = 0; let endPos = 0; this.codecModules.forEach((codecModule) => { if (codecModule === this) startPos = codecModule.startPos; endPos = codecModule.endPos > endPos ? codecModule.endPos : endPos; }); const calcChecksum = this.calculateTCPChecksum(this.packet.subarray(startPos, endPos)); this.instance.checksum.setValue(calcChecksum); this.writeBytes(16, (0, NumberToBuffer_1.UInt16ToBuffer)(calcChecksum)); }, 100); } } }, urgPtr: { type: 'integer', label: 'Urgent Pointer', minimum: 0, maximum: 65535, decode: () => { this.instance.urgPtr.setValue((0, BufferToNumber_1.BufferToUInt16)(this.readBytes(18, 2))); }, encode: () => { let urgPtr = this.instance.urgPtr.getValue(0); if (urgPtr > 65535) { this.recordError(this.instance.urgPtr.getPath(), 'Maximum value is 65535'); urgPtr = 65535; } if (urgPtr < 0) { this.recordError(this.instance.urgPtr.getPath(), 'Minimum value is 0'); urgPtr = 0; } this.instance.urgPtr.setValue(urgPtr); this.writeBytes(18, (0, NumberToBuffer_1.UInt16ToBuffer)(urgPtr)); } }, options: { type: 'array', label: 'Options', items: { anyOf: [ //Kind = 0 (End of Option List, EOL) { type: 'object', label: 'End of Option List', properties: { option: { type: 'string', label: 'Option', enum: [TCPOption.End_of_Option_List] } } }, //Kind = 1 (No-Operation, NOP) { type: 'object', label: 'No-Operation', properties: { option: { type: 'string', label: 'Option', enum: [TCPOption.No_Operation] } } }, //Kind = 2 (Maximum Segment Size, MSS) { type: 'object', label: 'Maximum Segment Size', properties: { option: { type: 'string', label: 'Option', enum: [TCPOption.Maximum_Segment_Size] }, mss: { type: 'integer', label: 'MSS', maximum: 65535, minimum: 0 } } }, //Kind = 3 (Window Scale) { type: 'object', label: 'Window Scale', properties: { option: { type: 'string', label: 'Option', enum: [TCPOption.Window_Scale] }, shift: { type: 'integer', label: 'Shift count', minimum: 0, maximum: 14 } } }, //Kind = 4 (Selective Acknowledgment Permitted, SACK-Permitted) { type: 'object', label: 'Selective Acknowledgment Permitted', properties: { option: { type: 'string', label: 'Option', enum: [TCPOption.Selective_Acknowledgment_Permitted] } } }, //Kind = 5 (Selective Acknowledgment, SACK) { type: 'object', label: 'Selective Acknowledgment', properties: { option: { type: 'string', label: 'Option', enum: [TCPOption.Selective_Acknowledgment] }, blocks: { type: 'array', label: 'SACK Blocks', items: { type: 'string', maxLength: 16, minLength: 16, contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX } } } }, //Kind = 8 (Timestamp, TS) { type: 'object', label: 'Timestamp', properties: { option: { type: 'string', label: 'Option', enum: [TCPOption.Timestamp] }, tsval: { type: 'integer', label: 'TSval', minimum: 0, maximum: 4294967295 }, tsecr: { type: 'integer', label: 'TSecr', minimum: 0, maximum: 4294967295 } } }, //Kind = 28 (User Timeout, UTO) { type: 'object', label: 'User Timeout', properties: { option: { type: 'string', label: 'Option', enum: [TCPOption.User_Timeout] }, timeout: { type: 'integer', label: 'Timeout', minimum: 0, maximum: 65535 }, granularity: { type: 'integer', label: 'Granularity', enum: [0, 1] } } }, //Kind = 29 (TCP Authentication Option, TCP-AO) { type: 'object', label: 'TCP Authentication Option', properties: { option: { type: 'string', label: 'Option', enum: [TCPOption.TCP_Authentication_Option] }, data: { type: 'string', label: 'Data', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX } } }, //Default { type: 'object', label: 'Default', properties: { kind: { type: 'integer', label: 'Kind' }, data: { type: 'string', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX, label: 'Data' } } } ] }, decode: () => { const hdrLen = this.instance.hdrLen.getValue(); const optionsLength = hdrLen - this.length; if (!optionsLength) return; let optionOffset = this.length; const options = []; let index = 0; while (optionOffset < hdrLen) { const kind = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); optionOffset += 1; switch (kind) { //Kind = 0 (End of Option List, EOL) case 0: { options.push({ option: TCPOption.End_of_Option_List }); } break; //Kind = 1 (No-Operation, NOP) case 1: { options.push({ option: TCPOption.No_Operation }); } break; //Kind = 2 (Maximum Segment Size, MSS) case 2: { let length = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); if (length !== 4) this.recordError(this.instance.options.getPath(index), 'MSS option TLV length should be 4'); optionOffset += 1; let value = (0, BufferToNumber_1.BufferToUInt16)(this.readBytes(optionOffset, 2)); optionOffset += 2; options.push({ option: TCPOption.Maximum_Segment_Size, mss: value }); } break; //Kind = 3 (Window Scale) case 3: { let length = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); if (length !== 3) this.recordError(this.instance.options.getPath(index), 'Window Scale option TLV length should be 3'); optionOffset += 1; let value = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); optionOffset += 1; if (value < 0 || value > 14) this.recordError(this.instance.options.getPath(index), 'Window Scale option TLV value should between 0 and 14'); options.push({ option: TCPOption.Window_Scale, shift: value }); } break; //Kind = 4 (Selective Acknowledgment Permitted, SACK-Permitted) case 4: { let length = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); optionOffset += 1; if (length !== 2) this.recordError(this.instance.options.getPath(index), 'SACK-Permitted option TLV length should be 2'); options.push({ option: TCPOption.Selective_Acknowledgment_Permitted }); } break; //Kind = 5 (Selective Acknowledgment, SACK) case 5: { let length = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); optionOffset += 1; let sackBlockTotalLength = length - 2; if (sackBlockTotalLength < 0) { this.recordError(this.instance.options.getPath(index), 'SACK option block count should not less than 0'); sackBlockTotalLength = 0; } let sackBlockCount = sackBlockTotalLength ? Math.floor(sackBlockTotalLength / 8) : 0; const sackBlocks = []; while (sackBlockCount > 0) { sackBlocks.push((0, NumberToHex_1.UInt64ToHex)(BigInt(`0x${(0, BufferToNumber_1.BufferToUInt64)(this.readBytes(optionOffset, 8)).toString(16)}`))); optionOffset += 8; sackBlockCount -= 1; } options.push({ option: TCPOption.Selective_Acknowledgment, blocks: sackBlocks }); } break; //Kind = 8 (Timestamp, TS) case 8: { let length = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); optionOffset += 1; if (length !== 10) this.recordError(this.instance.options.getPath(index), 'Timestamp option TLV length should be 10'); let tsval = (0, BufferToNumber_1.BufferToUInt32)(this.readBytes(optionOffset, 4)); optionOffset += 4; let tsecr = (0, BufferToNumber_1.BufferToUInt32)(this.readBytes(optionOffset, 4)); optionOffset += 4; options.push({ option: TCPOption.Timestamp, tsval: tsval, tsecr: tsecr }); } break; //Kind = 28 (User Timeout, UTO) case 28: { let length = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); optionOffset += 1; if (length !== 5) this.recordError(this.instance.options.getPath(index), 'UTO option TLV length should be 5'); let timeout = (0, BufferToNumber_1.BufferToUInt16)(this.readBytes(optionOffset, 2)); optionOffset += 2; let granularity = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); optionOffset += 1; options.push({ option: TCPOption.User_Timeout, timeout: timeout, granularity: granularity }); } break; //Kind = 29 (TCP Authentication Option, TCP-AO) case 29: { let length = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); optionOffset += 1; let dataLength = length - 2; if (dataLength < 0) { this.recordError(this.instance.options.getPath(index), 'TCP Authentication Option TLV length should not less than 2'); dataLength = 0; } let data; if (dataLength) { data = this.readBytes(optionOffset, dataLength); optionOffset += dataLength; } else { data = Buffer.from([]); } options.push({ option: TCPOption.TCP_Authentication_Option, data: data.toString('hex') }); } break; default: { let length = (0, BufferToNumber_1.BufferToUInt8)(this.readBytes(optionOffset, 1)); let dataLength = length - 2; if (dataLength < 0) { this.recordError(this.instance.options.getPath(index), 'Option TLV length should not less than 2'); dataLength = 0; } let data; if (dataLength) { data = this.readBytes(optionOffset, dataLength); optionOffset += dataLength; } else { data = Buffer.from([]); } options.push({ kind: kind, data: data.toString('hex') }); } } index += 1; } this.instance.options.setValue(options); }, encode: () => { const options = this.instance.options.getValue(); if (!options) return; let optionOffset = this.length; options.forEach((optionItem) => { const namedOptionItem = optionItem; switch (namedOptionItem.option) { case TCPOption.End_of_Option_List: { const optionEOL = optionItem; this.writeBytes(optionOffset, (0, NumberToBuffer_1.UInt8ToBuffer)(0)); optionOffset += 1; return; } case TCPOption.No_Operation: { const optionNOP = optionItem; this.writeBytes(optionOffset, (0, NumberToBuffer_1.UInt8ToBuffer)(1)); optionOffset += 1; return; } case TCPOption.Maximum_Segment_Size: { const optionMSS = optionItem; const mssBuffer = Buffer.concat([ (0, NumberToBuffer_1.UInt8ToBuffer)(2), (0, NumberToBuffer_1.UInt8ToBuffer)(4), (0, NumberToBuffer_1.UInt16ToBuffer)(optionMSS.mss) ]); this.writeBytes(optionOffset, mssBuffer); optionOffset += mssBuffer.length; return; } case TCPOption.Window_Scale: { const optionWS = optionItem; const wsBuffer = Buffer.concat([ (0, NumberToBuffer_1.UInt8ToBuffer)(3), (0, NumberToBuffer_1.UInt8ToBuffer)(3), (0, NumberToBuffer_1.UInt8ToBuffer)(optionWS.shift) ]); this.writeBytes(optionOffset, wsBuffer); optionOffset += wsBuffer.length; return; } case TCPOption.Selective_Acknowledgment_Permitted: { const optionSackPermitted = optionItem; const sackPermittedBuffer = Buffer.concat([ (0, NumberToBuffer_1.UInt8ToBuffer)(4), (0, NumberToBuffer_1.UInt8ToBuffer)(2) ]); this.writeBytes(optionOffset, sackPermittedBuffer); optionOffset += sackPermittedBuffer.length; return; } case TCPOption.Selective_Acknowledgment: { const optionSack = optionItem; const kindBuffer = (0, NumberToBuffer_1.UInt8ToBuffer)(5); let length = 2; let blocksBuffer = Buffer.from([]); optionSack.blocks.forEach((block) => { blocksBuffer = Buffer.concat([blocksBuffer, (0, NumberToBuffer_1.UInt64ToBuffer)((0, HexToNumber_1.HexToUInt64)(block))]); }); const sackBuffer = Buffer.concat([kindBuffer, (0, NumberToBuffer_1.UInt8ToBuffer)(length + blocksBuffer.length), blocksBuffer]); this.writeBytes(optionOffset, sackBuffer); optionOffset += sackBuffer.length; return; } case TCPOption.Timestamp: { const optionTS = optionItem; const tsBuffer = Buffer.concat([ (0, NumberToBuffer_1.UInt8ToBuffer)(8), (0, NumberToBuffer_1.UInt8ToBuffer)(10), (0, NumberToBuffer_1.UInt32ToBuffer)(optionTS.tsval ? optionTS.tsval : 0), (0, NumberToBuffer_1.UInt32ToBuffer)(optionTS.tsecr ? optionTS.tsecr : 0) ]); this.writeBytes(optionOffset, tsBuffer); optionOffset += tsBuffer.length; return; } case TCPOption.User_Timeout: { const optionUTO = optionItem; const utoBuffer = Buffer.concat([ (0, NumberToBuffer_1.UInt8ToBuffer)(28), (0, NumberToBuffer_1.UInt8ToBuffer)(5), (0, NumberToBuffer_1.UInt16ToBuffer)(optionUTO.timeout ? optionUTO.timeout : 0), (0, NumberToBuffer_1.UInt8ToBuffer)(optionUTO.granularity ? optionUTO.granularity : 0) ]); this.writeBytes(optionOffset, utoBuffer); optionOffset += utoBuffer.length; return; } case TCPOption.TCP_Authentication_Option: { const optionTcpAo = optionItem; const kindBuffer = (0, NumberToBuffer_1.UInt8ToBuffer)(29); const dataBuffer = Buffer.from(optionTcpAo.data, 'hex'); const lengthBuffer = (0, NumberToBuffer_1.UInt8ToBuffer)(dataBuffer.length + 2); const tcpAoBuffer = Buffer.concat([kindBuffer, lengthBuffer, dataBuffer]); this.writeBytes(optionOffset, tcpAoBuffer); optionOffset += tcpAoBuffer.length; return; } default: { const defaultOptionItem = optionItem; const kind = defaultOptionItem.kind; const hexBuffer = Buffer.from(defaultOptionItem.data.toString(), 'hex'); const length = hexBuffer.length + 2; const defaultOptionBuffer = Buffer.concat([(0, NumberToBuffer_1.UInt8ToBuffer)(kind), (0, NumberToBuffer_1.UInt8ToBuffer)(length), hexBuffer]); this.writeBytes(optionOffset, defaultOptionBuffer); optionOffset += defaultOptionBuffer.length; } } }); if (this.length > 60) return this.recordError(this.instance.options.getPath(), 'Options too large'); const headerBitLength = this.length * 8; if (headerBitLength % 4) { //Add Padding this.writeBytes(this.length, Buffer.from([0x00])); } } } } }; this.id = 'tcp'; this.name = 'Transmission Control Protocol'; this.nickname = 'TCP'; } /** * Calculate TCP Checksum * @param tcpHeaderBuffer * @protected */ calculateTCPChecksum(tcpHeaderBuffer) { const tcpHeaderLength = tcpHeaderBuffer.length; const ipVersion = this.prevCodecModule.instance.version.getValue(); let pseudoHeaderBuffer = Buffer.from([]); const sourceIp = this.prevCodecModule.instance.sip.getValue(); const destinationIp = this.prevCodecModule.instance.dip.getValue(); if (ipVersion === 4) { //4 Bytes const sourceIPv4Buffer = Buffer.from(sourceIp.split('.').map((value) => parseInt(value))); const destinationIPv4Buffer = Buffer.from(destinationIp.split('.').map((value) => parseInt(value))); //IPv4 Pseudo header pseudoHeaderBuffer = Buffer.concat([ sourceIPv4Buffer, destinationIPv4Buffer, (0, NumberToBuffer_1.UInt8ToBuffer)(0), //Reserved field (0, NumberToBuffer_1.UInt8ToBuffer)(6), //Protocol type (TCP = 6) Buffer.from([(tcpHeaderLength >> 8) & 0xFF]), Buffer.from([tcpHeaderLength & 0xFF]) ]); } else if (ipVersion === 6) { //16 Bytes const sourceIPv6Buffer = (0, IPToBuffer_1.IPv6ToBuffer)(sourceIp); const destinationIPv6Buffer = (0, IPToBuffer_1.IPv6ToBuffer)(destinationIp); //IPv6 Pseudo header pseudoHeaderBuffer = Buffer.concat([ sourceIPv6Buffer, destinationIPv6Buffer, (0, NumberToBuffer_1.UInt8ToBuffer)(0), //Reserved field (0, NumberToBuffer_1.UInt8ToBuffer)(0), //Reserved field (0, NumberToBuffer_1.UInt8ToBuffer)(0), //Reserved field (0, NumberToBuffer_1.UInt8ToBuffer)(6), //Protocol type (TCP = 6) Buffer.from([(tcpHeaderLength >> 8) & 0xFF]), Buffer.from([tcpHeaderLength & 0xFF]) ]); } else { return 0; } const dataBuffer = Buffer.concat([pseudoHeaderBuffer, tcpHeaderBuffer]); const data = Uint8Array.from(dataBuffer); let sum = 0; for (let i = 0; i < data.length; i += 2) sum += (data[i] << 8) + (data[i + 1] || 0); while (sum >>> 16) sum = (sum & 0xFFFF) + (sum >>> 16); return (~sum) & 0xFFFF; } match() { if (!this.prevCodecModule) return false; if (this.prevCodecModule.instance.protocol.getValue() === 0x06) return true; return false; } } exports.TCP = TCP;