1717use ArrayAccess \DnsRecord \Packet \RequestData ;
1818use ArrayAccess \DnsRecord \Packet \Response ;
1919use ArrayAccess \DnsRecord \ResourceRecord \Definitions \QClass \IN ;
20+ use ArrayAccess \DnsRecord \ResourceRecord \RRTypes \OPT ;
2021use ArrayAccess \DnsRecord \Traits \PacketSenderTrait ;
2122use ArrayAccess \DnsRecord \Utils \Lookup ;
2223use Throwable ;
@@ -27,12 +28,72 @@ class Resolver
2728{
2829 use PacketSenderTrait;
2930
31+ protected bool $ cdFlag = false ;
32+
33+ protected bool $ adFlag = true ;
34+
35+ /**
36+ * request DNSSEC values, by setting the DO flag to 1; this actually makes
37+ * the resolver add an OPT RR to the additional section, and sets the DO flag
38+ * in this RR to 1
39+ */
40+ protected bool $ dnsSec = false ;
41+
42+ /**
43+ * if we should set the recursion desired bit to 1 or 0.
44+ *
45+ * by default, this is set to true, the DNS server to perform a recursive
46+ * request. If set to false, the RD bit will be set to 0, and the server will
47+ * not perform recursion on the request.
48+ */
49+ public bool $ recurse = true ;
50+
3051 public function __construct (
3152 protected ?DnsServerStorage $ dnsServerStorage = null ,
3253 protected ?CacheStorageInterface $ cache = null
3354 ) {
3455 }
3556
57+ public function isCdFlag (): bool
58+ {
59+ return $ this ->cdFlag ;
60+ }
61+
62+ public function setCdFlag (bool $ cdFlag ): void
63+ {
64+ $ this ->cdFlag = $ cdFlag ;
65+ }
66+
67+ public function isAdFlag (): bool
68+ {
69+ return $ this ->adFlag ;
70+ }
71+
72+ public function setAdFlag (bool $ adFlag ): void
73+ {
74+ $ this ->adFlag = $ adFlag ;
75+ }
76+
77+ public function isDnsSec (): bool
78+ {
79+ return $ this ->dnsSec ;
80+ }
81+
82+ public function setDnsSec (bool $ dnsSec ): void
83+ {
84+ $ this ->dnsSec = $ dnsSec ;
85+ }
86+
87+ public function isRecurse (): bool
88+ {
89+ return $ this ->recurse ;
90+ }
91+
92+ public function setRecurse (bool $ recurse ): void
93+ {
94+ $ this ->recurse = $ recurse ;
95+ }
96+
3697 public function getCache (): CacheStorageInterface
3798 {
3899 if (!isset ($ this ->cache )) {
@@ -64,18 +125,37 @@ public function setDnsServerStorage(DnsServerStorage $dnsServerStorage): void
64125 * @param string $name
65126 * @param string $type
66127 * @param string $class
128+ * @param ?bool $adFlag
129+ * @param ?bool $cdFlag
130+ * @param ?bool $dnsSec
131+ * @param ?bool $recurse
67132 * @param string ...$server
68133 * @return PacketRequestDataInterface
69134 */
70- protected function createQueryOpcode (
135+ public function createQueryOpcode (
71136 int |string |ResourceRecordOpcodeInterface $ opcode ,
72137 string $ name ,
73138 string $ type = 'A ' ,
74- string $ class = 'IN ' ,
139+ string $ class = IN ::NAME ,
140+ ?bool $ adFlag = null ,
141+ ?bool $ cdFlag = null ,
142+ ?bool $ dnsSec = null ,
143+ ?bool $ recurse = null ,
75144 string ...$ server
76145 ) : PacketRequestDataInterface {
146+ $ adFlag ??= $ this ->isAdFlag ();
147+ $ cdFlag ??= $ this ->isCdFlag ();
148+ $ dnsSec ??= $ this ->isDnsSec ();
149+ $ recurse ??= $ this ->isRecurse ();
150+
77151 // IN as default
78- $ class = trim ($ class ?:'IN ' )?:'IN ' ;
152+ $ class = trim ($ class ?:IN ::NAME )?:IN ::NAME ;
153+ $ class = Lookup::resourceClass ($ class );
154+ $ type = Lookup::resourceType ($ type );
155+ $ isOpt = $ type ->getName () === OPT ::TYPE ;
156+ if ($ isOpt ) { // if is OPT fallback to A
157+ $ type = 'A ' ;
158+ }
79159 $ question = new Question ($ name , $ type , $ class );
80160 $ dns = $ this ->getDnsServerStorage ();
81161 if (!empty ($ server )) {
@@ -85,11 +165,18 @@ protected function createQueryOpcode(
85165 }
86166 $ dns = new DnsServerStorage (...$ ss );
87167 }
88- return new RequestData (
89- Header::createQueryHeader ($ opcode ),
168+ $ requestData = new RequestData (
169+ Header::createQueryHeader ($ opcode, null , $ adFlag , $ cdFlag , $ recurse ),
90170 $ dns ,
91- $ question,
171+ $ question
92172 );
173+
174+ if ($ isOpt || $ dnsSec ) {
175+ $ requestData
176+ ->getAdditionalRecords ()
177+ ->add (OPT ::create ($ question ->getType ()->getValue ()));
178+ }
179+ return $ requestData ;
93180 }
94181
95182 /**
@@ -110,6 +197,8 @@ public function query(
110197 $ name ,
111198 $ type ,
112199 $ class ,
200+ $ this ->isAdFlag (),
201+ $ this ->isCdFlag (),
113202 ...$ server
114203 );
115204 }
@@ -132,6 +221,8 @@ public function iQuery(
132221 $ name ,
133222 $ type ,
134223 $ class ,
224+ $ this ->isAdFlag (),
225+ $ this ->isCdFlag (),
135226 ...$ server
136227 );
137228 }
@@ -154,7 +245,11 @@ public function lookups(
154245 }
155246
156247 $ requests = [];
157- $ header = Header::createQueryHeader ();
248+ $ header = Header::createQueryHeader (
249+ adFlag: $ this ->adFlag ,
250+ cdFlag: $ this ->cdFlag ,
251+ rdFlag: $ this ->recurse
252+ );
158253 $ dns = $ this ->getDnsServerStorage ();
159254 foreach ($ types as $ key => $ type ) {
160255 $ requests [$ key ] = new RequestData ($ header , $ dns , new Question (
0 commit comments