Skip to content

Commit c38bbdf

Browse files
committed
[Dns] Correctly resolve CNAME aliases
1 parent 518e12e commit c38bbdf

1 file changed

Lines changed: 57 additions & 16 deletions

File tree

Resolver/Resolver.php

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,75 @@ public function resolve($domain)
2626

2727
return $this->executor
2828
->query($this->nameserver, $query)
29-
->then(function (Message $response) use ($that) {
30-
return $that->extractAddress($response, Message::TYPE_A);
29+
->then(function (Message $response) use ($that, $query) {
30+
return $that->extractAddress($query, $response);
3131
});
3232
}
3333

34-
public function extractAddress(Message $response, $type)
34+
public function extractAddress(Query $query, Message $response)
3535
{
36-
$answer = $this->pickRandomAnswerOfType($response, $type);
37-
$address = $answer->data;
36+
$answers = $response->answers;
37+
38+
$addresses = $this->resolveAliases($answers, $query->name);
39+
40+
if (0 === count($addresses)) {
41+
$message = 'DNS Request did not return valid answer.';
42+
throw new RecordNotFoundException($message);
43+
}
44+
45+
$address = $addresses[array_rand($addresses)];
3846
return $address;
3947
}
4048

41-
public function pickRandomAnswerOfType(Message $response, $type)
49+
public function resolveAliases(array $answers, $name)
4250
{
43-
// TODO: filter by name to make sure domain matches
44-
// TODO: resolve CNAME aliases
51+
$named = $this->filterByName($answers, $name);
52+
$aRecords = $this->filterByType($named, Message::TYPE_A);
53+
$cnameRecords = $this->filterByType($named, Message::TYPE_CNAME);
4554

46-
$filteredAnswers = array_filter($response->answers, function ($answer) use ($type) {
47-
return $type === $answer->type;
48-
});
55+
if ($aRecords) {
56+
return $this->mapRecordData($aRecords);
57+
}
4958

50-
if (0 === count($filteredAnswers)) {
51-
$message = sprintf('DNS Request did not return valid answer. Received answers: %s', json_encode($response->answers));
52-
throw new RecordNotFoundException($message);
59+
if ($cnameRecords) {
60+
$aRecords = array();
61+
62+
$cnames = $this->mapRecordData($cnameRecords);
63+
foreach ($cnames as $cname) {
64+
$targets = $this->filterByName($answers, $cname);
65+
$aRecords = array_merge(
66+
$aRecords,
67+
$this->resolveAliases($answers, $cname)
68+
);
69+
}
70+
71+
return $aRecords;
5372
}
5473

55-
$answer = $filteredAnswers[array_rand($filteredAnswers)];
74+
return array();
75+
}
76+
77+
private function filterByName(array $answers, $name)
78+
{
79+
return $this->filterByField($answers, 'name', $name);
80+
}
81+
82+
private function filterByType(array $answers, $type)
83+
{
84+
return $this->filterByField($answers, 'type', $type);
85+
}
5686

57-
return $answer;
87+
private function filterByField(array $answers, $field, $value)
88+
{
89+
return array_filter($answers, function ($answer) use ($field, $value) {
90+
return $value === $answer->$field;
91+
});
92+
}
93+
94+
private function mapRecordData(array $records)
95+
{
96+
return array_map(function ($record) {
97+
return $record->data;
98+
}, $records);
5899
}
59100
}

0 commit comments

Comments
 (0)