endpoint.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright 2014 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. package icmp
  5. import (
  6. "net"
  7. "runtime"
  8. "syscall"
  9. "time"
  10. "golang.org/x/net/ipv4"
  11. "golang.org/x/net/ipv6"
  12. )
  13. var _ net.PacketConn = &PacketConn{}
  14. // A PacketConn represents a packet network endpoint that uses either
  15. // ICMPv4 or ICMPv6.
  16. type PacketConn struct {
  17. c net.PacketConn
  18. p4 *ipv4.PacketConn
  19. p6 *ipv6.PacketConn
  20. }
  21. func (c *PacketConn) ok() bool { return c != nil && c.c != nil }
  22. // IPv4PacketConn returns the ipv4.PacketConn of c.
  23. // It returns nil when c is not created as the endpoint for ICMPv4.
  24. func (c *PacketConn) IPv4PacketConn() *ipv4.PacketConn {
  25. if !c.ok() {
  26. return nil
  27. }
  28. return c.p4
  29. }
  30. // IPv6PacketConn returns the ipv6.PacketConn of c.
  31. // It returns nil when c is not created as the endpoint for ICMPv6.
  32. func (c *PacketConn) IPv6PacketConn() *ipv6.PacketConn {
  33. if !c.ok() {
  34. return nil
  35. }
  36. return c.p6
  37. }
  38. // ReadFrom reads an ICMP message from the connection.
  39. func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
  40. if !c.ok() {
  41. return 0, nil, syscall.EINVAL
  42. }
  43. // Please be informed that ipv4.NewPacketConn enables
  44. // IP_STRIPHDR option by default on Darwin.
  45. // See golang.org/issue/9395 for further information.
  46. if runtime.GOOS == "darwin" && c.p4 != nil {
  47. n, _, peer, err := c.p4.ReadFrom(b)
  48. return n, peer, err
  49. }
  50. return c.c.ReadFrom(b)
  51. }
  52. // WriteTo writes the ICMP message b to dst.
  53. // Dst must be net.UDPAddr when c is a non-privileged
  54. // datagram-oriented ICMP endpoint. Otherwise it must be net.IPAddr.
  55. func (c *PacketConn) WriteTo(b []byte, dst net.Addr) (int, error) {
  56. if !c.ok() {
  57. return 0, syscall.EINVAL
  58. }
  59. return c.c.WriteTo(b, dst)
  60. }
  61. // Close closes the endpoint.
  62. func (c *PacketConn) Close() error {
  63. if !c.ok() {
  64. return syscall.EINVAL
  65. }
  66. return c.c.Close()
  67. }
  68. // LocalAddr returns the local network address.
  69. func (c *PacketConn) LocalAddr() net.Addr {
  70. if !c.ok() {
  71. return nil
  72. }
  73. return c.c.LocalAddr()
  74. }
  75. // SetDeadline sets the read and write deadlines associated with the
  76. // endpoint.
  77. func (c *PacketConn) SetDeadline(t time.Time) error {
  78. if !c.ok() {
  79. return syscall.EINVAL
  80. }
  81. return c.c.SetDeadline(t)
  82. }
  83. // SetReadDeadline sets the read deadline associated with the
  84. // endpoint.
  85. func (c *PacketConn) SetReadDeadline(t time.Time) error {
  86. if !c.ok() {
  87. return syscall.EINVAL
  88. }
  89. return c.c.SetReadDeadline(t)
  90. }
  91. // SetWriteDeadline sets the write deadline associated with the
  92. // endpoint.
  93. func (c *PacketConn) SetWriteDeadline(t time.Time) error {
  94. if !c.ok() {
  95. return syscall.EINVAL
  96. }
  97. return c.c.SetWriteDeadline(t)
  98. }