/** * Called when new UDP packet received. * @param string $pct * @return void */ public function onUdpPacket($pct) { $orig = $pct; $this->response = []; /*$id = */ Binary::getWord($pct); $bitmap = Binary::getBitmap(Binary::getByte($pct)) . Binary::getBitmap(Binary::getByte($pct)); //$qr = (int) $bitmap[0]; $opcode = bindec(substr($bitmap, 1, 4)); //$aa = (int) $bitmap[5]; //$tc = (int) $bitmap[6]; //$rd = (int) $bitmap[7]; //$ra = (int) $bitmap[8]; //$z = bindec(substr($bitmap, 9, 3)); //$rcode = bindec(substr($bitmap, 12)); $qdcount = Binary::getWord($pct); $ancount = Binary::getWord($pct); $nscount = Binary::getWord($pct); $arcount = Binary::getWord($pct); for ($i = 0; $i < $qdcount; ++$i) { $name = Binary::parseLabels($pct, $orig); $typeInt = Binary::getWord($pct); $type = isset(Pool::$type[$typeInt]) ? Pool::$type[$typeInt] : 'UNK(' . $typeInt . ')'; $classInt = Binary::getWord($pct); $class = isset(Pool::$class[$classInt]) ? Pool::$class[$classInt] : 'UNK(' . $classInt . ')'; if (!isset($this->response[$type])) { $this->response[$type] = []; } $record = ['name' => $name, 'type' => $type, 'class' => $class]; $this->response['query'][] = $record; } $getResRecord = function (&$pct) use($orig) { $name = Binary::parseLabels($pct, $orig); $typeInt = Binary::getWord($pct); $type = isset(Pool::$type[$typeInt]) ? Pool::$type[$typeInt] : 'UNK(' . $typeInt . ')'; $classInt = Binary::getWord($pct); $class = isset(Pool::$class[$classInt]) ? Pool::$class[$classInt] : 'UNK(' . $classInt . ')'; $ttl = Binary::getDWord($pct); $length = Binary::getWord($pct); $data = binarySubstr($pct, 0, $length); $pct = binarySubstr($pct, $length); $record = ['name' => $name, 'type' => $type, 'class' => $class, 'ttl' => $ttl]; if ($type === 'A') { if ($data === "") { $record['ip'] = false; $record['ttl'] = 5; } else { $record['ip'] = inet_ntop($data); } } elseif ($type === 'NS') { $record['ns'] = Binary::parseLabels($data); } elseif ($type === 'CNAME') { $record['cname'] = Binary::parseLabels($data, $orig); } return $record; }; for ($i = 0; $i < $ancount; ++$i) { $record = $getResRecord($pct); if (!isset($this->response[$record['type']])) { $this->response[$record['type']] = []; } $this->response[$record['type']][] = $record; } for ($i = 0; $i < $nscount; ++$i) { $record = $getResRecord($pct); if (!isset($this->response[$record['type']])) { $this->response[$record['type']] = []; } $this->response[$record['type']][] = $record; } for ($i = 0; $i < $arcount; ++$i) { $record = $getResRecord($pct); if (!isset($this->response[$record['type']])) { $this->response[$record['type']] = []; } $this->response[$record['type']][] = $record; } $this->onResponse->executeOne($this->response); if (!$this->keepalive) { $this->finish(); return; } else { $this->checkFree(); } }
/** * Called when new UDP packet received. * @param string $pct * @return void */ public function onUdpPacket($pct) { if (mb_orig_strlen($pct) < 10) { return; } $orig = $pct; $this->response = []; Binary::getWord($pct); // ID $bitmap = Binary::getBitmap(Binary::getByte($pct)) . Binary::getBitmap(Binary::getByte($pct)); //$qr = (int) $bitmap[0]; $opcode = bindec(substr($bitmap, 1, 4)); //$aa = (int) $bitmap[5]; //$tc = (int) $bitmap[6]; //$rd = (int) $bitmap[7]; //$ra = (int) $bitmap[8]; //$z = bindec(substr($bitmap, 9, 3)); $rcode = bindec(mb_orig_substr($bitmap, 12)); $this->response['status'] = ['rcode' => $rcode, 'msg' => $this->getMessageByRcode($rcode)]; $qdcount = Binary::getWord($pct); $ancount = Binary::getWord($pct); $nscount = Binary::getWord($pct); $arcount = Binary::getWord($pct); for ($i = 0; $i < $qdcount; ++$i) { $name = Binary::parseLabels($pct, $orig); $typeInt = Binary::getWord($pct); $type = isset(Pool::$type[$typeInt]) ? Pool::$type[$typeInt] : 'UNK(' . $typeInt . ')'; $classInt = Binary::getWord($pct); $class = isset(Pool::$class[$classInt]) ? Pool::$class[$classInt] : 'UNK(' . $classInt . ')'; if (!isset($this->response[$type])) { $this->response[$type] = []; } $record = ['name' => $name, 'type' => $type, 'class' => $class]; $this->response['query'][] = $record; } $getResRecord = function (&$pct) use($orig) { $name = Binary::parseLabels($pct, $orig); $typeInt = Binary::getWord($pct); $type = isset(Pool::$type[$typeInt]) ? Pool::$type[$typeInt] : 'UNK(' . $typeInt . ')'; $classInt = Binary::getWord($pct); $class = isset(Pool::$class[$classInt]) ? Pool::$class[$classInt] : 'UNK(' . $classInt . ')'; $ttl = Binary::getDWord($pct); $length = Binary::getWord($pct); $data = mb_orig_substr($pct, 0, $length); $pct = mb_orig_substr($pct, $length); $record = ['name' => $name, 'type' => $type, 'class' => $class, 'ttl' => $ttl]; if ($type === 'A' || $type === 'AAAA') { if ($data === "") { $record['ip'] = false; $record['ttl'] = 5; } else { $record['ip'] = inet_ntop($data); } } elseif ($type === 'NS') { $record['ns'] = Binary::parseLabels($data, $orig); } elseif ($type === 'CNAME') { $record['cname'] = Binary::parseLabels($data, $orig); } elseif ($type === 'SOA') { $record['mname'] = Binary::parseLabels($data, $orig); $record['rname'] = Binary::parseLabels($data, $orig); $record['serial'] = Binary::getDWord($data); $record['refresh'] = Binary::getDWord($data); $record['retry'] = Binary::getDWord($data); $record['expire'] = Binary::getDWord($data); $record['nx'] = Binary::getDWord($data); } elseif ($type === 'MX') { $record['preference'] = Binary::getWord($data); $record['exchange'] = Binary::parseLabels($data, $orig); } elseif ($type === 'TXT') { $record['text'] = ''; $lastLength = -1; while (($length = mb_orig_strlen($data)) > 0 && $length !== $lastLength) { $record['text'] .= Binary::parseLabels($data, $orig); $lastLength = $length; } } elseif ($type === 'SRV') { $record['priority'] = Binary::getWord($data); $record['weight'] = Binary::getWord($data); $record['port'] = Binary::getWord($data); $record['target'] = Binary::parseLabels($data, $orig); } return $record; }; for ($i = 0; $i < $ancount; ++$i) { $record = $getResRecord($pct); if (!isset($this->response[$record['type']])) { $this->response[$record['type']] = []; } $this->response[$record['type']][] = $record; } for ($i = 0; $i < $nscount; ++$i) { $record = $getResRecord($pct); if (!isset($this->response[$record['type']])) { $this->response[$record['type']] = []; } $this->response[$record['type']][] = $record; } for ($i = 0; $i < $arcount; ++$i) { $record = $getResRecord($pct); if (!isset($this->response[$record['type']])) { $this->response[$record['type']] = []; } $this->response[$record['type']][] = $record; } $this->onResponse->executeOne($this->response); if (!$this->keepalive) { $this->finish(); return; } else { $this->checkFree(); } }