summaryrefslogtreecommitdiff
path: root/libgo/go/net/iprawsock.go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
commitadb0401dac41c81571722312d4586b2693f95aa6 (patch)
treeea2b52e3c258d6b6d9356977c683c7f72a4a5fd5 /libgo/go/net/iprawsock.go
parent5548ca3540bccbc908a45942896d635ea5f1c23f (diff)
Update Go library to r60.
From-SVN: r178910
Diffstat (limited to 'libgo/go/net/iprawsock.go')
-rw-r--r--libgo/go/net/iprawsock.go317
1 files changed, 14 insertions, 303 deletions
diff --git a/libgo/go/net/iprawsock.go b/libgo/go/net/iprawsock.go
index 5be6fe4e0b9..662b9f57bd3 100644
--- a/libgo/go/net/iprawsock.go
+++ b/libgo/go/net/iprawsock.go
@@ -8,22 +8,8 @@ package net
import (
"os"
- "sync"
- "syscall"
)
-var onceReadProtocols sync.Once
-
-func sockaddrToIP(sa syscall.Sockaddr) Addr {
- switch sa := sa.(type) {
- case *syscall.SockaddrInet4:
- return &IPAddr{sa.Addr[0:]}
- case *syscall.SockaddrInet6:
- return &IPAddr{sa.Addr[0:]}
- }
- return nil
-}
-
// IPAddr represents the address of a IP end point.
type IPAddr struct {
IP IP
@@ -39,320 +25,45 @@ func (a *IPAddr) String() string {
return a.IP.String()
}
-func (a *IPAddr) family() int {
- if a == nil || len(a.IP) <= 4 {
- return syscall.AF_INET
- }
- if ip := a.IP.To4(); ip != nil {
- return syscall.AF_INET
- }
- return syscall.AF_INET6
-}
-
-func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) {
- return ipToSockaddr(family, a.IP, 0)
-}
-
-func (a *IPAddr) toAddr() sockaddr {
- if a == nil { // nil *IPAddr
- return nil // nil interface
- }
- return a
-}
-
// ResolveIPAddr parses addr as a IP address and resolves domain
-// names to numeric addresses. A literal IPv6 host address must be
+// names to numeric addresses on the network net, which must be
+// "ip", "ip4" or "ip6". A literal IPv6 host address must be
// enclosed in square brackets, as in "[::]".
-func ResolveIPAddr(addr string) (*IPAddr, os.Error) {
- ip, err := hostToIP(addr)
+func ResolveIPAddr(net, addr string) (*IPAddr, os.Error) {
+ ip, err := hostToIP(net, addr)
if err != nil {
return nil, err
}
return &IPAddr{ip}, nil
}
-// IPConn is the implementation of the Conn and PacketConn
-// interfaces for IP network connections.
-type IPConn struct {
- fd *netFD
-}
-
-func newIPConn(fd *netFD) *IPConn { return &IPConn{fd} }
-
-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
-}
-
-// Write implements the net.Conn Write method.
-func (c *IPConn) Write(b []byte) (n int, err os.Error) {
- if !c.ok() {
- return 0, os.EINVAL
- }
- return c.fd.Write(b)
-}
-
-// Close closes the IP connection.
-func (c *IPConn) Close() os.Error {
- if !c.ok() {
- return os.EINVAL
- }
- err := c.fd.Close()
- c.fd = nil
- return err
-}
-
-// LocalAddr returns the local network address.
-func (c *IPConn) LocalAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.laddr
-}
-
-// RemoteAddr returns the remote network address, a *IPAddr.
-func (c *IPConn) RemoteAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.raddr
-}
-
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *IPConn) SetTimeout(nsec int64) os.Error {
- if !c.ok() {
- return os.EINVAL
- }
- return setTimeout(c.fd, nsec)
-}
-
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *IPConn) SetReadTimeout(nsec int64) os.Error {
- if !c.ok() {
- return os.EINVAL
- }
- return setReadTimeout(c.fd, nsec)
-}
-
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *IPConn) SetWriteTimeout(nsec int64) os.Error {
- if !c.ok() {
- return os.EINVAL
- }
- return setWriteTimeout(c.fd, nsec)
-}
-
-// SetReadBuffer sets the size of the operating system's
-// receive buffer associated with the connection.
-func (c *IPConn) SetReadBuffer(bytes int) os.Error {
- if !c.ok() {
- return os.EINVAL
- }
- return setReadBuffer(c.fd, bytes)
-}
-
-// SetWriteBuffer sets the size of the operating system's
-// transmit buffer associated with the connection.
-func (c *IPConn) SetWriteBuffer(bytes int) os.Error {
- if !c.ok() {
- return os.EINVAL
- }
- return setWriteBuffer(c.fd, bytes)
-}
-
-// IP-specific methods.
-
-// ReadFromIP reads a IP packet from c, copying the payload into b.
-// It returns the number of bytes copied into b and the return address
-// 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) {
- 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
- n, sa, err := c.fd.ReadFrom(b)
- switch sa := sa.(type) {
- case *syscall.SockaddrInet4:
- addr = &IPAddr{sa.Addr[0:]}
- if len(b) >= 4 { // discard ipv4 header
- hsize := (int(b[0]) & 0xf) * 4
- copy(b, b[hsize:])
- n -= hsize
- }
- case *syscall.SockaddrInet6:
- addr = &IPAddr{sa.Addr[0:]}
- }
- return
-}
-
-// ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
- if !c.ok() {
- return 0, nil, os.EINVAL
- }
- n, uaddr, err := c.ReadFromIP(b)
- return n, uaddr.toAddr(), err
-}
-
-// WriteToIP writes a IP packet to addr via c, copying the payload from b.
-//
-// WriteToIP can be made to time out and return
-// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
-// On packet-oriented connections, write timeouts are rare.
-func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err os.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}
- }
- 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) {
- if !c.ok() {
- return 0, os.EINVAL
- }
- a, ok := addr.(*IPAddr)
- if !ok {
- return 0, &OpError{"writeto", "ip", addr, os.EINVAL}
- }
- return c.WriteToIP(b, a)
-}
-
// Convert "host" into IP address.
-func hostToIP(host string) (ip IP, err os.Error) {
+func hostToIP(net, host string) (ip IP, err os.Error) {
var addr IP
// Try as an IP address.
addr = ParseIP(host)
if addr == nil {
+ filter := anyaddr
+ if net != "" && net[len(net)-1] == '4' {
+ filter = ipv4only
+ }
+ if net != "" && net[len(net)-1] == '6' {
+ filter = ipv6only
+ }
// Not an IP address. Try as a DNS name.
addrs, err1 := LookupHost(host)
if err1 != nil {
err = err1
goto Error
}
- addr = firstSupportedAddr(anyaddr, addrs)
+ addr = firstFavoriteAddr(filter, addrs)
if addr == nil {
// should not happen
- err = &AddrError{"LookupHost returned invalid address", addrs[0]}
+ err = &AddrError{"LookupHost returned no suitable address", addrs[0]}
goto Error
}
}
-
return addr, nil
-
Error:
return nil, err
}
-
-
-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 netProtoSplit(netProto string) (net string, proto int, err os.Error) {
- onceReadProtocols.Do(readProtocols)
- i := last(netProto, ':')
- if i < 0 { // no colon
- return "", 0, os.ErrorString("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 := netProtoSplit(netProto)
- if err != nil {
- return
- }
- switch net {
- case "ip", "ip4", "ip6":
- default:
- return nil, UnknownNetworkError(net)
- }
- if raddr == nil {
- return nil, &OpError{"dial", "ip", nil, errMissingAddress}
- }
- fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
- if e != nil {
- return nil, e
- }
- return newIPConn(fd), nil
-}
-
-// ListenIP listens for incoming IP packets addressed to the
-// 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 := netProtoSplit(netProto)
- if err != nil {
- return
- }
- 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
- }
- 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))
-}