123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- // Copyright 2011 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package net
- import (
- "internal/syscall/windows"
- "os"
- "syscall"
- "unsafe"
- )
- // adapterAddresses returns a list of IP adapter and address
- // structures. The structure contains an IP adapter and flattened
- // multiple IP addresses including unicast, anycast and multicast
- // addresses.
- func adapterAddresses() ([]*windows.IpAdapterAddresses, error) {
- var b []byte
- l := uint32(15000) // recommended initial size
- for {
- b = make([]byte, l)
- err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l)
- if err == nil {
- if l == 0 {
- return nil, nil
- }
- break
- }
- if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW {
- return nil, os.NewSyscallError("getadaptersaddresses", err)
- }
- if l <= uint32(len(b)) {
- return nil, os.NewSyscallError("getadaptersaddresses", err)
- }
- }
- var aas []*windows.IpAdapterAddresses
- for aa := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); aa != nil; aa = aa.Next {
- aas = append(aas, aa)
- }
- return aas, nil
- }
- // If the ifindex is zero, interfaceTable returns mappings of all
- // network interfaces. Otherwise it returns a mapping of a specific
- // interface.
- func interfaceTable(ifindex int) ([]Interface, error) {
- aas, err := adapterAddresses()
- if err != nil {
- return nil, err
- }
- var ift []Interface
- for _, aa := range aas {
- index := aa.IfIndex
- if index == 0 { // ipv6IfIndex is a substitute for ifIndex
- index = aa.Ipv6IfIndex
- }
- if ifindex == 0 || ifindex == int(index) {
- ifi := Interface{
- Index: int(index),
- Name: windows.UTF16PtrToString(aa.FriendlyName),
- }
- if aa.OperStatus == windows.IfOperStatusUp {
- ifi.Flags |= FlagUp
- }
- // For now we need to infer link-layer service
- // capabilities from media types.
- // TODO: use MIB_IF_ROW2.AccessType now that we no longer support
- // Windows XP.
- switch aa.IfType {
- case windows.IF_TYPE_ETHERNET_CSMACD, windows.IF_TYPE_ISO88025_TOKENRING, windows.IF_TYPE_IEEE80211, windows.IF_TYPE_IEEE1394:
- ifi.Flags |= FlagBroadcast | FlagMulticast
- case windows.IF_TYPE_PPP, windows.IF_TYPE_TUNNEL:
- ifi.Flags |= FlagPointToPoint | FlagMulticast
- case windows.IF_TYPE_SOFTWARE_LOOPBACK:
- ifi.Flags |= FlagLoopback | FlagMulticast
- case windows.IF_TYPE_ATM:
- ifi.Flags |= FlagBroadcast | FlagPointToPoint | FlagMulticast // assume all services available; LANE, point-to-point and point-to-multipoint
- }
- if aa.Mtu == 0xffffffff {
- ifi.MTU = -1
- } else {
- ifi.MTU = int(aa.Mtu)
- }
- if aa.PhysicalAddressLength > 0 {
- ifi.HardwareAddr = make(HardwareAddr, aa.PhysicalAddressLength)
- copy(ifi.HardwareAddr, aa.PhysicalAddress[:])
- }
- ift = append(ift, ifi)
- if ifindex == ifi.Index {
- break
- }
- }
- }
- return ift, nil
- }
- // If the ifi is nil, interfaceAddrTable returns addresses for all
- // network interfaces. Otherwise it returns addresses for a specific
- // interface.
- func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
- aas, err := adapterAddresses()
- if err != nil {
- return nil, err
- }
- var ifat []Addr
- for _, aa := range aas {
- index := aa.IfIndex
- if index == 0 { // ipv6IfIndex is a substitute for ifIndex
- index = aa.Ipv6IfIndex
- }
- if ifi == nil || ifi.Index == int(index) {
- for puni := aa.FirstUnicastAddress; puni != nil; puni = puni.Next {
- sa, err := puni.Address.Sockaddr.Sockaddr()
- if err != nil {
- return nil, os.NewSyscallError("sockaddr", err)
- }
- switch sa := sa.(type) {
- case *syscall.SockaddrInet4:
- 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)})
- case *syscall.SockaddrInet6:
- ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(puni.OnLinkPrefixLength), 8*IPv6len)}
- copy(ifa.IP, sa.Addr[:])
- ifat = append(ifat, ifa)
- }
- }
- for pany := aa.FirstAnycastAddress; pany != nil; pany = pany.Next {
- sa, err := pany.Address.Sockaddr.Sockaddr()
- if err != nil {
- return nil, os.NewSyscallError("sockaddr", err)
- }
- switch sa := sa.(type) {
- case *syscall.SockaddrInet4:
- ifat = append(ifat, &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])})
- case *syscall.SockaddrInet6:
- ifa := &IPAddr{IP: make(IP, IPv6len)}
- copy(ifa.IP, sa.Addr[:])
- ifat = append(ifat, ifa)
- }
- }
- }
- }
- return ifat, nil
- }
- // interfaceMulticastAddrTable returns addresses for a specific
- // interface.
- func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
- aas, err := adapterAddresses()
- if err != nil {
- return nil, err
- }
- var ifat []Addr
- for _, aa := range aas {
- index := aa.IfIndex
- if index == 0 { // ipv6IfIndex is a substitute for ifIndex
- index = aa.Ipv6IfIndex
- }
- if ifi == nil || ifi.Index == int(index) {
- for pmul := aa.FirstMulticastAddress; pmul != nil; pmul = pmul.Next {
- sa, err := pmul.Address.Sockaddr.Sockaddr()
- if err != nil {
- return nil, os.NewSyscallError("sockaddr", err)
- }
- switch sa := sa.(type) {
- case *syscall.SockaddrInet4:
- ifat = append(ifat, &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])})
- case *syscall.SockaddrInet6:
- ifa := &IPAddr{IP: make(IP, IPv6len)}
- copy(ifa.IP, sa.Addr[:])
- ifat = append(ifat, ifa)
- }
- }
- }
- }
- return ifat, nil
- }
|