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.
8 "internal/syscall/windows"
14 // adapterAddresses returns a list of IP adapter and address
15 // structures. The structure contains an IP adapter and flattened
16 // multiple IP addresses including unicast, anycast and multicast
18 func adapterAddresses() ([]*windows.IpAdapterAddresses, error) {
20 l := uint32(15000) // recommended initial size
23 err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l)
30 if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW {
31 return nil, os.NewSyscallError("getadaptersaddresses", err)
33 if l <= uint32(len(b)) {
34 return nil, os.NewSyscallError("getadaptersaddresses", err)
37 var aas []*windows.IpAdapterAddresses
38 for aa := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); aa != nil; aa = aa.Next {
44 // If the ifindex is zero, interfaceTable returns mappings of all
45 // network interfaces. Otherwise it returns a mapping of a specific
47 func interfaceTable(ifindex int) ([]Interface, error) {
48 aas, err := adapterAddresses()
53 for _, aa := range aas {
55 if index == 0 { // ipv6IfIndex is a substitute for ifIndex
56 index = aa.Ipv6IfIndex
58 if ifindex == 0 || ifindex == int(index) {
61 Name: windows.UTF16PtrToString(aa.FriendlyName),
63 if aa.OperStatus == windows.IfOperStatusUp {
65 ifi.Flags |= FlagRunning
67 // For now we need to infer link-layer service
68 // capabilities from media types.
69 // TODO: use MIB_IF_ROW2.AccessType now that we no longer support
72 case windows.IF_TYPE_ETHERNET_CSMACD, windows.IF_TYPE_ISO88025_TOKENRING, windows.IF_TYPE_IEEE80211, windows.IF_TYPE_IEEE1394:
73 ifi.Flags |= FlagBroadcast | FlagMulticast
74 case windows.IF_TYPE_PPP, windows.IF_TYPE_TUNNEL:
75 ifi.Flags |= FlagPointToPoint | FlagMulticast
76 case windows.IF_TYPE_SOFTWARE_LOOPBACK:
77 ifi.Flags |= FlagLoopback | FlagMulticast
78 case windows.IF_TYPE_ATM:
79 ifi.Flags |= FlagBroadcast | FlagPointToPoint | FlagMulticast // assume all services available; LANE, point-to-point and point-to-multipoint
81 if aa.Mtu == 0xffffffff {
86 if aa.PhysicalAddressLength > 0 {
87 ifi.HardwareAddr = make(HardwareAddr, aa.PhysicalAddressLength)
88 copy(ifi.HardwareAddr, aa.PhysicalAddress[:])
90 ift = append(ift, ifi)
91 if ifindex == ifi.Index {
99 // If the ifi is nil, interfaceAddrTable returns addresses for all
100 // network interfaces. Otherwise it returns addresses for a specific
102 func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
103 aas, err := adapterAddresses()
108 for _, aa := range aas {
110 if index == 0 { // ipv6IfIndex is a substitute for ifIndex
111 index = aa.Ipv6IfIndex
113 if ifi == nil || ifi.Index == int(index) {
114 for puni := aa.FirstUnicastAddress; puni != nil; puni = puni.Next {
115 sa, err := puni.Address.Sockaddr.Sockaddr()
117 return nil, os.NewSyscallError("sockaddr", err)
119 switch sa := sa.(type) {
120 case *syscall.SockaddrInet4:
121 ifat = append(ifat, &IPNet{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3]), Mask: CIDRMask(int(puni.OnLinkPrefixLength), 8*IPv4len)})
122 case *syscall.SockaddrInet6:
123 ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(puni.OnLinkPrefixLength), 8*IPv6len)}
124 copy(ifa.IP, sa.Addr[:])
125 ifat = append(ifat, ifa)
128 for pany := aa.FirstAnycastAddress; pany != nil; pany = pany.Next {
129 sa, err := pany.Address.Sockaddr.Sockaddr()
131 return nil, os.NewSyscallError("sockaddr", err)
133 switch sa := sa.(type) {
134 case *syscall.SockaddrInet4:
135 ifat = append(ifat, &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])})
136 case *syscall.SockaddrInet6:
137 ifa := &IPAddr{IP: make(IP, IPv6len)}
138 copy(ifa.IP, sa.Addr[:])
139 ifat = append(ifat, ifa)
147 // interfaceMulticastAddrTable returns addresses for a specific
149 func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
150 aas, err := adapterAddresses()
155 for _, aa := range aas {
157 if index == 0 { // ipv6IfIndex is a substitute for ifIndex
158 index = aa.Ipv6IfIndex
160 if ifi == nil || ifi.Index == int(index) {
161 for pmul := aa.FirstMulticastAddress; pmul != nil; pmul = pmul.Next {
162 sa, err := pmul.Address.Sockaddr.Sockaddr()
164 return nil, os.NewSyscallError("sockaddr", err)
166 switch sa := sa.(type) {
167 case *syscall.SockaddrInet4:
168 ifat = append(ifat, &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])})
169 case *syscall.SockaddrInet6:
170 ifa := &IPAddr{IP: make(IP, IPv6len)}
171 copy(ifa.IP, sa.Addr[:])
172 ifat = append(ifat, ifa)