@@ -177,6 +177,18 @@ func isWindowsXP(t *testing.T) bool {
177
177
return major < 6
178
178
}
179
179
180
+ var (
181
+ modkernel32 = syscall .NewLazyDLL ("kernel32.dll" )
182
+ procGetACP = modkernel32 .NewProc ("GetACP" )
183
+ )
184
+
185
+ func isEnglishOS (t * testing.T ) bool {
186
+ const windows_1252 = 1252 // ANSI Latin 1; Western European (Windows)
187
+ r0 , _ , _ := syscall .Syscall (procGetACP .Addr (), 0 , 0 , 0 , 0 )
188
+ acp := uint32 (r0 )
189
+ return acp == windows_1252
190
+ }
191
+
180
192
func runCmd (args ... string ) ([]byte , error ) {
181
193
removeUTF8BOM := func (b []byte ) []byte {
182
194
if len (b ) >= 3 && b [0 ] == 0xEF && b [1 ] == 0xBB && b [2 ] == 0xBF {
@@ -213,40 +225,87 @@ func runCmd(args ...string) ([]byte, error) {
213
225
return removeUTF8BOM (out ), nil
214
226
}
215
227
216
- func netshInterfaceIPShowConfig () ([] string , error ) {
217
- out , err := runCmd ("netsh" , "interface" , "ip " , "show " , "config " )
228
+ func netshInterfaceIPShowInterface ( ipver string , ifaces map [ string ] bool ) error {
229
+ out , err := runCmd ("netsh" , "interface" , ipver , "show " , "interface " , "level=verbose " )
218
230
if err != nil {
219
- return nil , err
231
+ return err
220
232
}
233
+ // interface information is listed like:
234
+ //
235
+ //Interface Local Area Connection Parameters
236
+ //----------------------------------------------
237
+ //IfLuid : ethernet_6
238
+ //IfIndex : 11
239
+ //State : connected
240
+ //Metric : 10
241
+ //...
242
+ var name string
221
243
lines := bytes .Split (out , []byte {'\r' , '\n' })
222
- names := make ([]string , 0 )
223
244
for _ , line := range lines {
224
- f := bytes .Split (line , []byte {'"' })
225
- if len (f ) == 3 {
226
- names = append (names , string (f [1 ]))
245
+ if bytes .HasPrefix (line , []byte ("Interface " )) && bytes .HasSuffix (line , []byte (" Parameters" )) {
246
+ f := line [len ("Interface " ):]
247
+ f = f [:len (f )- len (" Parameters" )]
248
+ name = string (f )
249
+ continue
250
+ }
251
+ var isup bool
252
+ switch string (line ) {
253
+ case "State : connected" :
254
+ isup = true
255
+ case "State : disconnected" :
256
+ isup = false
257
+ default :
258
+ continue
259
+ }
260
+ if name != "" {
261
+ if v , ok := ifaces [name ]; ok && v != isup {
262
+ return fmt .Errorf ("%s:%s isup=%v: ipv4 and ipv6 report different interface state" , ipver , name , isup )
263
+ }
264
+ ifaces [name ] = isup
265
+ name = ""
227
266
}
228
267
}
229
- return names , nil
268
+ return nil
230
269
}
231
270
232
271
func TestInterfacesWithNetsh (t * testing.T ) {
233
272
if isWindowsXP (t ) {
234
273
t .Skip ("Windows XP netsh command does not provide required functionality" )
235
274
}
275
+ if ! isEnglishOS (t ) {
276
+ t .Skip ("English version of OS required for this test" )
277
+ }
278
+
279
+ toString := func (name string , isup bool ) string {
280
+ if isup {
281
+ return name + ":up"
282
+ }
283
+ return name + ":down"
284
+ }
285
+
236
286
ift , err := Interfaces ()
237
287
if err != nil {
238
288
t .Fatal (err )
239
289
}
240
290
have := make ([]string , 0 )
241
291
for _ , ifi := range ift {
242
- have = append (have , ifi .Name )
292
+ have = append (have , toString ( ifi .Name , ifi . Flags & FlagUp != 0 ) )
243
293
}
244
294
sort .Strings (have )
245
295
246
- want , err := netshInterfaceIPShowConfig ()
296
+ ifaces := make (map [string ]bool )
297
+ err = netshInterfaceIPShowInterface ("ipv6" , ifaces )
247
298
if err != nil {
248
299
t .Fatal (err )
249
300
}
301
+ err = netshInterfaceIPShowInterface ("ipv4" , ifaces )
302
+ if err != nil {
303
+ t .Fatal (err )
304
+ }
305
+ want := make ([]string , 0 )
306
+ for name , isup := range ifaces {
307
+ want = append (want , toString (name , isup ))
308
+ }
250
309
sort .Strings (want )
251
310
252
311
if strings .Join (want , "/" ) != strings .Join (have , "/" ) {
@@ -324,6 +383,9 @@ func TestInterfaceAddrsWithNetsh(t *testing.T) {
324
383
if isWindowsXP (t ) {
325
384
t .Skip ("Windows XP netsh command does not provide required functionality" )
326
385
}
386
+ if ! isEnglishOS (t ) {
387
+ t .Skip ("English version of OS required for this test" )
388
+ }
327
389
ift , err := Interfaces ()
328
390
if err != nil {
329
391
t .Fatal (err )
@@ -377,6 +439,10 @@ func TestInterfaceHardwareAddrWithGetmac(t *testing.T) {
377
439
if isWindowsXP (t ) {
378
440
t .Skip ("Windows XP does not have powershell command" )
379
441
}
442
+ if ! isEnglishOS (t ) {
443
+ t .Skip ("English version of OS required for this test" )
444
+ }
445
+
380
446
ift , err := Interfaces ()
381
447
if err != nil {
382
448
t .Fatal (err )
0 commit comments