OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / icmp / ping_test.go
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
5 package icmp_test
6
7 import (
8         "errors"
9         "fmt"
10         "net"
11         "os"
12         "runtime"
13         "sync"
14         "testing"
15         "time"
16
17         "golang.org/x/net/icmp"
18         "golang.org/x/net/internal/iana"
19         "golang.org/x/net/internal/nettest"
20         "golang.org/x/net/ipv4"
21         "golang.org/x/net/ipv6"
22 )
23
24 func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
25         const host = "www.google.com"
26         ips, err := net.LookupIP(host)
27         if err != nil {
28                 return nil, err
29         }
30         netaddr := func(ip net.IP) (net.Addr, error) {
31                 switch c.LocalAddr().(type) {
32                 case *net.UDPAddr:
33                         return &net.UDPAddr{IP: ip}, nil
34                 case *net.IPAddr:
35                         return &net.IPAddr{IP: ip}, nil
36                 default:
37                         return nil, errors.New("neither UDPAddr nor IPAddr")
38                 }
39         }
40         for _, ip := range ips {
41                 switch protocol {
42                 case iana.ProtocolICMP:
43                         if ip.To4() != nil {
44                                 return netaddr(ip)
45                         }
46                 case iana.ProtocolIPv6ICMP:
47                         if ip.To16() != nil && ip.To4() == nil {
48                                 return netaddr(ip)
49                         }
50                 }
51         }
52         return nil, errors.New("no A or AAAA record")
53 }
54
55 type pingTest struct {
56         network, address string
57         protocol         int
58         mtype            icmp.Type
59 }
60
61 var nonPrivilegedPingTests = []pingTest{
62         {"udp4", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
63
64         {"udp6", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
65 }
66
67 func TestNonPrivilegedPing(t *testing.T) {
68         if testing.Short() {
69                 t.Skip("avoid external network")
70         }
71         switch runtime.GOOS {
72         case "darwin":
73         case "linux":
74                 t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
75         default:
76                 t.Skipf("not supported on %s", runtime.GOOS)
77         }
78
79         for i, tt := range nonPrivilegedPingTests {
80                 if err := doPing(tt, i); err != nil {
81                         t.Error(err)
82                 }
83         }
84 }
85
86 var privilegedPingTests = []pingTest{
87         {"ip4:icmp", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
88
89         {"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
90 }
91
92 func TestPrivilegedPing(t *testing.T) {
93         if testing.Short() {
94                 t.Skip("avoid external network")
95         }
96         if m, ok := nettest.SupportsRawIPSocket(); !ok {
97                 t.Skip(m)
98         }
99
100         for i, tt := range privilegedPingTests {
101                 if err := doPing(tt, i); err != nil {
102                         t.Error(err)
103                 }
104         }
105 }
106
107 func doPing(tt pingTest, seq int) error {
108         c, err := icmp.ListenPacket(tt.network, tt.address)
109         if err != nil {
110                 return err
111         }
112         defer c.Close()
113
114         dst, err := googleAddr(c, tt.protocol)
115         if err != nil {
116                 return err
117         }
118
119         if tt.network != "udp6" && tt.protocol == iana.ProtocolIPv6ICMP {
120                 var f ipv6.ICMPFilter
121                 f.SetAll(true)
122                 f.Accept(ipv6.ICMPTypeDestinationUnreachable)
123                 f.Accept(ipv6.ICMPTypePacketTooBig)
124                 f.Accept(ipv6.ICMPTypeTimeExceeded)
125                 f.Accept(ipv6.ICMPTypeParameterProblem)
126                 f.Accept(ipv6.ICMPTypeEchoReply)
127                 if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil {
128                         return err
129                 }
130         }
131
132         wm := icmp.Message{
133                 Type: tt.mtype, Code: 0,
134                 Body: &icmp.Echo{
135                         ID: os.Getpid() & 0xffff, Seq: 1 << uint(seq),
136                         Data: []byte("HELLO-R-U-THERE"),
137                 },
138         }
139         wb, err := wm.Marshal(nil)
140         if err != nil {
141                 return err
142         }
143         if n, err := c.WriteTo(wb, dst); err != nil {
144                 return err
145         } else if n != len(wb) {
146                 return fmt.Errorf("got %v; want %v", n, len(wb))
147         }
148
149         rb := make([]byte, 1500)
150         if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
151                 return err
152         }
153         n, peer, err := c.ReadFrom(rb)
154         if err != nil {
155                 return err
156         }
157         rm, err := icmp.ParseMessage(tt.protocol, rb[:n])
158         if err != nil {
159                 return err
160         }
161         switch rm.Type {
162         case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply:
163                 return nil
164         default:
165                 return fmt.Errorf("got %+v from %v; want echo reply", rm, peer)
166         }
167 }
168
169 func TestConcurrentNonPrivilegedListenPacket(t *testing.T) {
170         if testing.Short() {
171                 t.Skip("avoid external network")
172         }
173         switch runtime.GOOS {
174         case "darwin":
175         case "linux":
176                 t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
177         default:
178                 t.Skipf("not supported on %s", runtime.GOOS)
179         }
180
181         network, address := "udp4", "127.0.0.1"
182         if !nettest.SupportsIPv4() {
183                 network, address = "udp6", "::1"
184         }
185         const N = 1000
186         var wg sync.WaitGroup
187         wg.Add(N)
188         for i := 0; i < N; i++ {
189                 go func() {
190                         defer wg.Done()
191                         c, err := icmp.ListenPacket(network, address)
192                         if err != nil {
193                                 t.Error(err)
194                                 return
195                         }
196                         c.Close()
197                 }()
198         }
199         wg.Wait()
200 }