diff options
Diffstat (limited to 'src/pkg/net/iprawsock_posix.go')
-rw-r--r-- | src/pkg/net/iprawsock_posix.go | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go index caeeb4653..722853257 100644 --- a/src/pkg/net/iprawsock_posix.go +++ b/src/pkg/net/iprawsock_posix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin freebsd linux netbsd openbsd windows +// +build darwin dragonfly freebsd linux netbsd openbsd windows package net @@ -11,6 +11,18 @@ import ( "time" ) +// BUG(mikio): On every POSIX platform, reads from the "ip4" network +// using the ReadFrom or ReadFromIP method might not return a complete +// IPv4 packet, including its header, even if there is space +// available. This can occur even in cases where Read or ReadMsgIP +// could return a complete packet. For this reason, it is recommended +// that you do not uses these methods if it is important to receive a +// full packet. +// +// The Go 1 compatibliity guidelines make it impossible for us to +// change the behavior of these methods; use Read or ReadMsgIP +// instead. + func sockaddrToIP(sa syscall.Sockaddr) Addr { switch sa := sa.(type) { case *syscall.SockaddrInet4: @@ -39,14 +51,10 @@ func (a *IPAddr) isWildcard() bool { } func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) { - return ipToSockaddr(family, a.IP, 0, a.Zone) -} - -func (a *IPAddr) toAddr() sockaddr { - if a == nil { // nil *IPAddr - return nil // nil interface + if a == nil { + return nil, nil } - return a + return ipToSockaddr(family, a.IP, 0, a.Zone) } // IPConn is the implementation of the Conn and PacketConn interfaces @@ -125,6 +133,9 @@ func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) { if !c.ok() { return 0, syscall.EINVAL } + if addr == nil { + return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress} + } sa, err := addr.sockaddr(c.fd.family) if err != nil { return 0, &OpError{"write", c.fd.net, addr, err} @@ -151,6 +162,9 @@ func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error if !c.ok() { return 0, 0, syscall.EINVAL } + if addr == nil { + return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress} + } sa, err := addr.sockaddr(c.fd.family) if err != nil { return 0, 0, &OpError{"write", c.fd.net, addr, err} @@ -168,19 +182,19 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) { func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) { net, proto, err := parseNetwork(netProto) if err != nil { - return nil, err + return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err} } switch net { case "ip", "ip4", "ip6": default: - return nil, UnknownNetworkError(netProto) + return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: UnknownNetworkError(netProto)} } if raddr == nil { - return nil, &OpError{"dial", netProto, nil, errMissingAddress} + return nil, &OpError{Op: "dial", Net: netProto, Addr: nil, Err: errMissingAddress} } - fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_RAW, proto, "dial", sockaddrToIP) + fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial", sockaddrToIP) if err != nil { - return nil, err + return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err} } return newIPConn(fd), nil } @@ -192,16 +206,16 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) { net, proto, err := parseNetwork(netProto) if err != nil { - return nil, err + return nil, &OpError{Op: "dial", Net: netProto, Addr: laddr, Err: err} } switch net { case "ip", "ip4", "ip6": default: - return nil, UnknownNetworkError(netProto) + return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: UnknownNetworkError(netProto)} } - fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_RAW, proto, "listen", sockaddrToIP) + fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen", sockaddrToIP) if err != nil { - return nil, err + return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: err} } return newIPConn(fd), nil } |