-
Notifications
You must be signed in to change notification settings - Fork 0
Fix: return name assigned to the answer if different #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
73e90c0
11dcca4
329ff02
4ca4c96
69efa06
2ed8db6
4037778
78e5a1f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -291,23 +291,39 @@ public function start(): void | |
|
|
||
| // Add answers section | ||
| foreach ($answers as $answer) { | ||
| $response .= chr(192) . chr(12); // 192 indicates this is pointer, 12 is offset to question. | ||
| // Pack the answer's type, not the question type | ||
| // Encode the domain name from the answer record | ||
| // For SOA records, this ensures we use the apex domain name | ||
| // even when the question was for a subdomain | ||
| $answerDomain = $answer->getName(); | ||
|
|
||
| // Check if we can use compression (domain names match) | ||
| if ($answerDomain === $domain) { | ||
| // Use pointer compression - points back to question domain | ||
| $response .= chr(192) . chr(12); | ||
| } else { | ||
| // Encode the full domain name since it's different from question | ||
| $response .= $this->encodeDomainName($answerDomain); | ||
| } | ||
|
|
||
| // Pack the answer's type and class | ||
| $response .= pack('nn', $answer->getType(), $classByte); | ||
|
Comment on lines
+294
to
315
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 🧩 Analysis chainVerify functionality with CNAME chains and NS records. While the implementation logic is sound, please verify that the changes work correctly for common cases where answer domains differ from the question:
Run the following script to check the test coverage for these scenarios: 🏁 Script executed: #!/bin/bash
# Description: Verify test coverage for CNAME, NS records and domain name encoding
# Check for existing tests of CNAME chains
echo "=== CNAME chain tests ==="
rg -n -A5 -B2 --type=php 'CNAME' tests/
echo -e "\n=== NS record tests ==="
rg -n -A5 -B2 --type=php '\bNS\b' tests/
echo -e "\n=== Domain name encoding tests ==="
rg -n -A5 -B2 --type=php 'encodeDomainName' tests/Length of output: 9394 Add tests for pointer compression and mixed answer sets
🤖 Prompt for AI Agents |
||
|
|
||
| /** | ||
| * @var string $type | ||
| */ | ||
| $type = $answer->getTypeName(); | ||
|
|
||
| // For record types that encode data only (not domain names in data) | ||
| $response .= match ($type) { | ||
| 'A' => $this->encodeIP($answer->getRdata(), $answer->getTTL()), | ||
| 'AAAA' => $this->encodeIPv6($answer->getRdata(), $answer->getTTL()), | ||
| 'CNAME' => $this->encodeDomain($answer->getRdata(), $answer->getTTL()), | ||
| 'NS' => $this->encodeDomain($answer->getRdata(), $answer->getTTL()), | ||
| 'SOA' => $this->encodeSOA($answer->getRdata(), $answer->getTTL()), | ||
| 'TXT' => $this->encodeText($answer->getRdata(), $answer->getTTL()), | ||
| 'CAA' => $this->encodeCAA($answer->getRdata(), $answer->getTTL()), | ||
| 'MX' => $this->encodeMx($answer->getRdata(), $answer->getTTL(), $answer->getPriority() ?? 0), | ||
| 'SRV' => $this->encodeSrv($answer->getRdata(), $answer->getTTL(), $answer->getPriority() ?? 0, $answer->getWeight() ?? 0, $answer->getPort() ?? 0), | ||
| // For CNAME and NS, we need to encode just the TTL, length, and target domain | ||
| 'CNAME', 'NS' => pack('Nn', $answer->getTTL(), strlen($this->encodeDomainName($answer->getName()))) . $this->encodeDomainName($answer->getName()), | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| default => '' | ||
| }; | ||
| } | ||
|
|
@@ -338,6 +354,37 @@ public function start(): void | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Encode just the domain name part (without TTL and length prefix) | ||
| * Used for domain names in answer sections | ||
| * | ||
| * @param string $domain | ||
| * @return string | ||
| */ | ||
|
Comment on lines
+360
to
+366
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Orphaned documentation comment. This doc comment has no corresponding method implementation. The method declaration and body are missing, though line 367 begins a different doc comment for the This appears to be an incomplete implementation of the This is addressed by the diff in the previous review comment, which adds the complete 🤖 Prompt for AI Agents |
||
| protected function encodeDomainName(string $domain): string | ||
| { | ||
| $labels = explode('.', rtrim($domain, '.')); | ||
| $result = ''; | ||
| $totalLength = 0; | ||
| foreach ($labels as $label) { | ||
| $labelLength = strlen($label); | ||
| if ($labelLength === 0) { | ||
| throw new \Exception("Empty label in domain: '{$domain}'"); | ||
| } | ||
| if ($labelLength > self::MAX_LABEL_LEN) { | ||
| throw new \Exception("Label too long in domain: {$label}"); | ||
| } | ||
| $result .= chr($labelLength) . $label; | ||
| $totalLength += 1 + $labelLength; | ||
| } | ||
| $result .= chr(0); | ||
| $totalLength += 1; | ||
| if ($totalLength > self::MAX_DOMAIN_NAME_LEN) { | ||
| throw new \Exception("Encoded domain name too long: {$domain}"); | ||
| } | ||
| return $result; | ||
| } | ||
|
|
||
| /** | ||
| * Resolve domain name to IP by record type | ||
| * | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extend logic to all record types and use a helper method.
The condition restricts this behavior to SOA records only, but the PR objectives state "Response uses the DNS name from the answer if it's different than the question" without limiting to SOA. Records like CNAME, NS, and others can also have answer domains that differ from the question domain.
Additionally, the inline domain encoding (lines 300-308) duplicates logic already present in the
encodeDomainmethod. According to the AI summary, a new protected methodencodeDomainName(string $domain): stringwas supposed to be introduced to handle domain encoding without TTL/length prefix, but it's missing from this file.Apply this diff to generalize the logic and extract the helper method:
Then update the answer encoding logic to use the helper and remove the SOA restriction:
$answerDomain = $answer->getName(); $type = $answer->getTypeName(); - // For SOA records, check if we need to encode a different domain name - if ($type === 'SOA' && $answerDomain !== $domain) { - // Encode the full domain name since it's different from question (apex vs subdomain) - $labels = explode('.', rtrim($answerDomain, '.')); - foreach ($labels as $label) { - $labelLength = strlen($label); - if ($labelLength > self::MAX_LABEL_LEN) { - throw new \Exception("Label too long in SOA domain: {$label}"); - } - $response .= chr($labelLength) . $label; - } - $response .= chr(0); // End of domain name + // Check if we need to encode a different domain name + if ($answerDomain !== $domain) { + // Encode the full domain name since it's different from question + $response .= $this->encodeDomainName($answerDomain); } else { // Use compression pointer for all other cases $response .= chr(192) . chr(12); // 192 indicates this is pointer, 12 is offset to question. }🤖 Prompt for AI Agents