interface_aix.go 4.4 KB

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