github.com/gidoBOSSftw5731/go/src@v0.0.0-20210226122457-d24b0edbf019/net/interface_aix.go (about) 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 := make([]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, uintptr(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_BROADCAST != 0 { 105 f |= FlagBroadcast 106 } 107 if rawFlags&syscall.IFF_LOOPBACK != 0 { 108 f |= FlagLoopback 109 } 110 if rawFlags&syscall.IFF_POINTOPOINT != 0 { 111 f |= FlagPointToPoint 112 } 113 if rawFlags&syscall.IFF_MULTICAST != 0 { 114 f |= FlagMulticast 115 } 116 return f 117 } 118 119 // If the ifi is nil, interfaceAddrTable returns addresses for all 120 // network interfaces. Otherwise it returns addresses for a specific 121 // interface. 122 func interfaceAddrTable(ifi *Interface) ([]Addr, error) { 123 tab, err := getIfList() 124 if err != nil { 125 return nil, err 126 } 127 128 var ifat []Addr 129 for len(tab) > 0 { 130 ifm := (*syscall.IfMsgHdr)(unsafe.Pointer(&tab[0])) 131 if ifm.Msglen == 0 { 132 break 133 } 134 if ifm.Type == syscall.RTM_NEWADDR { 135 if ifi == nil || ifi.Index == int(ifm.Index) { 136 mask := ifm.Addrs 137 off := uint(syscall.SizeofIfMsghdr) 138 139 var iprsa, nmrsa *syscall.RawSockaddr 140 for i := uint(0); i < _RTAX_MAX; i++ { 141 if mask&(1<<i) == 0 { 142 continue 143 } 144 rsa := (*syscall.RawSockaddr)(unsafe.Pointer(&tab[off])) 145 if i == _RTAX_NETMASK { 146 nmrsa = rsa 147 } 148 if i == _RTAX_IFA { 149 iprsa = rsa 150 } 151 off += (uint(rsa.Len) + 3) &^ 3 152 } 153 if iprsa != nil && nmrsa != nil { 154 var mask IPMask 155 var ip IP 156 157 switch iprsa.Family { 158 case syscall.AF_INET: 159 ipsa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(iprsa)) 160 nmsa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(nmrsa)) 161 ip = IPv4(ipsa.Addr[0], ipsa.Addr[1], ipsa.Addr[2], ipsa.Addr[3]) 162 mask = IPv4Mask(nmsa.Addr[0], nmsa.Addr[1], nmsa.Addr[2], nmsa.Addr[3]) 163 case syscall.AF_INET6: 164 ipsa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(iprsa)) 165 nmsa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(nmrsa)) 166 ip = make(IP, IPv6len) 167 copy(ip, ipsa.Addr[:]) 168 mask = make(IPMask, IPv6len) 169 copy(mask, nmsa.Addr[:]) 170 } 171 ifa := &IPNet{IP: ip, Mask: mask} 172 ifat = append(ifat, ifa) 173 } 174 } 175 } 176 tab = tab[ifm.Msglen:] 177 } 178 179 return ifat, nil 180 } 181 182 // interfaceMulticastAddrTable returns addresses for a specific 183 // interface. 184 func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) { 185 return nil, nil 186 }