1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Network interface identification for Windows
15 func bytePtrToString(p *uint8) string {
16 a := (*[10000]uint8)(unsafe.Pointer(p))
24 func getAdapterList() (*syscall.IpAdapterInfo, error) {
25 b := make([]byte, 1000)
27 a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
28 err := syscall.GetAdaptersInfo(a, &l)
29 if err == syscall.ERROR_BUFFER_OVERFLOW {
31 a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
32 err = syscall.GetAdaptersInfo(a, &l)
35 return nil, os.NewSyscallError("GetAdaptersInfo", err)
40 func getInterfaceList() ([]syscall.InterfaceInfo, error) {
41 s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
43 return nil, os.NewSyscallError("Socket", err)
45 defer syscall.Closesocket(s)
47 ii := [20]syscall.InterfaceInfo{}
49 size := uint32(unsafe.Sizeof(ii))
50 err = syscall.WSAIoctl(s, syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0)
52 return nil, os.NewSyscallError("WSAIoctl", err)
54 c := ret / uint32(unsafe.Sizeof(ii[0]))
58 // If the ifindex is zero, interfaceTable returns mappings of all
59 // network interfaces. Otherwise it returns a mapping of a specific
61 func interfaceTable(ifindex int) ([]Interface, error) {
62 ai, err := getAdapterList()
67 ii, err := getInterfaceList()
73 for ; ai != nil; ai = ai.Next {
75 if ifindex == 0 || ifindex == int(index) {
78 row := syscall.MibIfRow{Index: index}
79 e := syscall.GetIfEntry(&row)
81 return nil, os.NewSyscallError("GetIfEntry", e)
84 for _, ii := range ii {
85 ip := (*syscall.RawSockaddrInet4)(unsafe.Pointer(&ii.Address)).Addr
86 ipv4 := IPv4(ip[0], ip[1], ip[2], ip[3])
87 ipl := &ai.IpAddressList
89 ips := bytePtrToString(&ipl.IpAddress.String[0])
90 if ipv4.Equal(parseIPv4(ips)) {
98 if ii.Flags&syscall.IFF_UP != 0 {
101 if ii.Flags&syscall.IFF_LOOPBACK != 0 {
102 flags |= FlagLoopback
104 if ii.Flags&syscall.IFF_BROADCAST != 0 {
105 flags |= FlagBroadcast
107 if ii.Flags&syscall.IFF_POINTTOPOINT != 0 {
108 flags |= FlagPointToPoint
110 if ii.Flags&syscall.IFF_MULTICAST != 0 {
111 flags |= FlagMulticast
115 name := bytePtrToString(&ai.AdapterName[0])
121 HardwareAddr: HardwareAddr(row.PhysAddr[:row.PhysAddrLen]),
123 ift = append(ift, ifi)
129 // If the ifindex is zero, interfaceAddrTable returns addresses
130 // for all network interfaces. Otherwise it returns addresses
131 // for a specific interface.
132 func interfaceAddrTable(ifindex int) ([]Addr, error) {
133 ai, err := getAdapterList()
139 for ; ai != nil; ai = ai.Next {
141 if ifindex == 0 || ifindex == int(index) {
142 ipl := &ai.IpAddressList
143 for ; ipl != nil; ipl = ipl.Next {
145 ifa.IP = parseIPv4(bytePtrToString(&ipl.IpAddress.String[0]))
146 ifat = append(ifat, ifa.toAddr())
153 // If the ifindex is zero, interfaceMulticastAddrTable returns
154 // addresses for all network interfaces. Otherwise it returns
155 // addresses for a specific interface.
156 func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {