interface_aix.mx raw

   1  // Copyright 2018 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.
   4  
   5  package net
   6  
   7  import (
   8  	"internal/poll"
   9  	"internal/syscall/unix"
  10  	"syscall"
  11  	"unsafe"
  12  )
  13  
  14  type rawSockaddrDatalink struct {
  15  	Len    uint8
  16  	Family uint8
  17  	Index  uint16
  18  	Type   uint8
  19  	Nlen   uint8
  20  	Alen   uint8
  21  	Slen   uint8
  22  	Data   [120]byte
  23  }
  24  
  25  type ifreq struct {
  26  	Name [16]uint8
  27  	Ifru [16]byte
  28  }
  29  
  30  const _KINFO_RT_IFLIST = (0x1 << 8) | 3 | (1 << 30)
  31  
  32  const _RTAX_NETMASK = 2
  33  const _RTAX_IFA = 5
  34  const _RTAX_MAX = 8
  35  
  36  func getIfList() ([]byte, error) {
  37  	needed, err := syscall.Getkerninfo(_KINFO_RT_IFLIST, 0, 0, 0)
  38  	if err != nil {
  39  		return nil, err
  40  	}
  41  	tab := []byte{:needed}
  42  	_, err = syscall.Getkerninfo(_KINFO_RT_IFLIST, uintptr(unsafe.Pointer(&tab[0])), uintptr(unsafe.Pointer(&needed)), 0)
  43  	if err != nil {
  44  		return nil, err
  45  	}
  46  	return tab[:needed], nil
  47  }
  48  
  49  // If the ifindex is zero, interfaceTable returns mappings of all
  50  // network interfaces. Otherwise it returns a mapping of a specific
  51  // interface.
  52  func interfaceTable(ifindex int) ([]Interface, error) {
  53  	tab, err := getIfList()
  54  	if err != nil {
  55  		return nil, err
  56  	}
  57  
  58  	sock, err := sysSocket(syscall.AF_INET, syscall.SOCK_DGRAM, 0)
  59  	if err != nil {
  60  		return nil, err
  61  	}
  62  	defer poll.CloseFunc(sock)
  63  
  64  	var ift []Interface
  65  	for len(tab) > 0 {
  66  		ifm := (*syscall.IfMsgHdr)(unsafe.Pointer(&tab[0]))
  67  		if ifm.Msglen == 0 {
  68  			break
  69  		}
  70  		if ifm.Type == syscall.RTM_IFINFO {
  71  			if ifindex == 0 || ifindex == int(ifm.Index) {
  72  				sdl := (*rawSockaddrDatalink)(unsafe.Pointer(&tab[syscall.SizeofIfMsghdr]))
  73  
  74  				ifi := &Interface{Index: int(ifm.Index), Flags: linkFlags(ifm.Flags)}
  75  				ifi.Name = string(sdl.Data[:sdl.Nlen])
  76  				ifi.HardwareAddr = sdl.Data[sdl.Nlen : sdl.Nlen+sdl.Alen]
  77  
  78  				// Retrieve MTU
  79  				ifr := &ifreq{}
  80  				copy(ifr.Name[:], ifi.Name)
  81  				err = unix.Ioctl(sock, syscall.SIOCGIFMTU, unsafe.Pointer(ifr))
  82  				if err != nil {
  83  					return nil, err
  84  				}
  85  				ifi.MTU = int(ifr.Ifru[0])<<24 | int(ifr.Ifru[1])<<16 | int(ifr.Ifru[2])<<8 | int(ifr.Ifru[3])
  86  
  87  				ift = append(ift, *ifi)
  88  				if ifindex == int(ifm.Index) {
  89  					break
  90  				}
  91  			}
  92  		}
  93  		tab = tab[ifm.Msglen:]
  94  	}
  95  
  96  	return ift, nil
  97  }
  98  
  99  func linkFlags(rawFlags int32) Flags {
 100  	var f Flags
 101  	if rawFlags&syscall.IFF_UP != 0 {
 102  		f |= FlagUp
 103  	}
 104  	if rawFlags&syscall.IFF_RUNNING != 0 {
 105  		f |= FlagRunning
 106  	}
 107  	if rawFlags&syscall.IFF_BROADCAST != 0 {
 108  		f |= FlagBroadcast
 109  	}
 110  	if rawFlags&syscall.IFF_LOOPBACK != 0 {
 111  		f |= FlagLoopback
 112  	}
 113  	if rawFlags&syscall.IFF_POINTOPOINT != 0 {
 114  		f |= FlagPointToPoint
 115  	}
 116  	if rawFlags&syscall.IFF_MULTICAST != 0 {
 117  		f |= FlagMulticast
 118  	}
 119  	return f
 120  }
 121  
 122  // If the ifi is nil, interfaceAddrTable returns addresses for all
 123  // network interfaces. Otherwise it returns addresses for a specific
 124  // interface.
 125  func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
 126  	tab, err := getIfList()
 127  	if err != nil {
 128  		return nil, err
 129  	}
 130  
 131  	var ifat []Addr
 132  	for len(tab) > 0 {
 133  		ifm := (*syscall.IfMsgHdr)(unsafe.Pointer(&tab[0]))
 134  		if ifm.Msglen == 0 {
 135  			break
 136  		}
 137  		if ifm.Type == syscall.RTM_NEWADDR {
 138  			if ifi == nil || ifi.Index == int(ifm.Index) {
 139  				mask := ifm.Addrs
 140  				off := uint(syscall.SizeofIfMsghdr)
 141  
 142  				var iprsa, nmrsa *syscall.RawSockaddr
 143  				for i := uint(0); i < _RTAX_MAX; i++ {
 144  					if mask&(1<<i) == 0 {
 145  						continue
 146  					}
 147  					rsa := (*syscall.RawSockaddr)(unsafe.Pointer(&tab[off]))
 148  					if i == _RTAX_NETMASK {
 149  						nmrsa = rsa
 150  					}
 151  					if i == _RTAX_IFA {
 152  						iprsa = rsa
 153  					}
 154  					off += (uint(rsa.Len) + 3) &^ 3
 155  				}
 156  				if iprsa != nil && nmrsa != nil {
 157  					var mask IPMask
 158  					var ip IP
 159  
 160  					switch iprsa.Family {
 161  					case syscall.AF_INET:
 162  						ipsa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(iprsa))
 163  						nmsa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(nmrsa))
 164  						ip = IPv4(ipsa.Addr[0], ipsa.Addr[1], ipsa.Addr[2], ipsa.Addr[3])
 165  						mask = IPv4Mask(nmsa.Addr[0], nmsa.Addr[1], nmsa.Addr[2], nmsa.Addr[3])
 166  					case syscall.AF_INET6:
 167  						ipsa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(iprsa))
 168  						nmsa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(nmrsa))
 169  						ip = make(IP, IPv6len)
 170  						copy(ip, ipsa.Addr[:])
 171  						mask = make(IPMask, IPv6len)
 172  						copy(mask, nmsa.Addr[:])
 173  					}
 174  					ifa := &IPNet{IP: ip, Mask: mask}
 175  					ifat = append(ifat, ifa)
 176  				}
 177  			}
 178  		}
 179  		tab = tab[ifm.Msglen:]
 180  	}
 181  
 182  	return ifat, nil
 183  }
 184  
 185  // interfaceMulticastAddrTable returns addresses for a specific
 186  // interface.
 187  func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
 188  	return nil, nil
 189  }
 190