Source file
src/net/ipsock_posix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "internal/poll"
12 "net/netip"
13 "runtime"
14 "syscall"
15 _ "unsafe"
16 )
17
18
19
20
21
22
23
24
25
26
27
28 func (p *ipStackCapabilities) probe() {
29 switch runtime.GOOS {
30 case "js", "wasip1":
31
32 p.ipv4Enabled = true
33 p.ipv6Enabled = true
34 p.ipv4MappedIPv6Enabled = true
35 return
36 }
37
38 s, err := sysSocket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
39 switch err {
40 case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
41 case nil:
42 poll.CloseFunc(s)
43 p.ipv4Enabled = true
44 }
45 var probes = []struct {
46 laddr TCPAddr
47 value int
48 }{
49
50 {laddr: TCPAddr{IP: ParseIP("::1")}, value: 1},
51
52 {laddr: TCPAddr{IP: IPv4(127, 0, 0, 1)}, value: 0},
53 }
54 switch runtime.GOOS {
55 case "dragonfly", "openbsd":
56
57
58
59 probes = probes[:1]
60 }
61 for i := range probes {
62 s, err := sysSocket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
63 if err != nil {
64 continue
65 }
66 defer poll.CloseFunc(s)
67 syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, probes[i].value)
68 sa, err := probes[i].laddr.sockaddr(syscall.AF_INET6)
69 if err != nil {
70 continue
71 }
72 if err := syscall.Bind(s, sa); err != nil {
73
74
75
76
77 if err != syscall.EPERM && err != syscall.EACCES {
78 continue
79 }
80 }
81 if i == 0 {
82 p.ipv6Enabled = true
83 } else {
84 p.ipv4MappedIPv6Enabled = true
85 }
86 }
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 func favoriteAddrFamily(network string, laddr, raddr sockaddr, mode string) (family int, ipv6only bool) {
141 switch network[len(network)-1] {
142 case '4':
143 return syscall.AF_INET, false
144 case '6':
145 return syscall.AF_INET6, true
146 }
147
148 if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
149 if supportsIPv4map() || !supportsIPv4() {
150 return syscall.AF_INET6, false
151 }
152 if laddr == nil {
153 return syscall.AF_INET, false
154 }
155 return laddr.family(), false
156 }
157
158 if (laddr == nil || laddr.family() == syscall.AF_INET) &&
159 (raddr == nil || raddr.family() == syscall.AF_INET) {
160 return syscall.AF_INET, false
161 }
162 return syscall.AF_INET6, false
163 }
164
165 func internetSocket(ctx context.Context, net string, laddr, raddr sockaddr, sotype, proto int, mode string, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) (fd *netFD, err error) {
166 switch runtime.GOOS {
167 case "aix", "freebsd", "windows", "openbsd", "js", "wasip1":
168 if mode == "dial" && raddr.isWildcard() {
169 raddr = raddr.toLocal(net)
170 }
171 }
172 family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
173 return socket(ctx, net, family, sotype, proto, ipv6only, laddr, raddr, ctrlCtxFn)
174 }
175
176 func ipToSockaddrInet4(ip IP, port int) (syscall.SockaddrInet4, error) {
177 if len(ip) == 0 {
178 ip = IPv4zero
179 }
180 ip4 := ip.To4()
181 if ip4 == nil {
182 return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
183 }
184 sa := syscall.SockaddrInet4{Port: port}
185 copy(sa.Addr[:], ip4)
186 return sa, nil
187 }
188
189 func ipToSockaddrInet6(ip IP, port int, zone string) (syscall.SockaddrInet6, error) {
190
191
192
193
194
195
196
197
198
199
200 if len(ip) == 0 || ip.Equal(IPv4zero) {
201 ip = IPv6zero
202 }
203
204
205 ip6 := ip.To16()
206 if ip6 == nil {
207 return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: ip.String()}
208 }
209 sa := syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))}
210 copy(sa.Addr[:], ip6)
211 return sa, nil
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225 func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
226 switch family {
227 case syscall.AF_INET:
228 sa, err := ipToSockaddrInet4(ip, port)
229 if err != nil {
230 return nil, err
231 }
232 return &sa, nil
233 case syscall.AF_INET6:
234 sa, err := ipToSockaddrInet6(ip, port, zone)
235 if err != nil {
236 return nil, err
237 }
238 return &sa, nil
239 }
240 return nil, &AddrError{Err: "invalid address family", Addr: ip.String()}
241 }
242
243 func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) {
244
245
246
247
248
249
250 addr := ap.Addr()
251 if !addr.Is4() && !addr.Is4In6() {
252 return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: addr.String()}
253 }
254 sa := syscall.SockaddrInet4{
255 Addr: addr.As4(),
256 Port: int(ap.Port()),
257 }
258 return sa, nil
259 }
260
261 func addrPortToSockaddrInet6(ap netip.AddrPort) (syscall.SockaddrInet6, error) {
262
263
264
265
266
267
268 addr := ap.Addr()
269 sa := syscall.SockaddrInet6{
270 Addr: addr.As16(),
271 Port: int(ap.Port()),
272 ZoneId: uint32(zoneCache.index(addr.Zone())),
273 }
274 return sa, nil
275 }
276
View as plain text