Source file
src/net/ipsock_posix.go
Documentation: net
1
2
3
4
5
6
7
8 package net
9
10 import (
11 "context"
12 "internal/poll"
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, ctrlFn func(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, ctrlFn)
143 }
144
145 func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
146 switch family {
147 case syscall.AF_INET:
148 if len(ip) == 0 {
149 ip = IPv4zero
150 }
151 ip4 := ip.To4()
152 if ip4 == nil {
153 return nil, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
154 }
155 sa := &syscall.SockaddrInet4{Port: port}
156 copy(sa.Addr[:], ip4)
157 return sa, nil
158 case syscall.AF_INET6:
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 nil, &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 return nil, &AddrError{Err: "invalid address family", Addr: ip.String()}
183 }
184
View as plain text