/** * Parse Interface Statistics Block. * @param string $raw Binary string * @param int $currentPosition Current position in file * @return array * @throws Exception */ public function parse($raw, &$currentPosition) { $blockStart = PcapngParser::bin2hexEndian(substr($raw, $currentPosition, 4)); if ($blockStart !== static::BYTE_TYPE) { throw new Exception('Unknown format of Interface Statistics Block'); } // Block Total Length $totalLength = PcapngParser::rawToDecimal(substr($raw, $currentPosition + 4, 4)); $block['length'] = $totalLength; $interfaceId = PcapngParser::rawToDecimal(substr($raw, $currentPosition + 8, 4)); $block['interface_id'] = $interfaceId; $timestampHigh = PcapngParser::rawToFloat(substr($raw, $currentPosition + 12, 4)); //todo wrong representation $block['timestamp_high'] = $timestampHigh; $timestampLow = PcapngParser::rawToFloat(substr($raw, $currentPosition + 16, 4)); //todo wrong representation $block['timestamp_low'] = $timestampLow; $currentPosition += 20; $this->parseOptions($raw, $currentPosition); $lengthEnd = PcapngParser::rawToDecimal(substr($raw, $currentPosition, 4)); if ($lengthEnd !== $totalLength) { throw new Exception('Unknown format'); } $currentPosition += 4; }
/** * Parse XX Block. * @param string $raw Binary string * @param int $currentPosition Current position in file * @return array * @throws Exception */ public function parse($raw, &$currentPosition) { $blockStart = PcapngParser::bin2hexEndian(substr($raw, $currentPosition, 4)); if ($blockStart !== static::BYTE_TYPE) { throw new Exception('Unknown format of Interface Description Block'); } // Block Total Length $totalLength = PcapngParser::rawToDecimal(substr($raw, $currentPosition + 4, 4)); $block['length'] = $totalLength; //LinkType $linkType = PcapngParser::rawToDecimal(substr($raw, $currentPosition + 8, 2)); $this->linkType = $linkType; $reserved = PcapngParser::bin2hexEndian(substr($raw, $currentPosition + 10, 2)); if ($reserved !== '0000') { trigger_error('Reserved field in Interface Description Block must by 0', E_USER_NOTICE); } $snapLen = PcapngParser::rawToDecimal(substr($raw, $currentPosition + 12, 4)); $block['snap_length'] = $snapLen; $currentPosition += 16; $this->options = $this->parseOptions($raw, $currentPosition); $lengthEnd = PcapngParser::rawToDecimal(substr($raw, $currentPosition, 4)); if ($lengthEnd !== $totalLength) { throw new Exception('Unknown format'); } $currentPosition += 4; }
/** * Parse Options. * @param string $raw Binary string * @param int $currentPosition * @return array * @throws Exception */ protected function parseOptions($raw, &$currentPosition) { //Option Code while ($optionCode = substr($raw, $currentPosition, 2) !== chr(0) . chr(0)) { $optionCode = PcapngParser::rawToDecimal($optionCode); //Option Length $optionLength = PcapngParser::rawToDecimal(substr($raw, $currentPosition + 2, 2)); if (array_key_exists($optionCode, $this->optionType)) { //PEN = Private Enterprise Number if ($this->optionType[$optionCode]['name'] === 'opt_custom') { $penRaw = substr($raw, $currentPosition + 4, 4); //todo ?? $currentPosition += 4; } } else { if (array_key_exists($optionCode, $this->optionsTypeCustom)) { } else { throw new Exception('Unknow type of option'); } } //Option Value $this->options[] = array('code' => $optionCode, 'value' => substr($raw, $currentPosition + 4, $optionLength)); $currentPosition += 4 + ceil($optionLength / 4) * 4; //4 = Option code + Option length } $currentPosition += 4; //closing Option code + closing Option length return $this->options; }
/** * Parse Section Header Block (SHB). * @param string $raw Binary string * @param int $currentPosition Current position in file * @return array * @throws Exception */ public function parse($raw, &$currentPosition) { // Section Header Block - Block Type $blockStart = PcapngParser::bin2hexEndian(substr($raw, $currentPosition, 4)); if ($blockStart !== static::BYTE_TYPE) { throw new Exception('Unknown format of Section Header Block'); } // Section Header Block - Block Total Length $shbLength = PcapngParser::rawToDecimal(substr($raw, $currentPosition + 4, 4)); // Section Header Block - Byte-Order Magic $byteOrderMagic = substr($raw, $currentPosition + 8, 4); if (bin2hex($byteOrderMagic) === static::BYTE_ORDER_MAGIC) { $this->endian = 0; } else { if (PcapngParser::bin2hexEndian($byteOrderMagic) === static::BYTE_ORDER_MAGIC) { $this->endian = 1; } else { throw new Exception('Unknown format'); } } // Section Header Block - Major Version $this->majorVersion = PcapngParser::rawToDecimal(substr($raw, $currentPosition + 12, 2)); // Section Header Block - Minor Version $this->minorVersion = PcapngParser::rawToDecimal(substr($raw, $currentPosition + 14, 2)); // Section Header Block - Section Length //https://en.wikipedia.org/wiki/Signed_number_representations $sectionLength = substr($raw, $currentPosition + 16, 8); $this->sectionLength = bin2hex($sectionLength); //todo make numeric // Section Header Block - Options $currentPosition += 16 + 8; $this->parseOptions($raw, $currentPosition); $shbLengthEnd = PcapngParser::rawToDecimal(substr($raw, $currentPosition, 4)); if ($shbLengthEnd !== $shbLength) { throw new Exception('Unknown format'); } $currentPosition += 4; //closing Block Total Length }