github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/net/iprawsock.go (about)

     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 NaCl, Plan 9 and Windows, the ReadMsgIP and
    25  // WriteMsgIP methods of 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 parses addr as an IP address of the form "host" or
    65  // "ipv6-host%zone" and resolves the domain name on the network net,
    66  // which must be "ip", "ip4" or "ip6".
    67  //
    68  // Resolving a hostname is not recommended because this returns at most
    69  // one of its IP addresses.
    70  func ResolveIPAddr(net, addr string) (*IPAddr, error) {
    71  	if net == "" { // a hint wildcard for Go 1.0 undocumented behavior
    72  		net = "ip"
    73  	}
    74  	afnet, _, err := parseNetwork(context.Background(), net, false)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	switch afnet {
    79  	case "ip", "ip4", "ip6":
    80  	default:
    81  		return nil, UnknownNetworkError(net)
    82  	}
    83  	addrs, err := DefaultResolver.internetAddrList(context.Background(), afnet, addr)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	return addrs.first(isIPv4).(*IPAddr), nil
    88  }
    89  
    90  // IPConn is the implementation of the Conn and PacketConn interfaces
    91  // for IP network connections.
    92  type IPConn struct {
    93  	conn
    94  }
    95  
    96  // ReadFromIP reads an IP packet from c, copying the payload into b.
    97  // It returns the number of bytes copied into b and the return address
    98  // that was on the packet.
    99  //
   100  // ReadFromIP can be made to time out and return an error with
   101  // Timeout() == true after a fixed time limit; see SetDeadline and
   102  // SetReadDeadline.
   103  func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
   104  	if !c.ok() {
   105  		return 0, nil, syscall.EINVAL
   106  	}
   107  	n, addr, err := c.readFrom(b)
   108  	if err != nil {
   109  		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   110  	}
   111  	return n, addr, err
   112  }
   113  
   114  // ReadFrom implements the PacketConn ReadFrom method.
   115  func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
   116  	if !c.ok() {
   117  		return 0, nil, syscall.EINVAL
   118  	}
   119  	n, addr, err := c.readFrom(b)
   120  	if err != nil {
   121  		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   122  	}
   123  	if addr == nil {
   124  		return n, nil, err
   125  	}
   126  	return n, addr, err
   127  }
   128  
   129  // ReadMsgIP reads a packet from c, copying the payload into b and the
   130  // associated out-of-band data into oob. It returns the number of
   131  // bytes copied into b, the number of bytes copied into oob, the flags
   132  // that were set on the packet and the source address of the packet.
   133  func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
   134  	if !c.ok() {
   135  		return 0, 0, 0, nil, syscall.EINVAL
   136  	}
   137  	n, oobn, flags, addr, err = c.readMsg(b, oob)
   138  	if err != nil {
   139  		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   140  	}
   141  	return
   142  }
   143  
   144  // WriteToIP writes an IP packet to addr via c, copying the payload
   145  // from b.
   146  //
   147  // WriteToIP can be made to time out and return an error with
   148  // Timeout() == true after a fixed time limit; see SetDeadline and
   149  // SetWriteDeadline. On packet-oriented connections, write timeouts
   150  // are rare.
   151  func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
   152  	if !c.ok() {
   153  		return 0, syscall.EINVAL
   154  	}
   155  	n, err := c.writeTo(b, addr)
   156  	if err != nil {
   157  		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
   158  	}
   159  	return n, err
   160  }
   161  
   162  // WriteTo implements the PacketConn WriteTo method.
   163  func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
   164  	if !c.ok() {
   165  		return 0, syscall.EINVAL
   166  	}
   167  	a, ok := addr.(*IPAddr)
   168  	if !ok {
   169  		return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
   170  	}
   171  	n, err := c.writeTo(b, a)
   172  	if err != nil {
   173  		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
   174  	}
   175  	return n, err
   176  }
   177  
   178  // WriteMsgIP writes a packet to addr via c, copying the payload from
   179  // b and the associated out-of-band data from oob. It returns the
   180  // number of payload and out-of-band bytes written.
   181  func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
   182  	if !c.ok() {
   183  		return 0, 0, syscall.EINVAL
   184  	}
   185  	n, oobn, err = c.writeMsg(b, oob, addr)
   186  	if err != nil {
   187  		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
   188  	}
   189  	return
   190  }
   191  
   192  func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
   193  
   194  // DialIP connects to the remote address raddr on the network protocol
   195  // netProto, which must be "ip", "ip4", or "ip6" followed by a colon
   196  // and a protocol number or name.
   197  func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
   198  	c, err := dialIP(context.Background(), netProto, laddr, raddr)
   199  	if err != nil {
   200  		return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
   201  	}
   202  	return c, nil
   203  }
   204  
   205  // ListenIP listens for incoming IP packets addressed to the local
   206  // address laddr. The returned connection's ReadFrom and WriteTo
   207  // methods can be used to receive and send IP packets with per-packet
   208  // addressing.
   209  func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
   210  	c, err := listenIP(context.Background(), netProto, laddr)
   211  	if err != nil {
   212  		return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
   213  	}
   214  	return c, nil
   215  }