...

Source file src/pkg/net/iprawsock.go

     1	// Copyright 2010 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package net
     6	
     7	import (
     8		"context"
     9		"syscall"
    10	)
    11	
    12	// BUG(mikio): On every POSIX platform, reads from the "ip4" network
    13	// using the ReadFrom or ReadFromIP method might not return a complete
    14	// IPv4 packet, including its header, even if there is space
    15	// available. This can occur even in cases where Read or ReadMsgIP
    16	// could return a complete packet. For this reason, it is recommended
    17	// that you do not use these methods if it is important to receive a
    18	// full packet.
    19	//
    20	// The Go 1 compatibility guidelines make it impossible for us to
    21	// change the behavior of these methods; use Read or ReadMsgIP
    22	// instead.
    23	
    24	// BUG(mikio): On JS, NaCl and Plan 9, methods and functions related
    25	// to IPConn are not implemented.
    26	
    27	// BUG(mikio): On Windows, the File method of IPConn is not
    28	// implemented.
    29	
    30	// IPAddr represents the address of an IP end point.
    31	type IPAddr struct {
    32		IP   IP
    33		Zone string // IPv6 scoped addressing zone
    34	}
    35	
    36	// Network returns the address's network name, "ip".
    37	func (a *IPAddr) Network() string { return "ip" }
    38	
    39	func (a *IPAddr) String() string {
    40		if a == nil {
    41			return "<nil>"
    42		}
    43		ip := ipEmptyString(a.IP)
    44		if a.Zone != "" {
    45			return ip + "%" + a.Zone
    46		}
    47		return ip
    48	}
    49	
    50	func (a *IPAddr) isWildcard() bool {
    51		if a == nil || a.IP == nil {
    52			return true
    53		}
    54		return a.IP.IsUnspecified()
    55	}
    56	
    57	func (a *IPAddr) opAddr() Addr {
    58		if a == nil {
    59			return nil
    60		}
    61		return a
    62	}
    63	
    64	// ResolveIPAddr returns an address of IP end point.
    65	//
    66	// The network must be an IP network name.
    67	//
    68	// If the host in the address parameter is not a literal IP address,
    69	// ResolveIPAddr resolves the address to an address of IP end point.
    70	// Otherwise, it parses the address as a literal IP address.
    71	// The address parameter can use a host name, but this is not
    72	// recommended, because it will return at most one of the host name's
    73	// IP addresses.
    74	//
    75	// See func Dial for a description of the network and address
    76	// parameters.
    77	func ResolveIPAddr(network, address string) (*IPAddr, error) {
    78		if network == "" { // a hint wildcard for Go 1.0 undocumented behavior
    79			network = "ip"
    80		}
    81		afnet, _, err := parseNetwork(context.Background(), network, false)
    82		if err != nil {
    83			return nil, err
    84		}
    85		switch afnet {
    86		case "ip", "ip4", "ip6":
    87		default:
    88			return nil, UnknownNetworkError(network)
    89		}
    90		addrs, err := DefaultResolver.internetAddrList(context.Background(), afnet, address)
    91		if err != nil {
    92			return nil, err
    93		}
    94		return addrs.forResolve(network, address).(*IPAddr), nil
    95	}
    96	
    97	// IPConn is the implementation of the Conn and PacketConn interfaces
    98	// for IP network connections.
    99	type IPConn struct {
   100		conn
   101	}
   102	
   103	// SyscallConn returns a raw network connection.
   104	// This implements the syscall.Conn interface.
   105	func (c *IPConn) SyscallConn() (syscall.RawConn, error) {
   106		if !c.ok() {
   107			return nil, syscall.EINVAL
   108		}
   109		return newRawConn(c.fd)
   110	}
   111	
   112	// ReadFromIP acts like ReadFrom but returns an IPAddr.
   113	func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
   114		if !c.ok() {
   115			return 0, nil, syscall.EINVAL
   116		}
   117		n, addr, err := c.readFrom(b)
   118		if err != nil {
   119			err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   120		}
   121		return n, addr, err
   122	}
   123	
   124	// ReadFrom implements the PacketConn ReadFrom method.
   125	func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
   126		if !c.ok() {
   127			return 0, nil, syscall.EINVAL
   128		}
   129		n, addr, err := c.readFrom(b)
   130		if err != nil {
   131			err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   132		}
   133		if addr == nil {
   134			return n, nil, err
   135		}
   136		return n, addr, err
   137	}
   138	
   139	// ReadMsgIP reads a message from c, copying the payload into b and
   140	// the associated out-of-band data into oob. It returns the number of
   141	// bytes copied into b, the number of bytes copied into oob, the flags
   142	// that were set on the message and the source address of the message.
   143	//
   144	// The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be
   145	// used to manipulate IP-level socket options in oob.
   146	func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
   147		if !c.ok() {
   148			return 0, 0, 0, nil, syscall.EINVAL
   149		}
   150		n, oobn, flags, addr, err = c.readMsg(b, oob)
   151		if err != nil {
   152			err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   153		}
   154		return
   155	}
   156	
   157	// WriteToIP acts like WriteTo but takes an IPAddr.
   158	func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
   159		if !c.ok() {
   160			return 0, syscall.EINVAL
   161		}
   162		n, err := c.writeTo(b, addr)
   163		if err != nil {
   164			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
   165		}
   166		return n, err
   167	}
   168	
   169	// WriteTo implements the PacketConn WriteTo method.
   170	func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
   171		if !c.ok() {
   172			return 0, syscall.EINVAL
   173		}
   174		a, ok := addr.(*IPAddr)
   175		if !ok {
   176			return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
   177		}
   178		n, err := c.writeTo(b, a)
   179		if err != nil {
   180			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
   181		}
   182		return n, err
   183	}
   184	
   185	// WriteMsgIP writes a message to addr via c, copying the payload from
   186	// b and the associated out-of-band data from oob. It returns the
   187	// number of payload and out-of-band bytes written.
   188	//
   189	// The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be
   190	// used to manipulate IP-level socket options in oob.
   191	func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
   192		if !c.ok() {
   193			return 0, 0, syscall.EINVAL
   194		}
   195		n, oobn, err = c.writeMsg(b, oob, addr)
   196		if err != nil {
   197			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
   198		}
   199		return
   200	}
   201	
   202	func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
   203	
   204	// DialIP acts like Dial for IP networks.
   205	//
   206	// The network must be an IP network name; see func Dial for details.
   207	//
   208	// If laddr is nil, a local address is automatically chosen.
   209	// If the IP field of raddr is nil or an unspecified IP address, the
   210	// local system is assumed.
   211	func DialIP(network string, laddr, raddr *IPAddr) (*IPConn, error) {
   212		if raddr == nil {
   213			return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
   214		}
   215		sd := &sysDialer{network: network, address: raddr.String()}
   216		c, err := sd.dialIP(context.Background(), laddr, raddr)
   217		if err != nil {
   218			return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
   219		}
   220		return c, nil
   221	}
   222	
   223	// ListenIP acts like ListenPacket for IP networks.
   224	//
   225	// The network must be an IP network name; see func Dial for details.
   226	//
   227	// If the IP field of laddr is nil or an unspecified IP address,
   228	// ListenIP listens on all available IP addresses of the local system
   229	// except multicast IP addresses.
   230	func ListenIP(network string, laddr *IPAddr) (*IPConn, error) {
   231		if laddr == nil {
   232			laddr = &IPAddr{}
   233		}
   234		sl := &sysListener{network: network, address: laddr.String()}
   235		c, err := sl.listenIP(context.Background(), laddr)
   236		if err != nil {
   237			return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
   238		}
   239		return c, nil
   240	}
   241	

View as plain text