X Tutup
Skip to content

Commit f00362b

Browse files
apilloudcixtor
authored andcommitted
net: LookupHost and Resolve{TCP,UDP,IP}Addr should use zone from getaddrinfo
The unix and windows getaddrinfo calls return a zone with IPv6 addresses. IPv6 link-local addresses returned are only valid on the given zone. When the zone is dropped, connections to the address will fail. This patch replaces IP with IPAddr in several internal resolver functions, and plumbs through the zone. Change-Id: Ifea891654f586f15b76988464f82e04a42ccff6d Reviewed-on: https://go-review.googlesource.com/5851 Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
1 parent cbc854a commit f00362b

File tree

10 files changed

+132
-119
lines changed

10 files changed

+132
-119
lines changed

src/net/cgo_stub.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func cgoLookupPort(network, service string) (port int, err error, completed bool
1616
return 0, nil, false
1717
}
1818

19-
func cgoLookupIP(name string) (addrs []IP, err error, completed bool) {
19+
func cgoLookupIP(name string) (addrs []IPAddr, err error, completed bool) {
2020
return nil, nil, false
2121
}
2222

src/net/cgo_unix.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func cgoLookupPort(net, service string) (port int, err error, completed bool) {
8181
return 0, &AddrError{"unknown port", net + "/" + service}, true
8282
}
8383

84-
func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, completed bool) {
84+
func cgoLookupIPCNAME(name string) (addrs []IPAddr, cname string, err error, completed bool) {
8585
acquireThread()
8686
defer releaseThread()
8787

@@ -135,16 +135,18 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, complet
135135
continue
136136
case C.AF_INET:
137137
sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
138-
addrs = append(addrs, copyIP(sa.Addr[:]))
138+
addr := IPAddr{IP: copyIP(sa.Addr[:])}
139+
addrs = append(addrs, addr)
139140
case C.AF_INET6:
140141
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
141-
addrs = append(addrs, copyIP(sa.Addr[:]))
142+
addr := IPAddr{IP: copyIP(sa.Addr[:]), Zone: zoneToString(int(sa.Scope_id))}
143+
addrs = append(addrs, addr)
142144
}
143145
}
144146
return addrs, cname, nil, true
145147
}
146148

147-
func cgoLookupIP(name string) (addrs []IP, err error, completed bool) {
149+
func cgoLookupIP(name string) (addrs []IPAddr, err error, completed bool) {
148150
addrs, _, err, completed = cgoLookupIPCNAME(name)
149151
return
150152
}

src/net/dnsclient_unix.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,13 +361,15 @@ func goLookupHost(name string) (addrs []string, err error) {
361361
// Normally we let cgo use the C library resolver instead of
362362
// depending on our lookup code, so that Go and C get the same
363363
// answers.
364-
func goLookupIP(name string) (addrs []IP, err error) {
364+
func goLookupIP(name string) (addrs []IPAddr, err error) {
365365
// Use entries from /etc/hosts if possible.
366366
haddrs := lookupStaticHost(name)
367367
if len(haddrs) > 0 {
368368
for _, haddr := range haddrs {
369+
haddr, zone := splitHostZone(haddr)
369370
if ip := ParseIP(haddr); ip != nil {
370-
addrs = append(addrs, ip)
371+
addr := IPAddr{IP: ip, Zone: zone}
372+
addrs = append(addrs, addr)
371373
}
372374
}
373375
if len(addrs) > 0 {
@@ -396,9 +398,15 @@ func goLookupIP(name string) (addrs []IP, err error) {
396398
}
397399
switch racer.qtype {
398400
case dnsTypeA:
399-
addrs = append(addrs, convertRR_A(racer.rrs)...)
401+
for _, ip := range convertRR_A(racer.rrs) {
402+
addr := IPAddr{IP: ip}
403+
addrs = append(addrs, addr)
404+
}
400405
case dnsTypeAAAA:
401-
addrs = append(addrs, convertRR_AAAA(racer.rrs)...)
406+
for _, ip := range convertRR_AAAA(racer.rrs) {
407+
addr := IPAddr{IP: ip}
408+
addrs = append(addrs, addr)
409+
}
402410
}
403411
}
404412
if len(addrs) == 0 && lastErr != nil {

src/net/ipsock.go

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ var errNoSuitableAddress = errors.New("no suitable address found")
6464
// implement the netaddr interface. Known filters are nil, ipv4only
6565
// and ipv6only. It returns any address when filter is nil. The result
6666
// contains at least one address when error is nil.
67-
func firstFavoriteAddr(filter func(IP) IP, ips []IP, inetaddr func(IP) netaddr) (netaddr, error) {
67+
func firstFavoriteAddr(filter func(IPAddr) bool, ips []IPAddr, inetaddr func(IPAddr) netaddr) (netaddr, error) {
6868
if filter != nil {
6969
return firstSupportedAddr(filter, ips, inetaddr)
7070
}
@@ -79,14 +79,14 @@ func firstFavoriteAddr(filter func(IP) IP, ips []IP, inetaddr func(IP) netaddr)
7979
// possible. This is especially relevant if localhost
8080
// resolves to [ipv6-localhost, ipv4-localhost]. Too
8181
// much code assumes localhost == ipv4-localhost.
82-
if ip4 := ipv4only(ip); ip4 != nil && !ipv4 {
83-
list = append(list, inetaddr(ip4))
82+
if ipv4only(ip) && !ipv4 {
83+
list = append(list, inetaddr(ip))
8484
ipv4 = true
8585
if ipv6 {
8686
swap = true
8787
}
88-
} else if ip6 := ipv6only(ip); ip6 != nil && !ipv6 {
89-
list = append(list, inetaddr(ip6))
88+
} else if ipv6only(ip) && !ipv6 {
89+
list = append(list, inetaddr(ip))
9090
ipv6 = true
9191
}
9292
if ipv4 && ipv6 {
@@ -106,33 +106,25 @@ func firstFavoriteAddr(filter func(IP) IP, ips []IP, inetaddr func(IP) netaddr)
106106
}
107107
}
108108

109-
func firstSupportedAddr(filter func(IP) IP, ips []IP, inetaddr func(IP) netaddr) (netaddr, error) {
109+
func firstSupportedAddr(filter func(IPAddr) bool, ips []IPAddr, inetaddr func(IPAddr) netaddr) (netaddr, error) {
110110
for _, ip := range ips {
111-
if ip := filter(ip); ip != nil {
111+
if filter(ip) {
112112
return inetaddr(ip), nil
113113
}
114114
}
115115
return nil, errNoSuitableAddress
116116
}
117117

118-
// ipv4only returns IPv4 addresses that we can use with the kernel's
119-
// IPv4 addressing modes. If ip is an IPv4 address, ipv4only returns ip.
120-
// Otherwise it returns nil.
121-
func ipv4only(ip IP) IP {
122-
if supportsIPv4 && ip.To4() != nil {
123-
return ip
124-
}
125-
return nil
118+
// ipv4only reports whether the kernel supports IPv4 addressing mode
119+
// and addr is an IPv4 address.
120+
func ipv4only(addr IPAddr) bool {
121+
return supportsIPv4 && addr.IP.To4() != nil
126122
}
127123

128-
// ipv6only returns IPv6 addresses that we can use with the kernel's
129-
// IPv6 addressing modes. It returns IPv4-mapped IPv6 addresses as
130-
// nils and returns other IPv6 address types as IPv6 addresses.
131-
func ipv6only(ip IP) IP {
132-
if supportsIPv6 && len(ip) == IPv6len && ip.To4() == nil {
133-
return ip
134-
}
135-
return nil
124+
// ipv6only reports whether the kernel supports IPv6 addressing mode
125+
// and addr is an IPv6 address except IPv4-mapped IPv6 address.
126+
func ipv6only(addr IPAddr) bool {
127+
return supportsIPv6 && len(addr.IP) == IPv6len && addr.IP.To4() == nil
136128
}
137129

138130
// SplitHostPort splits a network address of the form "host:port",
@@ -236,9 +228,9 @@ func JoinHostPort(host, port string) string {
236228
// address when error is nil.
237229
func resolveInternetAddr(net, addr string, deadline time.Time) (netaddr, error) {
238230
var (
239-
err error
240-
host, port, zone string
241-
portnum int
231+
err error
232+
host, port string
233+
portnum int
242234
)
243235
switch net {
244236
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
@@ -257,40 +249,40 @@ func resolveInternetAddr(net, addr string, deadline time.Time) (netaddr, error)
257249
default:
258250
return nil, UnknownNetworkError(net)
259251
}
260-
inetaddr := func(ip IP) netaddr {
252+
inetaddr := func(ip IPAddr) netaddr {
261253
switch net {
262254
case "tcp", "tcp4", "tcp6":
263-
return &TCPAddr{IP: ip, Port: portnum, Zone: zone}
255+
return &TCPAddr{IP: ip.IP, Port: portnum, Zone: ip.Zone}
264256
case "udp", "udp4", "udp6":
265-
return &UDPAddr{IP: ip, Port: portnum, Zone: zone}
257+
return &UDPAddr{IP: ip.IP, Port: portnum, Zone: ip.Zone}
266258
case "ip", "ip4", "ip6":
267-
return &IPAddr{IP: ip, Zone: zone}
259+
return &IPAddr{IP: ip.IP, Zone: ip.Zone}
268260
default:
269261
panic("unexpected network: " + net)
270262
}
271263
}
272264
if host == "" {
273-
return inetaddr(nil), nil
265+
return inetaddr(IPAddr{}), nil
274266
}
275267
// Try as a literal IP address.
276268
var ip IP
277269
if ip = parseIPv4(host); ip != nil {
278-
return inetaddr(ip), nil
270+
return inetaddr(IPAddr{IP: ip}), nil
279271
}
272+
var zone string
280273
if ip, zone = parseIPv6(host, true); ip != nil {
281-
return inetaddr(ip), nil
274+
return inetaddr(IPAddr{IP: ip, Zone: zone}), nil
282275
}
283276
// Try as a DNS name.
284-
host, zone = splitHostZone(host)
285277
ips, err := lookupIPDeadline(host, deadline)
286278
if err != nil {
287279
return nil, err
288280
}
289-
var filter func(IP) IP
281+
var filter func(IPAddr) bool
290282
if net != "" && net[len(net)-1] == '4' {
291283
filter = ipv4only
292284
}
293-
if net != "" && net[len(net)-1] == '6' || zone != "" {
285+
if net != "" && net[len(net)-1] == '6' {
294286
filter = ipv6only
295287
}
296288
return firstFavoriteAddr(filter, ips, inetaddr)

0 commit comments

Comments
 (0)
X Tutup