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