1
2
3
4
19
20 package dns
21
22 import (
23 "fmt"
24 "os"
25 "strings"
26 "syscall"
27 "unsafe"
28
29 "golang.org/x/sys/windows"
30 "golang.org/x/sys/windows/registry"
31 runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
32 "k8s.io/klog/v2"
33 )
34
35 const (
36 netRegistry = `System\CurrentControlSet\Services\TCPIP\Parameters`
37 netIfacesRegistry = `System\CurrentControlSet\Services\TCPIP\Parameters\Interfaces`
38 maxHostnameLen = 128
39 maxDomainNameLen = 128
40 maxScopeIDLen = 256
41
42
43
44 hostResolvConf = "Host"
45 )
46
47
48 type FixedInfo struct {
49 HostName [maxHostnameLen + 4]byte
50 DomainName [maxDomainNameLen + 4]byte
51 CurrentDNSServer *syscall.IpAddrString
52 DNSServerList syscall.IpAddrString
53 NodeType uint32
54 ScopeID [maxScopeIDLen + 4]byte
55 EnableRouting uint32
56 EnableProxy uint32
57 EnableDNS uint32
58 }
59
60 var (
61
62
63 iphlpapidll = windows.MustLoadDLL("iphlpapi.dll")
64 procGetNetworkParams = iphlpapidll.MustFindProc("GetNetworkParams")
65 )
66
67 func fileExists(filename string) (bool, error) {
68 stat, err := os.Stat(filename)
69 if os.IsNotExist(err) {
70 return false, nil
71 }
72 if err != nil {
73 return false, err
74 }
75
76 return stat.Mode().IsRegular(), nil
77 }
78
79 func getHostDNSConfig(resolverConfig string) (*runtimeapi.DNSConfig, error) {
80 if resolverConfig == "" {
81
82 return getDNSConfig(resolverConfig)
83 }
84
85 isFile, err := fileExists(resolverConfig)
86 if err != nil {
87 err = fmt.Errorf(`Unexpected error while getting os.Stat for "%s" resolver config. Error: %w`, resolverConfig, err)
88 klog.ErrorS(err, "Cannot get host DNS Configuration.")
89 return nil, err
90 }
91 if isFile {
92
93 return getDNSConfig(resolverConfig)
94 }
95
96 if resolverConfig != hostResolvConf {
97 err := fmt.Errorf(`Unexpected resolver config value: "%s". Expected "", "%s", or a path to an existing resolv.conf file.`, resolverConfig, hostResolvConf)
98 klog.ErrorS(err, "Cannot get host DNS Configuration.")
99 return nil, err
100 }
101
102
103
104
105 hostDNS, err := getDNSServerList()
106 if err != nil {
107 err = fmt.Errorf("Could not get the host's DNS Server List. Error: %w", err)
108 klog.ErrorS(err, "Encountered error while getting host's DNS Server List.")
109 return nil, err
110 }
111 hostSearch, err := getDNSSuffixList()
112 if err != nil {
113 err = fmt.Errorf("Could not get the host's DNS Suffix List. Error: %w", err)
114 klog.ErrorS(err, "Encountered error while getting host's DNS Suffix List.")
115 return nil, err
116 }
117 return &runtimeapi.DNSConfig{
118 Servers: hostDNS,
119 Searches: hostSearch,
120 }, nil
121 }
122
123 func elemInList(elem string, list []string) bool {
124 for _, e := range list {
125 if e == elem {
126 return true
127 }
128 }
129 return false
130 }
131
132 func getRegistryStringValue(reg, key string) (string, error) {
133 regKey, err := registry.OpenKey(registry.LOCAL_MACHINE, reg, registry.QUERY_VALUE)
134 if err != nil {
135 return "", err
136 }
137 defer regKey.Close()
138
139 regValue, _, err := regKey.GetStringValue(key)
140 return regValue, err
141 }
142
143
144 func getDNSSuffixList() ([]string, error) {
145
146 allSuffixes := []string{}
147 suffixes, err := getRegistryStringValue(netRegistry, "SearchList")
148 if err != nil {
149 return nil, err
150 }
151 allSuffixes = strings.Split(suffixes, ",")
152
153
154 regKey, err := registry.OpenKey(registry.LOCAL_MACHINE, netIfacesRegistry, registry.ENUMERATE_SUB_KEYS)
155 if err != nil {
156 return nil, err
157 }
158 defer regKey.Close()
159
160 ifaces, err := regKey.ReadSubKeyNames(0)
161 if err != nil {
162 return nil, err
163 }
164 for _, iface := range ifaces {
165 suffixes, err := getRegistryStringValue(fmt.Sprintf("%s\\%s", netIfacesRegistry, iface), "SearchList")
166 if err != nil {
167 return nil, err
168 }
169 if suffixes == "" {
170 continue
171 }
172 for _, suffix := range strings.Split(suffixes, ",") {
173 if !elemInList(suffix, allSuffixes) {
174 allSuffixes = append(allSuffixes, suffix)
175 }
176 }
177 }
178
179 return allSuffixes, nil
180 }
181
182 func getNetworkParams() (*FixedInfo, error) {
183
184
185 var size int = 1
186 buffer := make([]byte, 1)
187 ret, _, err := procGetNetworkParams.Call(
188 uintptr(unsafe.Pointer(&buffer[0])),
189 uintptr(unsafe.Pointer(&size)),
190 )
191 if ret != uintptr(syscall.ERROR_BUFFER_OVERFLOW) {
192 err = fmt.Errorf("Unexpected return value %d from GetNetworkParams. Expected: %d. Error: %w", ret, syscall.ERROR_BUFFER_OVERFLOW, err)
193 return nil, err
194 }
195
196 buffer = make([]byte, size)
197 ret, _, err = procGetNetworkParams.Call(
198 uintptr(unsafe.Pointer(&buffer[0])),
199 uintptr(unsafe.Pointer(&size)),
200 )
201 if ret != 0 {
202 err = fmt.Errorf("Unexpected return value %d from GetNetworkParams. Expected: 0. Error: %w", ret, err)
203 return nil, err
204 }
205
206 info := (*FixedInfo)(unsafe.Pointer(&buffer[0]))
207 return info, nil
208 }
209
210 func getDNSServerList() ([]string, error) {
211 dnsServerList := []string{}
212 fixedInfo, err := getNetworkParams()
213 if err != nil {
214 return nil, err
215 }
216
217 list := &(fixedInfo.DNSServerList)
218 for list != nil {
219 dnsServer := strings.TrimRight(string(list.IpAddress.String[:]), "\x00")
220 dnsServerList = append(dnsServerList, dnsServer)
221 list = list.Next
222 }
223 return dnsServerList, nil
224 }
225
View as plain text