2ecd465a16f51ff7450a50892ccbabcb42fbc9b1
[platform/core/system/edge-orchestration.git] / vendor / github.com / miekg / dns / vendor / golang.org / x / net / icmp / diag_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 type diagTest struct {
25         network, address string
26         protocol         int
27         m                icmp.Message
28 }
29
30 func TestDiag(t *testing.T) {
31         if testing.Short() {
32                 t.Skip("avoid external network")
33         }
34
35         t.Run("Ping/NonPrivileged", func(t *testing.T) {
36                 switch runtime.GOOS {
37                 case "darwin":
38                 case "linux":
39                         t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
40                 default:
41                         t.Logf("not supported on %s", runtime.GOOS)
42                         return
43                 }
44                 for i, dt := range []diagTest{
45                         {
46                                 "udp4", "0.0.0.0", iana.ProtocolICMP,
47                                 icmp.Message{
48                                         Type: ipv4.ICMPTypeEcho, Code: 0,
49                                         Body: &icmp.Echo{
50                                                 ID:   os.Getpid() & 0xffff,
51                                                 Data: []byte("HELLO-R-U-THERE"),
52                                         },
53                                 },
54                         },
55
56                         {
57                                 "udp6", "::", iana.ProtocolIPv6ICMP,
58                                 icmp.Message{
59                                         Type: ipv6.ICMPTypeEchoRequest, Code: 0,
60                                         Body: &icmp.Echo{
61                                                 ID:   os.Getpid() & 0xffff,
62                                                 Data: []byte("HELLO-R-U-THERE"),
63                                         },
64                                 },
65                         },
66                 } {
67                         if err := doDiag(dt, i); err != nil {
68                                 t.Error(err)
69                         }
70                 }
71         })
72         t.Run("Ping/Privileged", func(t *testing.T) {
73                 if m, ok := nettest.SupportsRawIPSocket(); !ok {
74                         t.Skip(m)
75                 }
76                 for i, dt := range []diagTest{
77                         {
78                                 "ip4:icmp", "0.0.0.0", iana.ProtocolICMP,
79                                 icmp.Message{
80                                         Type: ipv4.ICMPTypeEcho, Code: 0,
81                                         Body: &icmp.Echo{
82                                                 ID:   os.Getpid() & 0xffff,
83                                                 Data: []byte("HELLO-R-U-THERE"),
84                                         },
85                                 },
86                         },
87
88                         {
89                                 "ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP,
90                                 icmp.Message{
91                                         Type: ipv6.ICMPTypeEchoRequest, Code: 0,
92                                         Body: &icmp.Echo{
93                                                 ID:   os.Getpid() & 0xffff,
94                                                 Data: []byte("HELLO-R-U-THERE"),
95                                         },
96                                 },
97                         },
98                 } {
99                         if err := doDiag(dt, i); err != nil {
100                                 t.Error(err)
101                         }
102                 }
103         })
104         t.Run("Probe/Privileged", func(t *testing.T) {
105                 if m, ok := nettest.SupportsRawIPSocket(); !ok {
106                         t.Skip(m)
107                 }
108                 for i, dt := range []diagTest{
109                         {
110                                 "ip4:icmp", "0.0.0.0", iana.ProtocolICMP,
111                                 icmp.Message{
112                                         Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
113                                         Body: &icmp.ExtendedEchoRequest{
114                                                 ID:    os.Getpid() & 0xffff,
115                                                 Local: true,
116                                                 Extensions: []icmp.Extension{
117                                                         &icmp.InterfaceIdent{
118                                                                 Class: 3, Type: 1,
119                                                                 Name: "doesnotexist",
120                                                         },
121                                                 },
122                                         },
123                                 },
124                         },
125
126                         {
127                                 "ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP,
128                                 icmp.Message{
129                                         Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
130                                         Body: &icmp.ExtendedEchoRequest{
131                                                 ID:    os.Getpid() & 0xffff,
132                                                 Local: true,
133                                                 Extensions: []icmp.Extension{
134                                                         &icmp.InterfaceIdent{
135                                                                 Class: 3, Type: 1,
136                                                                 Name: "doesnotexist",
137                                                         },
138                                                 },
139                                         },
140                                 },
141                         },
142                 } {
143                         if err := doDiag(dt, i); err != nil {
144                                 t.Error(err)
145                         }
146                 }
147         })
148 }
149
150 func doDiag(dt diagTest, seq int) error {
151         c, err := icmp.ListenPacket(dt.network, dt.address)
152         if err != nil {
153                 return err
154         }
155         defer c.Close()
156
157         dst, err := googleAddr(c, dt.protocol)
158         if err != nil {
159                 return err
160         }
161
162         if dt.network != "udp6" && dt.protocol == iana.ProtocolIPv6ICMP {
163                 var f ipv6.ICMPFilter
164                 f.SetAll(true)
165                 f.Accept(ipv6.ICMPTypeDestinationUnreachable)
166                 f.Accept(ipv6.ICMPTypePacketTooBig)
167                 f.Accept(ipv6.ICMPTypeTimeExceeded)
168                 f.Accept(ipv6.ICMPTypeParameterProblem)
169                 f.Accept(ipv6.ICMPTypeEchoReply)
170                 f.Accept(ipv6.ICMPTypeExtendedEchoReply)
171                 if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil {
172                         return err
173                 }
174         }
175
176         switch m := dt.m.Body.(type) {
177         case *icmp.Echo:
178                 m.Seq = 1 << uint(seq)
179         case *icmp.ExtendedEchoRequest:
180                 m.Seq = 1 << uint(seq)
181         }
182         wb, err := dt.m.Marshal(nil)
183         if err != nil {
184                 return err
185         }
186         if n, err := c.WriteTo(wb, dst); err != nil {
187                 return err
188         } else if n != len(wb) {
189                 return fmt.Errorf("got %v; want %v", n, len(wb))
190         }
191
192         rb := make([]byte, 1500)
193         if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
194                 return err
195         }
196         n, peer, err := c.ReadFrom(rb)
197         if err != nil {
198                 return err
199         }
200         rm, err := icmp.ParseMessage(dt.protocol, rb[:n])
201         if err != nil {
202                 return err
203         }
204         switch {
205         case dt.m.Type == ipv4.ICMPTypeEcho && rm.Type == ipv4.ICMPTypeEchoReply:
206                 fallthrough
207         case dt.m.Type == ipv6.ICMPTypeEchoRequest && rm.Type == ipv6.ICMPTypeEchoReply:
208                 fallthrough
209         case dt.m.Type == ipv4.ICMPTypeExtendedEchoRequest && rm.Type == ipv4.ICMPTypeExtendedEchoReply:
210                 fallthrough
211         case dt.m.Type == ipv6.ICMPTypeExtendedEchoRequest && rm.Type == ipv6.ICMPTypeExtendedEchoReply:
212                 return nil
213         default:
214                 return fmt.Errorf("got %+v from %v; want echo reply or extended echo reply", rm, peer)
215         }
216 }
217
218 func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
219         host := "ipv4.google.com"
220         if protocol == iana.ProtocolIPv6ICMP {
221                 host = "ipv6.google.com"
222         }
223         ips, err := net.LookupIP(host)
224         if err != nil {
225                 return nil, err
226         }
227         netaddr := func(ip net.IP) (net.Addr, error) {
228                 switch c.LocalAddr().(type) {
229                 case *net.UDPAddr:
230                         return &net.UDPAddr{IP: ip}, nil
231                 case *net.IPAddr:
232                         return &net.IPAddr{IP: ip}, nil
233                 default:
234                         return nil, errors.New("neither UDPAddr nor IPAddr")
235                 }
236         }
237         if len(ips) > 0 {
238                 return netaddr(ips[0])
239         }
240         return nil, errors.New("no A or AAAA record")
241 }
242
243 func TestConcurrentNonPrivilegedListenPacket(t *testing.T) {
244         if testing.Short() {
245                 t.Skip("avoid external network")
246         }
247         switch runtime.GOOS {
248         case "darwin":
249         case "linux":
250                 t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
251         default:
252                 t.Skipf("not supported on %s", runtime.GOOS)
253         }
254
255         network, address := "udp4", "127.0.0.1"
256         if !nettest.SupportsIPv4() {
257                 network, address = "udp6", "::1"
258         }
259         const N = 1000
260         var wg sync.WaitGroup
261         wg.Add(N)
262         for i := 0; i < N; i++ {
263                 go func() {
264                         defer wg.Done()
265                         c, err := icmp.ListenPacket(network, address)
266                         if err != nil {
267                                 t.Error(err)
268                                 return
269                         }
270                         c.Close()
271                 }()
272         }
273         wg.Wait()
274 }