Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(751)

Delta Between Two Patch Sets: src/pkg/net/tcpsock_posix.go

Issue 5650071: code review 5650071: net: avoid TCP self-connect (Closed)
Left Patch Set: Created 12 years, 1 month ago
Right Patch Set: diff -r 3242e3c73955 https://go.googlecode.com/hg/ Created 12 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/net/dial_test.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // +build darwin freebsd linux netbsd openbsd windows 5 // +build darwin freebsd linux netbsd openbsd windows
6 6
7 // TCP sockets 7 // TCP sockets
8 8
9 package net 9 package net
10 10
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 // Closing c does not affect f, and closing f does not affect c. 220 // Closing c does not affect f, and closing f does not affect c.
221 func (c *TCPConn) File() (f *os.File, err error) { return c.fd.dup() } 221 func (c *TCPConn) File() (f *os.File, err error) { return c.fd.dup() }
222 222
223 // DialTCP connects to the remote address raddr on the network net, 223 // DialTCP connects to the remote address raddr on the network net,
224 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used 224 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
225 // as the local address for the connection. 225 // as the local address for the connection.
226 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) { 226 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
227 if raddr == nil { 227 if raddr == nil {
228 return nil, &OpError{"dial", net, nil, errMissingAddress} 228 return nil, &OpError{"dial", net, nil, errMissingAddress}
229 } 229 }
230
230 fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.S OCK_STREAM, 0, "dial", sockaddrToTCP) 231 fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.S OCK_STREAM, 0, "dial", sockaddrToTCP)
232
233 // TCP has a rarely used mechanism called a 'simultaneous connection' in
234 // which Dial("tcp", addr1, addr2) run on the machine at addr1 can
235 // connect to a simultaneous Dial("tcp", addr2, addr1) run on the machin e
236 // at addr2, without either machine executing Listen. If laddr == nil,
237 // it means we want the kernel to pick an appropriate originating local
238 // address. Some Linux kernels cycle blindly through a fixed range of
239 // local ports, regardless of destination port. If a kernel happens to
240 // pick local port 50001 as the source for a Dial("tcp", "", "localhost: 50001"),
241 // then the Dial will succeed, having simultaneously connected to itself .
242 // This can only happen when we are letting the kernel pick a port (ladd r == nil)
243 // and when there is no listener for the destination address.
244 // It's hard to argue this is anything other than a kernel bug. If we
245 // see this happen, rather than expose the buggy effect to users, we
246 // close the fd and try again. If it happens twice more, we relent and
247 // use the result. See also:
248 // http://golang.org/issue/2690
249 // http://stackoverflow.com/questions/4949858/
250 for i := 0; i < 2 && err == nil && laddr == nil && selfConnect(fd); i++ {
251 fd.Close()
252 fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), sy scall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
253 }
254
231 if err != nil { 255 if err != nil {
232 return nil, err 256 return nil, err
233 } 257 }
234 return newTCPConn(fd), nil 258 return newTCPConn(fd), nil
259 }
260
261 func selfConnect(fd *netFD) bool {
262 l := fd.laddr.(*TCPAddr)
263 r := fd.raddr.(*TCPAddr)
264 return l.Port == r.Port && l.IP.Equal(r.IP)
235 } 265 }
236 266
237 // TCPListener is a TCP network listener. 267 // TCPListener is a TCP network listener.
238 // Clients should typically use variables of type Listener 268 // Clients should typically use variables of type Listener
239 // instead of assuming TCP. 269 // instead of assuming TCP.
240 type TCPListener struct { 270 type TCPListener struct {
241 fd *netFD 271 fd *netFD
242 } 272 }
243 273
244 // ListenTCP announces on the TCP address laddr and returns a TCP listener. 274 // ListenTCP announces on the TCP address laddr and returns a TCP listener.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 if l == nil || l.fd == nil { 331 if l == nil || l.fd == nil {
302 return os.EINVAL 332 return os.EINVAL
303 } 333 }
304 return setDeadline(l.fd, t) 334 return setDeadline(l.fd, t)
305 } 335 }
306 336
307 // File returns a copy of the underlying os.File, set to blocking mode. 337 // File returns a copy of the underlying os.File, set to blocking mode.
308 // It is the caller's responsibility to close f when finished. 338 // It is the caller's responsibility to close f when finished.
309 // Closing c does not affect f, and closing f does not affect c. 339 // Closing c does not affect f, and closing f does not affect c.
310 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() } 340 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b