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