OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / github.com / miekg / dns / clientconfig.go
1 package dns
2
3 import (
4         "bufio"
5         "io"
6         "os"
7         "strconv"
8         "strings"
9 )
10
11 // ClientConfig wraps the contents of the /etc/resolv.conf file.
12 type ClientConfig struct {
13         Servers  []string // servers to use
14         Search   []string // suffixes to append to local name
15         Port     string   // what port to use
16         Ndots    int      // number of dots in name to trigger absolute lookup
17         Timeout  int      // seconds before giving up on packet
18         Attempts int      // lost packets before giving up on server, not used in the package dns
19 }
20
21 // ClientConfigFromFile parses a resolv.conf(5) like file and returns
22 // a *ClientConfig.
23 func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
24         file, err := os.Open(resolvconf)
25         if err != nil {
26                 return nil, err
27         }
28         defer file.Close()
29         return ClientConfigFromReader(file)
30 }
31
32 // ClientConfigFromReader works like ClientConfigFromFile but takes an io.Reader as argument
33 func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
34         c := new(ClientConfig)
35         scanner := bufio.NewScanner(resolvconf)
36         c.Servers = make([]string, 0)
37         c.Search = make([]string, 0)
38         c.Port = "53"
39         c.Ndots = 1
40         c.Timeout = 5
41         c.Attempts = 2
42
43         for scanner.Scan() {
44                 if err := scanner.Err(); err != nil {
45                         return nil, err
46                 }
47                 line := scanner.Text()
48                 f := strings.Fields(line)
49                 if len(f) < 1 {
50                         continue
51                 }
52                 switch f[0] {
53                 case "nameserver": // add one name server
54                         if len(f) > 1 {
55                                 // One more check: make sure server name is
56                                 // just an IP address.  Otherwise we need DNS
57                                 // to look it up.
58                                 name := f[1]
59                                 c.Servers = append(c.Servers, name)
60                         }
61
62                 case "domain": // set search path to just this domain
63                         if len(f) > 1 {
64                                 c.Search = make([]string, 1)
65                                 c.Search[0] = f[1]
66                         } else {
67                                 c.Search = make([]string, 0)
68                         }
69
70                 case "search": // set search path to given servers
71                         c.Search = make([]string, len(f)-1)
72                         for i := 0; i < len(c.Search); i++ {
73                                 c.Search[i] = f[i+1]
74                         }
75
76                 case "options": // magic options
77                         for i := 1; i < len(f); i++ {
78                                 s := f[i]
79                                 switch {
80                                 case len(s) >= 6 && s[:6] == "ndots:":
81                                         n, _ := strconv.Atoi(s[6:])
82                                         if n < 0 {
83                                                 n = 0
84                                         } else if n > 15 {
85                                                 n = 15
86                                         }
87                                         c.Ndots = n
88                                 case len(s) >= 8 && s[:8] == "timeout:":
89                                         n, _ := strconv.Atoi(s[8:])
90                                         if n < 1 {
91                                                 n = 1
92                                         }
93                                         c.Timeout = n
94                                 case len(s) >= 9 && s[:9] == "attempts:":
95                                         n, _ := strconv.Atoi(s[9:])
96                                         if n < 1 {
97                                                 n = 1
98                                         }
99                                         c.Attempts = n
100                                 case s == "rotate":
101                                         /* not imp */
102                                 }
103                         }
104                 }
105         }
106         return c, nil
107 }
108
109 // NameList returns all of the names that should be queried based on the
110 // config. It is based off of go's net/dns name building, but it does not
111 // check the length of the resulting names.
112 func (c *ClientConfig) NameList(name string) []string {
113         // if this domain is already fully qualified, no append needed.
114         if IsFqdn(name) {
115                 return []string{name}
116         }
117
118         // Check to see if the name has more labels than Ndots. Do this before making
119         // the domain fully qualified.
120         hasNdots := CountLabel(name) > c.Ndots
121         // Make the domain fully qualified.
122         name = Fqdn(name)
123
124         // Make a list of names based off search.
125         names := []string{}
126
127         // If name has enough dots, try that first.
128         if hasNdots {
129                 names = append(names, name)
130         }
131         for _, s := range c.Search {
132                 names = append(names, Fqdn(name+s))
133         }
134         // If we didn't have enough dots, try after suffixes.
135         if !hasNdots {
136                 names = append(names, name)
137         }
138         return names
139 }