-
Notifications
You must be signed in to change notification settings - Fork 0
/
resolve.go
82 lines (76 loc) · 1.74 KB
/
resolve.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package main
import (
"log"
"strings"
"unicode"
)
func GetAnswers(packet DNSPacket) string {
for _, answer := range packet.Answers {
if answer.RecordType == TYPE_A {
return (DataToIp(answer.Data))
}
}
return ""
}
func GetNameserverIp(packet DNSPacket) string {
for _, answer := range packet.Additional {
if answer.RecordType == TYPE_A {
return (DataToIp(answer.Data))
}
}
return ""
}
func GetNameServer(packet DNSPacket) string {
res := ""
for _, answer := range packet.Authorities {
var domain []byte
if answer.RecordType == TYPE_NS {
for _, v := range answer.Data {
if unicode.IsSpace(rune(v)) {
domain = append(domain, ' ')
} else {
domain = append(domain, v)
}
}
}
res = strings.Join(strings.Split(strings.TrimSpace(string(domain)), " "), ".")
}
return res
}
func GetCname(packet DNSPacket) string {
for _, answer := range packet.Answers {
if answer.RecordType == TYPE_CNAME {
return string(answer.Data)
}
}
return ""
}
func Resolve(domain string, record int) string {
nameserver := "198.41.0.4" // e.root-servers.net
ip := ""
nsIp := ""
nsDomain := ""
cName := ""
for {
log.Println("Querying", nameserver, "for", domain)
packet := BuildQuery(domain, TYPE_A, nameserver)
ip = GetAnswers(packet)
nsIp = GetNameserverIp(packet)
nsDomain = GetNameServer(packet)
cName = GetCname(packet)
// log.Println("ip", ip, "nsIp", nsIp, "nsDomain", nsDomain, "cName", cName)
if len(ip) > 0 {
// base case
return string(ip)
} else if len(nsIp) > 0 {
nameserver = nsIp
} else if len(nsDomain) > 0 {
nameserver = Resolve(nsDomain, TYPE_A)
} else if len(cName) > 0 {
domain = cName
return Resolve(domain, TYPE_CNAME)
} else {
log.Fatalln("No nameserver found")
}
}
}