iprawsock_posix.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
  5. package net
  6. import (
  7. "syscall"
  8. "time"
  9. )
  10. // BUG(mikio): On every POSIX platform, reads from the "ip4" network
  11. // using the ReadFrom or ReadFromIP method might not return a complete
  12. // IPv4 packet, including its header, even if there is space
  13. // available. This can occur even in cases where Read or ReadMsgIP
  14. // could return a complete packet. For this reason, it is recommended
  15. // that you do not uses these methods if it is important to receive a
  16. // full packet.
  17. //
  18. // The Go 1 compatibility guidelines make it impossible for us to
  19. // change the behavior of these methods; use Read or ReadMsgIP
  20. // instead.
  21. func sockaddrToIP(sa syscall.Sockaddr) Addr {
  22. switch sa := sa.(type) {
  23. case *syscall.SockaddrInet4:
  24. return &IPAddr{IP: sa.Addr[0:]}
  25. case *syscall.SockaddrInet6:
  26. return &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
  27. }
  28. return nil
  29. }
  30. func (a *IPAddr) family() int {
  31. if a == nil || len(a.IP) <= IPv4len {
  32. return syscall.AF_INET
  33. }
  34. if a.IP.To4() != nil {
  35. return syscall.AF_INET
  36. }
  37. return syscall.AF_INET6
  38. }
  39. func (a *IPAddr) isWildcard() bool {
  40. if a == nil || a.IP == nil {
  41. return true
  42. }
  43. return a.IP.IsUnspecified()
  44. }
  45. func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
  46. if a == nil {
  47. return nil, nil
  48. }
  49. return ipToSockaddr(family, a.IP, 0, a.Zone)
  50. }
  51. // IPConn is the implementation of the Conn and PacketConn interfaces
  52. // for IP network connections.
  53. type IPConn struct {
  54. conn
  55. }
  56. func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
  57. // ReadFromIP reads an IP packet from c, copying the payload into b.
  58. // It returns the number of bytes copied into b and the return address
  59. // that was on the packet.
  60. //
  61. // ReadFromIP can be made to time out and return an error with
  62. // Timeout() == true after a fixed time limit; see SetDeadline and
  63. // SetReadDeadline.
  64. func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
  65. if !c.ok() {
  66. return 0, nil, syscall.EINVAL
  67. }
  68. // TODO(cw,rsc): consider using readv if we know the family
  69. // type to avoid the header trim/copy
  70. var addr *IPAddr
  71. n, sa, err := c.fd.readFrom(b)
  72. switch sa := sa.(type) {
  73. case *syscall.SockaddrInet4:
  74. addr = &IPAddr{IP: sa.Addr[0:]}
  75. if len(b) >= IPv4len { // discard ipv4 header
  76. hsize := (int(b[0]) & 0xf) * 4
  77. copy(b, b[hsize:])
  78. n -= hsize
  79. }
  80. case *syscall.SockaddrInet6:
  81. addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
  82. }
  83. return n, addr, err
  84. }
  85. // ReadFrom implements the PacketConn ReadFrom method.
  86. func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
  87. if !c.ok() {
  88. return 0, nil, syscall.EINVAL
  89. }
  90. n, addr, err := c.ReadFromIP(b)
  91. return n, addr.toAddr(), err
  92. }
  93. // ReadMsgIP reads a packet from c, copying the payload into b and the
  94. // associated out-of-band data into oob. It returns the number of
  95. // bytes copied into b, the number of bytes copied into oob, the flags
  96. // that were set on the packet and the source address of the packet.
  97. func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
  98. if !c.ok() {
  99. return 0, 0, 0, nil, syscall.EINVAL
  100. }
  101. var sa syscall.Sockaddr
  102. n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
  103. switch sa := sa.(type) {
  104. case *syscall.SockaddrInet4:
  105. addr = &IPAddr{IP: sa.Addr[0:]}
  106. case *syscall.SockaddrInet6:
  107. addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
  108. }
  109. return
  110. }
  111. // WriteToIP writes an IP packet to addr via c, copying the payload
  112. // from b.
  113. //
  114. // WriteToIP can be made to time out and return an error with
  115. // Timeout() == true after a fixed time limit; see SetDeadline and
  116. // SetWriteDeadline. On packet-oriented connections, write timeouts
  117. // are rare.
  118. func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
  119. if !c.ok() {
  120. return 0, syscall.EINVAL
  121. }
  122. if c.fd.isConnected {
  123. return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
  124. }
  125. if addr == nil {
  126. return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
  127. }
  128. sa, err := addr.sockaddr(c.fd.family)
  129. if err != nil {
  130. return 0, &OpError{"write", c.fd.net, addr, err}
  131. }
  132. return c.fd.writeTo(b, sa)
  133. }
  134. // WriteTo implements the PacketConn WriteTo method.
  135. func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
  136. if !c.ok() {
  137. return 0, syscall.EINVAL
  138. }
  139. a, ok := addr.(*IPAddr)
  140. if !ok {
  141. return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL}
  142. }
  143. return c.WriteToIP(b, a)
  144. }
  145. // WriteMsgIP writes a packet to addr via c, copying the payload from
  146. // b and the associated out-of-band data from oob. It returns the
  147. // number of payload and out-of-band bytes written.
  148. func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
  149. if !c.ok() {
  150. return 0, 0, syscall.EINVAL
  151. }
  152. if c.fd.isConnected {
  153. return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
  154. }
  155. if addr == nil {
  156. return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
  157. }
  158. sa, err := addr.sockaddr(c.fd.family)
  159. if err != nil {
  160. return 0, 0, &OpError{"write", c.fd.net, addr, err}
  161. }
  162. return c.fd.writeMsg(b, oob, sa)
  163. }
  164. // DialIP connects to the remote address raddr on the network protocol
  165. // netProto, which must be "ip", "ip4", or "ip6" followed by a colon
  166. // and a protocol number or name.
  167. func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
  168. return dialIP(netProto, laddr, raddr, noDeadline)
  169. }
  170. func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
  171. net, proto, err := parseNetwork(netProto)
  172. if err != nil {
  173. return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err}
  174. }
  175. switch net {
  176. case "ip", "ip4", "ip6":
  177. default:
  178. return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: UnknownNetworkError(netProto)}
  179. }
  180. if raddr == nil {
  181. return nil, &OpError{Op: "dial", Net: netProto, Addr: nil, Err: errMissingAddress}
  182. }
  183. fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial")
  184. if err != nil {
  185. return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err}
  186. }
  187. return newIPConn(fd), nil
  188. }
  189. // ListenIP listens for incoming IP packets addressed to the local
  190. // address laddr. The returned connection's ReadFrom and WriteTo
  191. // methods can be used to receive and send IP packets with per-packet
  192. // addressing.
  193. func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
  194. net, proto, err := parseNetwork(netProto)
  195. if err != nil {
  196. return nil, &OpError{Op: "dial", Net: netProto, Addr: laddr, Err: err}
  197. }
  198. switch net {
  199. case "ip", "ip4", "ip6":
  200. default:
  201. return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: UnknownNetworkError(netProto)}
  202. }
  203. fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen")
  204. if err != nil {
  205. return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: err}
  206. }
  207. return newIPConn(fd), nil
  208. }