-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdns.go
More file actions
94 lines (78 loc) · 2.24 KB
/
Copy pathdns.go
File metadata and controls
94 lines (78 loc) · 2.24 KB
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
83
84
85
86
87
88
89
90
91
92
93
94
package domain
import (
"context"
"net"
"sync"
)
// GetDns performs a DNS lookup for the given domain and returns a slice of IP addresses.
func (c *Client) GetDns(ctx context.Context, domain string) ([]string, error) {
return c.getDns(ctx, domain, "ip")
}
// GetDnsIPv4 performs a DNS lookup for the given domain and returns a slice of IPv4 addresses.
func (c *Client) GetDnsIPv4(ctx context.Context, domain string) ([]string, error) {
return c.getDns(ctx, domain, "ip4")
}
// GetDnsIPv6 performs a DNS lookup for the given domain and returns a slice of IPv6 addresses.
func (c *Client) GetDnsIPv6(ctx context.Context, domain string) ([]string, error) {
return c.getDns(ctx, domain, "ip6")
}
// GetMulti performs DNS lookups for multiple domains concurrently.
// It returns a map where keys are the domains and values are their IP addresses.
// It also returns a slice of errors encountered during the lookups.
func (c *Client) GetMulti(ctx context.Context, domains []string) (map[string][]string, []error) {
var wg sync.WaitGroup
results := make(map[string][]string)
mu := &sync.Mutex{}
var errs []error
for _, domain := range domains {
wg.Add(1)
go func(d string) {
defer wg.Done()
ips, err := c.GetDns(ctx, d)
if err != nil {
mu.Lock()
errs = append(errs, err)
mu.Unlock()
return
}
mu.Lock()
results[d] = ips
mu.Unlock()
}(domain)
}
wg.Wait()
return results, errs
}
func (c *Client) getDns(ctx context.Context, domain string, network string) ([]string, error) {
if ip := parseLiteralIP(domain); ip != nil {
return literalIPResult(ip, network)
}
pDomain := parseDomain(domain)
ipAddrs, err := c.resolver.LookupIP(ctx, network, pDomain)
if err != nil {
return nil, err
}
if len(ipAddrs) == 0 {
return []string{}, nil
}
ips := make([]string, len(ipAddrs))
for i, ip := range ipAddrs {
ips[i] = ip.String()
}
return ips, nil
}
func literalIPResult(ip net.IP, network string) ([]string, error) {
switch network {
case "ip":
return []string{ip.String()}, nil
case "ip4":
if ip.To4() != nil {
return []string{ip.String()}, nil
}
case "ip6":
if ip.To4() == nil {
return []string{ip.String()}, nil
}
}
return nil, &net.AddrError{Err: "no suitable address found", Addr: ip.String()}
}