UNPKG

netkitty

Version:
152 lines (140 loc) 6.01 kB
import {ProtocolJSONSchema} from '../../schema/ProtocolJSONSchema' import {BaseHeader} from '../abstracts/BaseHeader' import {BufferToUInt16, BufferToUInt8} from '../../helper/BufferToNumber' import {UInt16ToBuffer, UInt8ToBuffer} from '../../helper/NumberToBuffer' import {StringContentEncodingEnum} from '../lib/StringContentEncodingEnum' import {BufferToHex} from '../../helper/BufferToHex' export class ICMP extends BaseHeader { /** * Calculate ICMPv4 checksum * @protected */ protected calculateIcmpChecksum(): number { const icmpHeader: Buffer = Buffer.concat([ UInt8ToBuffer(this.instance.type.getValue(0)), UInt8ToBuffer(this.instance.code.getValue(0)), UInt16ToBuffer(this.instance.checksum.getValue(0)), UInt16ToBuffer(this.instance.ident.getValue(0)), UInt16ToBuffer(this.instance.seq.getValue(0)), Buffer.from(this.instance.message.getValue(''), 'hex') ]) const paddedBuffer: Buffer = icmpHeader.length % 2 === 1 ? Buffer.concat([ icmpHeader, UInt8ToBuffer(0) ]) : icmpHeader // 4. 计算 checksum let checksum = 0 for (let i = 0; i < paddedBuffer.length; i += 2) { const word = (paddedBuffer[i] << 8) | (paddedBuffer[i + 1] || 0) checksum += word // 处理溢出 if (checksum > 0xFFFF) { checksum = (checksum & 0xFFFF) + 1 } } // 取反得到最终 checksum return (~checksum) & 0xFFFF } public SCHEMA: ProtocolJSONSchema = { type: 'object', properties: { type: { type: 'integer', label: 'Type', minimum: 0, maximum: 255, decode: (): void => { this.instance.type.setValue(BufferToUInt8(this.readBytes(0, 1))) }, encode: (): void => { const type: number = this.instance.type.getValue(0, (nodePath: string): void => this.recordError(nodePath, 'Not Found')) this.instance.type.setValue(type) this.writeBytes(0, UInt8ToBuffer(type)) } }, code: { type: 'integer', label: 'Code', minimum: 0, maximum: 255, decode: (): void => { this.instance.code.setValue(BufferToUInt8(this.readBytes(1, 1))) }, encode: (): void => { const code: number = this.instance.code.getValue(0, (nodePath: string): void => this.recordError(nodePath, 'Not Found')) this.instance.code.setValue(code) this.writeBytes(1, UInt8ToBuffer(code)) } }, checksum: { type: 'integer', label: 'Checksum', minimum: 0, maximum: 65535, decode: (): void => { this.instance.checksum.setValue(BufferToUInt16(this.readBytes(2, 2))) }, encode: (): void => { let checksum: number = this.instance.checksum.getValue(0) this.instance.checksum.setValue(checksum) this.writeBytes(2, UInt16ToBuffer(checksum)) if (!checksum) { checksum = this.calculateIcmpChecksum() this.instance.checksum.setValue(checksum) this.writeBytes(2, UInt16ToBuffer(checksum)) } } }, ident: { type: 'number', label: 'Identifier (BE)', minimum: 0, maximum: 65535, decode: (): void => { this.instance.ident.setValue(BufferToUInt16(this.readBytes(4, 2))) }, encode: (): void => { const ident: number = this.instance.ident.getValue(0, (nodePath: string): void => this.recordError(nodePath, 'Not Found')) this.instance.ident.setValue(ident) this.writeBytes(4, UInt16ToBuffer(ident)) } }, seq: { type: 'number', label: 'Sequence Number (BE)', minimum: 0, maximum: 65535, decode: (): void => { this.instance.seq.setValue(BufferToUInt16(this.readBytes(6, 2))) }, encode: (): void => { const seq: number = this.instance.seq.getValue(0, (nodePath: string): void => this.recordError(nodePath, 'Not Found')) this.instance.seq.setValue(seq) this.writeBytes(6, UInt16ToBuffer(seq)) } }, message: { type: 'string', label: 'Message Body', contentEncoding: StringContentEncodingEnum.HEX, decode: (): void => { const messageDataLength: number = this.packet.length - this.startPos - 8 this.instance.message.setValue(BufferToHex(this.readBytes(8, messageDataLength))) }, encode: (): void => { const messageHex: string = this.instance.message.getValue('') this.instance.message.setValue(messageHex) this.writeBytes(8, Buffer.from(messageHex, 'hex')) } } } } public id: string = 'icmp' public name: string = 'Internet Control Message Protocol' public nickname: string = 'ICMP' public match(): boolean { if (!this.prevCodecModule) return false return this.prevCodecModule.instance.protocol.getValue() === 0x01 } }