From d44e38036c0ccef2dfb2fdc9edcae97d12d7f490 Mon Sep 17 00:00:00 2001 From: ArrayIterator Date: Sat, 11 Nov 2023 07:58:56 +0700 Subject: [PATCH] add change for recurse, cd & ad --- src/Resolver.php | 109 ++++++++++++++++++++++++++++++++++++++--- tests/ResolverTest.php | 15 ++++++ 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/src/Resolver.php b/src/Resolver.php index b9f0f5c..ba45cfb 100644 --- a/src/Resolver.php +++ b/src/Resolver.php @@ -17,6 +17,7 @@ use ArrayAccess\DnsRecord\Packet\RequestData; use ArrayAccess\DnsRecord\Packet\Response; use ArrayAccess\DnsRecord\ResourceRecord\Definitions\QClass\IN; +use ArrayAccess\DnsRecord\ResourceRecord\RRTypes\OPT; use ArrayAccess\DnsRecord\Traits\PacketSenderTrait; use ArrayAccess\DnsRecord\Utils\Lookup; use Throwable; @@ -27,12 +28,72 @@ class Resolver { use PacketSenderTrait; + protected bool $cdFlag = false; + + protected bool $adFlag = true; + + /** + * request DNSSEC values, by setting the DO flag to 1; this actually makes + * the resolver add an OPT RR to the additional section, and sets the DO flag + * in this RR to 1 + */ + protected bool $dnsSec = false; + + /** + * if we should set the recursion desired bit to 1 or 0. + * + * by default, this is set to true, the DNS server to perform a recursive + * request. If set to false, the RD bit will be set to 0, and the server will + * not perform recursion on the request. + */ + public bool $recurse = true; + public function __construct( protected ?DnsServerStorage $dnsServerStorage = null, protected ?CacheStorageInterface $cache = null ) { } + public function isCdFlag(): bool + { + return $this->cdFlag; + } + + public function setCdFlag(bool $cdFlag): void + { + $this->cdFlag = $cdFlag; + } + + public function isAdFlag(): bool + { + return $this->adFlag; + } + + public function setAdFlag(bool $adFlag): void + { + $this->adFlag = $adFlag; + } + + public function isDnsSec(): bool + { + return $this->dnsSec; + } + + public function setDnsSec(bool $dnsSec): void + { + $this->dnsSec = $dnsSec; + } + + public function isRecurse(): bool + { + return $this->recurse; + } + + public function setRecurse(bool $recurse): void + { + $this->recurse = $recurse; + } + public function getCache(): CacheStorageInterface { if (!isset($this->cache)) { @@ -64,18 +125,37 @@ public function setDnsServerStorage(DnsServerStorage $dnsServerStorage): void * @param string $name * @param string $type * @param string $class + * @param ?bool $adFlag + * @param ?bool $cdFlag + * @param ?bool $dnsSec + * @param ?bool $recurse * @param string ...$server * @return PacketRequestDataInterface */ - protected function createQueryOpcode( + public function createQueryOpcode( int|string|ResourceRecordOpcodeInterface $opcode, string $name, string $type = 'A', - string $class = 'IN', + string $class = IN::NAME, + ?bool $adFlag = null, + ?bool $cdFlag = null, + ?bool $dnsSec = null, + ?bool $recurse = null, string ...$server ) : PacketRequestDataInterface { + $adFlag ??= $this->isAdFlag(); + $cdFlag ??= $this->isCdFlag(); + $dnsSec ??= $this->isDnsSec(); + $recurse ??= $this->isRecurse(); + // IN as default - $class = trim($class?:'IN')?:'IN'; + $class = trim($class?:IN::NAME)?:IN::NAME; + $class = Lookup::resourceClass($class); + $type = Lookup::resourceType($type); + $isOpt = $type->getName() === OPT::TYPE; + if ($isOpt) { // if is OPT fallback to A + $type = 'A'; + } $question = new Question($name, $type, $class); $dns = $this->getDnsServerStorage(); if (!empty($server)) { @@ -85,11 +165,18 @@ protected function createQueryOpcode( } $dns = new DnsServerStorage(...$ss); } - return new RequestData( - Header::createQueryHeader($opcode), + $requestData = new RequestData( + Header::createQueryHeader($opcode, null, $adFlag, $cdFlag, $recurse), $dns, - $question, + $question ); + + if ($isOpt || $dnsSec) { + $requestData + ->getAdditionalRecords() + ->add(OPT::create($question->getType()->getValue())); + } + return $requestData; } /** @@ -110,6 +197,8 @@ public function query( $name, $type, $class, + $this->isAdFlag(), + $this->isCdFlag(), ...$server ); } @@ -132,6 +221,8 @@ public function iQuery( $name, $type, $class, + $this->isAdFlag(), + $this->isCdFlag(), ...$server ); } @@ -154,7 +245,11 @@ public function lookups( } $requests = []; - $header = Header::createQueryHeader(); + $header = Header::createQueryHeader( + adFlag: $this->adFlag, + cdFlag: $this->cdFlag, + rdFlag: $this->recurse + ); $dns = $this->getDnsServerStorage(); foreach ($types as $key => $type) { $requests[$key] = new RequestData($header, $dns, new Question( diff --git a/tests/ResolverTest.php b/tests/ResolverTest.php index 50e08b0..ee8b628 100644 --- a/tests/ResolverTest.php +++ b/tests/ResolverTest.php @@ -17,6 +17,7 @@ use ArrayAccess\DnsRecord\ResourceRecord\Definitions\Opcode\Query; use ArrayAccess\DnsRecord\ResourceRecord\Definitions\QClass\IN; use ArrayAccess\DnsRecord\ResourceRecord\RRTypes\A; +use ArrayAccess\DnsRecord\ResourceRecord\RRTypes\OPT; use PHPUnit\Framework\TestCase; use Throwable; use function sprintf; @@ -121,6 +122,7 @@ public function testGetCache() ) ); } + public function testQuery() { $resolver = new Resolver(); @@ -143,6 +145,19 @@ public function testQuery() Query::class ) ); + // default use dnssec + $this->assertNull( + $query->getAdditionalRecords()->getFilteredType('OPT', true), + 'dnssec disable by default' + ); + // set dns sec to true + $resolver->setDnsSec(true); + $query = $resolver->query('example.com'); + $this->assertInstanceOf( + OPT::class, + $query->getAdditionalRecords()->getFilteredType('OPT', true), + 'Enable dnssec and additional question contain OPT' + ); } public function testIQuery()