endpoint.go 2.7 KB

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