ping_test.go 2.8 KB

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