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. "time"
  9. "golang.org/x/net/ipv4"
  10. "golang.org/x/net/ipv6"
  11. )
  12. var _ net.PacketConn = &PacketConn{}
  13. // A PacketConn represents a packet network endpoint that uses either
  14. // ICMPv4 or ICMPv6.
  15. type PacketConn struct {
  16. c net.PacketConn
  17. p4 *ipv4.PacketConn
  18. p6 *ipv6.PacketConn
  19. }
  20. func (c *PacketConn) ok() bool { return c != nil && c.c != nil }
  21. // IPv4PacketConn returns the ipv4.PacketConn of c.
  22. // It returns nil when c is not created as the endpoint for ICMPv4.
  23. func (c *PacketConn) IPv4PacketConn() *ipv4.PacketConn {
  24. if !c.ok() {
  25. return nil
  26. }
  27. return c.p4
  28. }
  29. // IPv6PacketConn returns the ipv6.PacketConn of c.
  30. // It returns nil when c is not created as the endpoint for ICMPv6.
  31. func (c *PacketConn) IPv6PacketConn() *ipv6.PacketConn {
  32. if !c.ok() {
  33. return nil
  34. }
  35. return c.p6
  36. }
  37. // ReadFrom reads an ICMP message from the connection.
  38. func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
  39. if !c.ok() {
  40. return 0, nil, errInvalidConn
  41. }
  42. // Please be informed that ipv4.NewPacketConn enables
  43. // IP_STRIPHDR option by default on Darwin.
  44. // See golang.org/issue/9395 for further information.
  45. if runtime.GOOS == "darwin" && c.p4 != nil {
  46. n, _, peer, err := c.p4.ReadFrom(b)
  47. return n, peer, err
  48. }
  49. return c.c.ReadFrom(b)
  50. }
  51. // WriteTo writes the ICMP message b to dst.
  52. // The provided dst must be net.UDPAddr when c is a non-privileged
  53. // datagram-oriented ICMP endpoint.
  54. // 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, errInvalidConn
  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 errInvalidConn
  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 errInvalidConn
  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 errInvalidConn
  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 errInvalidConn
  96. }
  97. return c.c.SetWriteDeadline(t)
  98. }