diff options
Diffstat (limited to 'src/pkg/net/iprawsock_posix.go')
-rw-r--r-- | src/pkg/net/iprawsock_posix.go | 160 |
1 files changed, 55 insertions, 105 deletions
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go index 35aceb223..c34ffeb12 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 openbsd windows +// +build darwin freebsd linux netbsd openbsd windows // (Raw) IP sockets @@ -10,12 +10,10 @@ package net import ( "os" - "sync" "syscall" + "time" ) -var onceReadProtocols sync.Once - func sockaddrToIP(sa syscall.Sockaddr) Addr { switch sa := sa.(type) { case *syscall.SockaddrInet4: @@ -36,7 +34,7 @@ func (a *IPAddr) family() int { return syscall.AF_INET6 } -func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) { +func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) { return ipToSockaddr(family, a.IP, 0) } @@ -59,14 +57,14 @@ func (c *IPConn) ok() bool { return c != nil && c.fd != nil } // Implementation of the Conn interface - see Conn for documentation. -// Read implements the net.Conn Read method. -func (c *IPConn) Read(b []byte) (n int, err os.Error) { - n, _, err = c.ReadFrom(b) - return +// Read implements the Conn Read method. +func (c *IPConn) Read(b []byte) (int, error) { + n, _, err := c.ReadFrom(b) + return n, err } -// Write implements the net.Conn Write method. -func (c *IPConn) Write(b []byte) (n int, err os.Error) { +// Write implements the Conn Write method. +func (c *IPConn) Write(b []byte) (int, error) { if !c.ok() { return 0, os.EINVAL } @@ -74,7 +72,7 @@ func (c *IPConn) Write(b []byte) (n int, err os.Error) { } // Close closes the IP connection. -func (c *IPConn) Close() os.Error { +func (c *IPConn) Close() error { if !c.ok() { return os.EINVAL } @@ -99,33 +97,33 @@ func (c *IPConn) RemoteAddr() Addr { return c.fd.raddr } -// SetTimeout implements the net.Conn SetTimeout method. -func (c *IPConn) SetTimeout(nsec int64) os.Error { +// SetDeadline implements the Conn SetDeadline method. +func (c *IPConn) SetDeadline(t time.Time) error { if !c.ok() { return os.EINVAL } - return setTimeout(c.fd, nsec) + return setDeadline(c.fd, t) } -// SetReadTimeout implements the net.Conn SetReadTimeout method. -func (c *IPConn) SetReadTimeout(nsec int64) os.Error { +// SetReadDeadline implements the Conn SetReadDeadline method. +func (c *IPConn) SetReadDeadline(t time.Time) error { if !c.ok() { return os.EINVAL } - return setReadTimeout(c.fd, nsec) + return setReadDeadline(c.fd, t) } -// SetWriteTimeout implements the net.Conn SetWriteTimeout method. -func (c *IPConn) SetWriteTimeout(nsec int64) os.Error { +// SetWriteDeadline implements the Conn SetWriteDeadline method. +func (c *IPConn) SetWriteDeadline(t time.Time) error { if !c.ok() { return os.EINVAL } - return setWriteTimeout(c.fd, nsec) + return setWriteDeadline(c.fd, t) } // SetReadBuffer sets the size of the operating system's // receive buffer associated with the connection. -func (c *IPConn) SetReadBuffer(bytes int) os.Error { +func (c *IPConn) SetReadBuffer(bytes int) error { if !c.ok() { return os.EINVAL } @@ -134,7 +132,7 @@ func (c *IPConn) SetReadBuffer(bytes int) os.Error { // SetWriteBuffer sets the size of the operating system's // transmit buffer associated with the connection. -func (c *IPConn) SetWriteBuffer(bytes int) os.Error { +func (c *IPConn) SetWriteBuffer(bytes int) error { if !c.ok() { return os.EINVAL } @@ -148,14 +146,15 @@ func (c *IPConn) SetWriteBuffer(bytes int) os.Error { // that was on the packet. // // ReadFromIP can be made to time out and return an error with -// Timeout() == true after a fixed time limit; see SetTimeout and -// SetReadTimeout. -func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err os.Error) { +// Timeout() == true after a fixed time limit; see SetDeadline and +// SetReadDeadline. +func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) { if !c.ok() { return 0, nil, os.EINVAL } // TODO(cw,rsc): consider using readv if we know the family // type to avoid the header trim/copy + var addr *IPAddr n, sa, err := c.fd.ReadFrom(b) switch sa := sa.(type) { case *syscall.SockaddrInet4: @@ -168,11 +167,11 @@ func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err os.Error) { case *syscall.SockaddrInet6: addr = &IPAddr{sa.Addr[0:]} } - return + return n, addr, err } -// ReadFrom implements the net.PacketConn ReadFrom method. -func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { +// ReadFrom implements the PacketConn ReadFrom method. +func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) { if !c.ok() { return 0, nil, os.EINVAL } @@ -184,81 +183,37 @@ func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { // // WriteToIP can be made to time out and return // an error with Timeout() == true after a fixed time limit; -// see SetTimeout and SetWriteTimeout. +// see SetDeadline and SetWriteDeadline. // On packet-oriented connections, write timeouts are rare. -func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err os.Error) { +func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) { if !c.ok() { return 0, os.EINVAL } - sa, err1 := addr.sockaddr(c.fd.family) - if err1 != nil { - return 0, &OpError{Op: "write", Net: "ip", Addr: addr, Error: err1} + sa, err := addr.sockaddr(c.fd.family) + if err != nil { + return 0, &OpError{"write", c.fd.net, addr, err} } return c.fd.WriteTo(b, sa) } -// WriteTo implements the net.PacketConn WriteTo method. -func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { +// WriteTo implements the PacketConn WriteTo method. +func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) { if !c.ok() { return 0, os.EINVAL } a, ok := addr.(*IPAddr) if !ok { - return 0, &OpError{"writeto", "ip", addr, os.EINVAL} + return 0, &OpError{"write", c.fd.net, addr, os.EINVAL} } return c.WriteToIP(b, a) } -var protocols map[string]int - -func readProtocols() { - protocols = make(map[string]int) - if file, err := open("/etc/protocols"); err == nil { - for line, ok := file.readLine(); ok; line, ok = file.readLine() { - // tcp 6 TCP # transmission control protocol - if i := byteIndex(line, '#'); i >= 0 { - line = line[0:i] - } - f := getFields(line) - if len(f) < 2 { - continue - } - if proto, _, ok := dtoi(f[1], 0); ok { - protocols[f[0]] = proto - for _, alias := range f[2:] { - protocols[alias] = proto - } - } - } - file.close() - } -} - -func splitNetProto(netProto string) (net string, proto int, err os.Error) { - onceReadProtocols.Do(readProtocols) - i := last(netProto, ':') - if i < 0 { // no colon - return "", 0, os.NewError("no IP protocol specified") - } - net = netProto[0:i] - protostr := netProto[i+1:] - proto, i, ok := dtoi(protostr, 0) - if !ok || i != len(protostr) { - // lookup by name - proto, ok = protocols[protostr] - if ok { - return - } - } - return -} - -// DialIP connects to the remote address raddr on the network net, -// which must be "ip", "ip4", or "ip6". -func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) { - net, proto, err := splitNetProto(netProto) +// DialIP connects to the remote address raddr on the network protocol netProto, +// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name. +func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) { + net, proto, err := parseDialNetwork(netProto) if err != nil { - return + return nil, err } switch net { case "ip", "ip4", "ip6": @@ -266,11 +221,11 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) { return nil, UnknownNetworkError(net) } if raddr == nil { - return nil, &OpError{"dial", "ip", nil, errMissingAddress} + return nil, &OpError{"dial", netProto, nil, errMissingAddress} } - fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP) - if e != nil { - return nil, e + fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP) + if err != nil { + return nil, err } return newIPConn(fd), nil } @@ -279,29 +234,24 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) { // local address laddr. The returned connection c's ReadFrom // and WriteTo methods can be used to receive and send IP // packets with per-packet addressing. -func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err os.Error) { - net, proto, err := splitNetProto(netProto) +func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) { + net, proto, err := parseDialNetwork(netProto) if err != nil { - return + return nil, err } switch net { case "ip", "ip4", "ip6": default: return nil, UnknownNetworkError(net) } - fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "dial", sockaddrToIP) - if e != nil { - return nil, e + fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "listen", sockaddrToIP) + if err != nil { + return nil, err } return newIPConn(fd), nil } -// BindToDevice binds an IPConn to a network interface. -func (c *IPConn) BindToDevice(device string) os.Error { - if !c.ok() { - return os.EINVAL - } - c.fd.incref() - defer c.fd.decref() - return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device)) -} +// File returns a copy of the underlying os.File, set to blocking mode. +// It is the caller's responsibility to close f when finished. +// Closing c does not affect f, and closing f does not affect c. +func (c *IPConn) File() (f *os.File, err error) { return c.fd.dup() } |