Source file
src/net/ipsock_posix.go
Documentation: net
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 )
16
17
18
19
20
21
22
23
24
25
26
27 func (p *ipStackCapabilities) probe() {
28 switch runtime.GOOS {
29 case "js", "wasip1":
30
31 p.ipv4Enabled = true
32 p.ipv6Enabled = true
33 p.ipv4MappedIPv6Enabled = true
34 return
35 }
36
37 s, err := sysSocket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
38 switch err {
39 case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
40 case nil:
41 poll.CloseFunc(s)
42 p.ipv4Enabled = true
43 }
44 var probes = []struct {
45 laddr TCPAddr
46 value int
47 }{
48
49 {laddr: TCPAddr{IP: ParseIP("::1")}, value: 1},
50
51 {laddr: TCPAddr{IP: IPv4(127, 0, 0, 1)}, value: 0},
52 }
53 switch runtime.GOOS {
54 case "dragonfly", "openbsd":
55
56
57
58 probes = probes[:1]
59 }
60 for i := range probes {
61 s, err := sysSocket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
62 if err != nil {
63 continue
64 }
65 defer poll.CloseFunc(s)
66 syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, probes[i].value)
67 sa, err := probes[i].laddr.sockaddr(syscall.AF_INET6)
68 if err != nil {
69 continue
70 }
71 if err := syscall.Bind(s, sa); err != nil {
72 continue
73 }
74 if i == 0 {
75 p.ipv6Enabled = true
76 } else {
77 p.ipv4MappedIPv6Enabled = true
78 }
79 }
80 }
81
82
83
84
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 func favoriteAddrFamily(network string, laddr, raddr sockaddr, mode string) (family int, ipv6only bool) {
122 switch network[len(network)-1] {
123 case '4':
124 return syscall.AF_INET, false
125 case '6':
126 return syscall.AF_INET6, true
127 }
128
129 if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
130 if supportsIPv4map() || !supportsIPv4() {
131 return syscall.AF_INET6, false
132 }
133 if laddr == nil {
134 return syscall.AF_INET, false
135 }
136 return laddr.family(), false
137 }
138
139 if (laddr == nil || laddr.family() == syscall.AF_INET) &&
140 (raddr == nil || raddr.family() == syscall.AF_INET) {
141 return syscall.AF_INET, false
142 }
143 return syscall.AF_INET6, false
144 }
145
146 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) {
147 switch runtime.GOOS {
148 case "aix", "windows", "openbsd", "js", "wasip1":
149 if mode == "dial" && raddr.isWildcard() {
150 raddr = raddr.toLocal(net)
151 }
152 }
153 family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
154 return socket(ctx, net, family, sotype, proto, ipv6only, laddr, raddr, ctrlCtxFn)
155 }
156
157 func ipToSockaddrInet4(ip IP, port int) (syscall.SockaddrInet4, error) {
158 if len(ip) == 0 {
159 ip = IPv4zero
160 }
161 ip4 := ip.To4()
162 if ip4 == nil {
163 return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
164 }
165 sa := syscall.SockaddrInet4{Port: port}
166 copy(sa.Addr[:], ip4)
167 return sa, nil
168 }
169
170 func ipToSockaddrInet6(ip IP, port int, zone string) (syscall.SockaddrInet6, error) {
171
172
173
174
175
176
177
178
179
180
181 if len(ip) == 0 || ip.Equal(IPv4zero) {
182 ip = IPv6zero
183 }
184
185
186 ip6 := ip.To16()
187 if ip6 == nil {
188 return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: ip.String()}
189 }
190 sa := syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))}
191 copy(sa.Addr[:], ip6)
192 return sa, nil
193 }
194
195 func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
196 switch family {
197 case syscall.AF_INET:
198 sa, err := ipToSockaddrInet4(ip, port)
199 if err != nil {
200 return nil, err
201 }
202 return &sa, nil
203 case syscall.AF_INET6:
204 sa, err := ipToSockaddrInet6(ip, port, zone)
205 if err != nil {
206 return nil, err
207 }
208 return &sa, nil
209 }
210 return nil, &AddrError{Err: "invalid address family", Addr: ip.String()}
211 }
212
213 func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) {
214
215
216 addr := ap.Addr()
217 if !addr.Is4() {
218 return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: addr.String()}
219 }
220 sa := syscall.SockaddrInet4{
221 Addr: addr.As4(),
222 Port: int(ap.Port()),
223 }
224 return sa, nil
225 }
226
227 func addrPortToSockaddrInet6(ap netip.AddrPort) (syscall.SockaddrInet6, error) {
228
229
230
231
232
233
234 addr := ap.Addr()
235 if !addr.IsValid() {
236 return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: addr.String()}
237 }
238 sa := syscall.SockaddrInet6{
239 Addr: addr.As16(),
240 Port: int(ap.Port()),
241 ZoneId: uint32(zoneCache.index(addr.Zone())),
242 }
243 return sa, nil
244 }
245
View as plain text