master
go 73 lines 1.74 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package dnsquery
4
5 import (
6 "math/rand"
7 "net"
8 "strconv"
9 "sync"
10 "time"
11
12 "github.com/miekg/dns"
13 )
14
15 func (c *Collector) collect() (map[string]int64, error) {
16 if c.dnsClient == nil {
17 c.dnsClient = c.newDNSClient(c.Network, c.Timeout.Duration())
18 }
19
20 mx := make(map[string]int64)
21 domain := randomDomain(c.Domains)
22 c.Debugf("current domain : %s", domain)
23
24 var wg sync.WaitGroup
25 var mux sync.RWMutex
26 for _, srv := range c.Servers {
27 for rtypeName, rtype := range c.recordTypes {
28 wg.Add(1)
29 go func(srv, rtypeName string, rtype uint16, wg *sync.WaitGroup) {
30 defer wg.Done()
31
32 msg := new(dns.Msg)
33 msg.SetQuestion(dns.Fqdn(domain), rtype)
34 address := net.JoinHostPort(srv, strconv.Itoa(c.Port))
35
36 resp, rtt, err := c.dnsClient.Exchange(msg, address)
37
38 mux.Lock()
39 defer mux.Unlock()
40
41 px := "server_" + srv + "_record_" + rtypeName + "_"
42
43 mx[px+"query_status_success"] = 0
44 mx[px+"query_status_network_error"] = 0
45 mx[px+"query_status_dns_error"] = 0
46
47 if err != nil {
48 c.Debugf("error on querying %s after %s query for %s : %s", srv, rtypeName, domain, err)
49 mx[px+"query_status_network_error"] = 1
50 return
51 }
52
53 if resp != nil && resp.Rcode != dns.RcodeSuccess {
54 c.Debugf("invalid answer from %s after %s query for %s (rcode %d)", srv, rtypeName, domain, resp.Rcode)
55 mx[px+"query_status_dns_error"] = 1
56 } else {
57 mx[px+"query_status_success"] = 1
58 }
59 mx["server_"+srv+"_record_"+rtypeName+"_query_time"] = rtt.Nanoseconds()
60
61 }(srv, rtypeName, rtype, &wg)
62 }
63 }
64 wg.Wait()
65
66 return mx, nil
67 }
68
69 func randomDomain(domains []string) string {
70 src := rand.NewSource(time.Now().UnixNano())
71 r := rand.New(src)
72 return domains[r.Intn(len(domains))]
73 }