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