Source file src/pkg/net/ipsock_posix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "internal/poll"
12 "runtime"
13 "syscall"
14 )
15
16
17
18
19
20
21
22
23
24
25
26 func (p *ipStackCapabilities) probe() {
27 s, err := sysSocket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
28 switch err {
29 case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
30 case nil:
31 poll.CloseFunc(s)
32 p.ipv4Enabled = true
33 }
34 var probes = []struct {
35 laddr TCPAddr
36 value int
37 }{
38
39 {laddr: TCPAddr{IP: ParseIP("::1")}, value: 1},
40
41 {laddr: TCPAddr{IP: IPv4(127, 0, 0, 1)}, value: 0},
42 }
43 switch runtime.GOOS {
44 case "dragonfly", "openbsd":
45
46
47
48 probes = probes[:1]
49 }
50 for i := range probes {
51 s, err := sysSocket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
52 if err != nil {
53 continue
54 }
55 defer poll.CloseFunc(s)
56 syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, probes[i].value)
57 sa, err := probes[i].laddr.sockaddr(syscall.AF_INET6)
58 if err != nil {
59 continue
60 }
61 if err := syscall.Bind(s, sa); err != nil {
62 continue
63 }
64 if i == 0 {
65 p.ipv6Enabled = true
66 } else {
67 p.ipv4MappedIPv6Enabled = true
68 }
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 func favoriteAddrFamily(network string, laddr, raddr sockaddr, mode string) (family int, ipv6only bool) {
112 switch network[len(network)-1] {
113 case '4':
114 return syscall.AF_INET, false
115 case '6':
116 return syscall.AF_INET6, true
117 }
118
119 if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
120 if supportsIPv4map() || !supportsIPv4() {
121 return syscall.AF_INET6, false
122 }
123 if laddr == nil {
124 return syscall.AF_INET, false
125 }
126 return laddr.family(), false
127 }
128
129 if (laddr == nil || laddr.family() == syscall.AF_INET) &&
130 (raddr == nil || raddr.family() == syscall.AF_INET) {
131 return syscall.AF_INET, false
132 }
133 return syscall.AF_INET6, false
134 }
135
136 func internetSocket(ctx context.Context, net string, laddr, raddr sockaddr, sotype, proto int, mode string, ctrlFn func(string, string, syscall.RawConn) error) (fd *netFD, err error) {
137 if (runtime.GOOS == "aix" || runtime.GOOS == "windows" || runtime.GOOS == "openbsd" || runtime.GOOS == "nacl") && mode == "dial" && raddr.isWildcard() {
138 raddr = raddr.toLocal(net)
139 }
140 family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
141 return socket(ctx, net, family, sotype, proto, ipv6only, laddr, raddr, ctrlFn)
142 }
143
144 func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
145 switch family {
146 case syscall.AF_INET:
147 if len(ip) == 0 {
148 ip = IPv4zero
149 }
150 ip4 := ip.To4()
151 if ip4 == nil {
152 return nil, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
153 }
154 sa := &syscall.SockaddrInet4{Port: port}
155 copy(sa.Addr[:], ip4)
156 return sa, nil
157 case syscall.AF_INET6:
158
159
160
161
162
163
164
165
166
167
168 if len(ip) == 0 || ip.Equal(IPv4zero) {
169 ip = IPv6zero
170 }
171
172
173 ip6 := ip.To16()
174 if ip6 == nil {
175 return nil, &AddrError{Err: "non-IPv6 address", Addr: ip.String()}
176 }
177 sa := &syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))}
178 copy(sa.Addr[:], ip6)
179 return sa, nil
180 }
181 return nil, &AddrError{Err: "invalid address family", Addr: ip.String()}
182 }
183
View as plain text