ping_test.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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_test
  5. import (
  6. "errors"
  7. "net"
  8. "os"
  9. "runtime"
  10. "testing"
  11. "golang.org/x/net/icmp"
  12. "golang.org/x/net/internal/iana"
  13. "golang.org/x/net/internal/nettest"
  14. "golang.org/x/net/ipv4"
  15. "golang.org/x/net/ipv6"
  16. )
  17. func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
  18. const host = "www.google.com"
  19. ips, err := net.LookupIP(host)
  20. if err != nil {
  21. return nil, err
  22. }
  23. netaddr := func(ip net.IP) (net.Addr, error) {
  24. switch c.LocalAddr().(type) {
  25. case *net.UDPAddr:
  26. return &net.UDPAddr{IP: ip}, nil
  27. case *net.IPAddr:
  28. return &net.IPAddr{IP: ip}, nil
  29. default:
  30. return nil, errors.New("neither UDPAddr nor IPAddr")
  31. }
  32. }
  33. for _, ip := range ips {
  34. switch protocol {
  35. case iana.ProtocolICMP:
  36. if ip.To4() != nil {
  37. return netaddr(ip)
  38. }
  39. case iana.ProtocolIPv6ICMP:
  40. if ip.To16() != nil && ip.To4() == nil {
  41. return netaddr(ip)
  42. }
  43. }
  44. }
  45. return nil, errors.New("no A or AAAA record")
  46. }
  47. var pingGoogleTests = []struct {
  48. network, address string
  49. protocol int
  50. mtype icmp.Type
  51. }{
  52. {"udp4", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
  53. {"ip4:icmp", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
  54. {"udp6", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
  55. {"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
  56. }
  57. func TestPingGoogle(t *testing.T) {
  58. if testing.Short() {
  59. t.Skip("to avoid external network")
  60. }
  61. switch runtime.GOOS {
  62. case "darwin":
  63. case "linux":
  64. t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
  65. default:
  66. t.Skipf("not supported on %s", runtime.GOOS)
  67. }
  68. m, ok := nettest.SupportsRawIPSocket()
  69. for i, tt := range pingGoogleTests {
  70. if tt.network[:2] == "ip" && !ok {
  71. t.Log(m)
  72. continue
  73. }
  74. c, err := icmp.ListenPacket(tt.network, tt.address)
  75. if err != nil {
  76. t.Error(err)
  77. continue
  78. }
  79. defer c.Close()
  80. dst, err := googleAddr(c, tt.protocol)
  81. if err != nil {
  82. t.Error(err)
  83. continue
  84. }
  85. wm := icmp.Message{
  86. Type: tt.mtype, Code: 0,
  87. Body: &icmp.Echo{
  88. ID: os.Getpid() & 0xffff, Seq: 1 << uint(i),
  89. Data: []byte("HELLO-R-U-THERE"),
  90. },
  91. }
  92. wb, err := wm.Marshal(nil)
  93. if err != nil {
  94. t.Error(err)
  95. continue
  96. }
  97. if n, err := c.WriteTo(wb, dst); err != nil {
  98. t.Error(err, dst)
  99. continue
  100. } else if n != len(wb) {
  101. t.Errorf("got %v; want %v", n, len(wb))
  102. continue
  103. }
  104. rb := make([]byte, 1500)
  105. n, peer, err := c.ReadFrom(rb)
  106. if err != nil {
  107. t.Error(err)
  108. continue
  109. }
  110. rm, err := icmp.ParseMessage(tt.protocol, rb[:n])
  111. if err != nil {
  112. t.Error(err)
  113. continue
  114. }
  115. switch rm.Type {
  116. case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply:
  117. t.Logf("got reflection from %v", peer)
  118. default:
  119. t.Errorf("got %+v; want echo reply", rm)
  120. }
  121. }
  122. }