1
+ // +build windows
2
+
1
3
/*
2
4
Copyright 2019 The Kubernetes Authors.
3
5
@@ -17,40 +19,131 @@ limitations under the License.
17
19
package dns
18
20
19
21
import (
20
- "bytes"
21
- "os/exec"
22
+ "fmt"
22
23
"strings"
24
+ "syscall"
25
+ "unsafe"
26
+
27
+ "golang.org/x/sys/windows"
28
+ "golang.org/x/sys/windows/registry"
23
29
)
24
30
25
- const etcHostsFile = "C:/Windows/System32/drivers/etc/hosts"
31
+ const (
32
+ etcHostsFile = "C:/Windows/System32/drivers/etc/hosts"
33
+ netRegistry = `System\CurrentControlSet\Services\TCPIP\Parameters`
34
+ netIfacesRegistry = `System\CurrentControlSet\Services\TCPIP\Parameters\Interfaces`
35
+ maxHostnameLen = 128
36
+ maxDomainNameLen = 128
37
+ maxScopeIDLen = 256
38
+ )
26
39
27
- func getDNSSuffixList () []string {
28
- output := runCommand ("powershell" , "-Command" , "(Get-DnsClient)[0].SuffixSearchList" )
29
- if len (output ) > 0 {
30
- return strings .Split (output , "\r \n " )
31
- }
40
+ // FixedInfo information: https://docs.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-fixed_info_w2ksp1
41
+ type FixedInfo struct {
42
+ HostName [maxHostnameLen + 4 ]byte
43
+ DomainName [maxDomainNameLen + 4 ]byte
44
+ CurrentDNSServer * syscall.IpAddrString
45
+ DNSServerList syscall.IpAddrString
46
+ NodeType uint32
47
+ ScopeID [maxScopeIDLen + 4 ]byte
48
+ EnableRouting uint32
49
+ EnableProxy uint32
50
+ EnableDNS uint32
51
+ }
52
+
53
+ var (
54
+ // GetNetworkParams can be found in iphlpapi.dll
55
+ // see: https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getnetworkparams?redirectedfrom=MSDN
56
+ iphlpapidll = windows .MustLoadDLL ("iphlpapi.dll" )
57
+ procGetNetworkParams = iphlpapidll .MustFindProc ("GetNetworkParams" )
58
+ )
32
59
33
- panic ("Could not find DNS search list!" )
60
+ func elemInList (elem string , list []string ) bool {
61
+ for _ , e := range list {
62
+ if e == elem {
63
+ return true
64
+ }
65
+ }
66
+ return false
34
67
}
35
68
36
- func getDNSServerList () [] string {
37
- output := runCommand ( "powershell" , "-Command" , "(Get-DnsClientServerAddress).ServerAddresses" )
38
- if len ( output ) > 0 {
39
- return strings . Split ( output , " \r \n " )
69
+ func getRegistryValue ( reg , key string ) string {
70
+ regKey , err := registry . OpenKey ( registry . LOCAL_MACHINE , reg , registry . QUERY_VALUE )
71
+ if err != nil {
72
+ return ""
40
73
}
74
+ defer regKey .Close ()
41
75
42
- panic ("Could not find DNS Server list!" )
76
+ regValue , _ , err := regKey .GetStringValue (key )
77
+ if err != nil {
78
+ return ""
79
+ }
80
+ return regValue
43
81
}
44
82
45
- func runCommand (name string , arg ... string ) string {
46
- var out bytes.Buffer
47
- cmd := exec .Command (name , arg ... )
48
- cmd .Stdout = & out
83
+ // getDNSSuffixList reads DNS config file and returns the list of configured DNS suffixes
84
+ func getDNSSuffixList () []string {
85
+ // We start with the general suffix list that apply to all network connections.
86
+ allSuffixes := []string {}
87
+ suffixes := getRegistryValue (netRegistry , "SearchList" )
88
+ if suffixes != "" {
89
+ allSuffixes = strings .Split (suffixes , "," )
90
+ }
49
91
50
- err := cmd .Run ()
92
+ // Then we append the network-specific DNS suffix lists.
93
+ regKey , err := registry .OpenKey (registry .LOCAL_MACHINE , netIfacesRegistry , registry .ENUMERATE_SUB_KEYS )
51
94
if err != nil {
52
95
panic (err )
53
96
}
97
+ defer regKey .Close ()
54
98
55
- return strings .TrimSpace (out .String ())
99
+ ifaces , err := regKey .ReadSubKeyNames (0 )
100
+ if err != nil {
101
+ panic (err )
102
+ }
103
+ for _ , iface := range ifaces {
104
+ suffixes := getRegistryValue (fmt .Sprintf ("%s\\ %s" , netIfacesRegistry , iface ), "SearchList" )
105
+ if suffixes == "" {
106
+ continue
107
+ }
108
+ for _ , suffix := range strings .Split (suffixes , "," ) {
109
+ if ! elemInList (suffix , allSuffixes ) {
110
+ allSuffixes = append (allSuffixes , suffix )
111
+ }
112
+ }
113
+ }
114
+
115
+ return allSuffixes
116
+ }
117
+
118
+ func getNetworkParams () * FixedInfo {
119
+ // We don't know how big we should make the byte buffer, but the call will tell us by
120
+ // setting the size afterwards.
121
+ var size int
122
+ buffer := make ([]byte , 1 )
123
+ procGetNetworkParams .Call (
124
+ uintptr (unsafe .Pointer (& buffer [0 ])),
125
+ uintptr (unsafe .Pointer (& size )),
126
+ )
127
+
128
+ buffer = make ([]byte , size )
129
+ procGetNetworkParams .Call (
130
+ uintptr (unsafe .Pointer (& buffer [0 ])),
131
+ uintptr (unsafe .Pointer (& size )),
132
+ )
133
+
134
+ info := (* FixedInfo )(unsafe .Pointer (& buffer [0 ]))
135
+ return info
136
+ }
137
+
138
+ func getDNSServerList () []string {
139
+ dnsServerList := []string {}
140
+ fixedInfo := getNetworkParams ()
141
+ list := & (fixedInfo .DNSServerList )
142
+
143
+ for list != nil {
144
+ dnsServer := strings .TrimRight (string (list .IpAddress .String [:]), "\x00 " )
145
+ dnsServerList = append (dnsServerList , dnsServer )
146
+ list = list .Next
147
+ }
148
+ return dnsServerList
56
149
}
0 commit comments