github.com/Andyfoo/golang/x/net@v0.0.0-20190901054642-57c1bf301704/ipv4/unicast_test.go (about) 1 // Copyright 2012 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 ipv4_test 6 7 import ( 8 "bytes" 9 "net" 10 "os" 11 "runtime" 12 "testing" 13 "time" 14 15 "github.com/Andyfoo/golang/x/net/icmp" 16 "github.com/Andyfoo/golang/x/net/internal/iana" 17 "github.com/Andyfoo/golang/x/net/ipv4" 18 "github.com/Andyfoo/golang/x/net/nettest" 19 ) 20 21 func TestPacketConnReadWriteUnicastUDP(t *testing.T) { 22 switch runtime.GOOS { 23 case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": 24 t.Skipf("not supported on %s", runtime.GOOS) 25 } 26 if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil { 27 t.Skipf("not available on %s", runtime.GOOS) 28 } 29 30 c, err := nettest.NewLocalPacketListener("udp4") 31 if err != nil { 32 t.Fatal(err) 33 } 34 defer c.Close() 35 p := ipv4.NewPacketConn(c) 36 defer p.Close() 37 38 dst := c.LocalAddr() 39 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface 40 wb := []byte("HELLO-R-U-THERE") 41 42 for i, toggle := range []bool{true, false, true} { 43 if err := p.SetControlMessage(cf, toggle); err != nil { 44 if protocolNotSupported(err) { 45 t.Logf("not supported on %s", runtime.GOOS) 46 continue 47 } 48 t.Fatal(err) 49 } 50 p.SetTTL(i + 1) 51 if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { 52 t.Fatal(err) 53 } 54 if n, err := p.WriteTo(wb, nil, dst); err != nil { 55 t.Fatal(err) 56 } else if n != len(wb) { 57 t.Fatalf("got %v; want %v", n, len(wb)) 58 } 59 rb := make([]byte, 128) 60 if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { 61 t.Fatal(err) 62 } 63 if n, _, _, err := p.ReadFrom(rb); err != nil { 64 t.Fatal(err) 65 } else if !bytes.Equal(rb[:n], wb) { 66 t.Fatalf("got %v; want %v", rb[:n], wb) 67 } 68 } 69 } 70 71 func TestPacketConnReadWriteUnicastICMP(t *testing.T) { 72 switch runtime.GOOS { 73 case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": 74 t.Skipf("not supported on %s", runtime.GOOS) 75 } 76 if !nettest.SupportsRawSocket() { 77 t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) 78 } 79 if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil { 80 t.Skipf("not available on %s", runtime.GOOS) 81 } 82 83 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") 84 if err != nil { 85 t.Fatal(err) 86 } 87 defer c.Close() 88 89 dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") 90 if err != nil { 91 t.Fatal(err) 92 } 93 p := ipv4.NewPacketConn(c) 94 defer p.Close() 95 cf := ipv4.FlagDst | ipv4.FlagInterface 96 if runtime.GOOS != "illumos" && runtime.GOOS != "solaris" { 97 // Illumos and Solaris never allow modification of ICMP properties. 98 cf |= ipv4.FlagTTL 99 } 100 101 for i, toggle := range []bool{true, false, true} { 102 wb, err := (&icmp.Message{ 103 Type: ipv4.ICMPTypeEcho, Code: 0, 104 Body: &icmp.Echo{ 105 ID: os.Getpid() & 0xffff, Seq: i + 1, 106 Data: []byte("HELLO-R-U-THERE"), 107 }, 108 }).Marshal(nil) 109 if err != nil { 110 t.Fatal(err) 111 } 112 if err := p.SetControlMessage(cf, toggle); err != nil { 113 if protocolNotSupported(err) { 114 t.Logf("not supported on %s", runtime.GOOS) 115 continue 116 } 117 t.Fatal(err) 118 } 119 p.SetTTL(i + 1) 120 if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { 121 t.Fatal(err) 122 } 123 if n, err := p.WriteTo(wb, nil, dst); err != nil { 124 t.Fatal(err) 125 } else if n != len(wb) { 126 t.Fatalf("got %v; want %v", n, len(wb)) 127 } 128 rb := make([]byte, 128) 129 loop: 130 if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { 131 t.Fatal(err) 132 } 133 if n, _, _, err := p.ReadFrom(rb); err != nil { 134 switch runtime.GOOS { 135 case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket 136 t.Logf("not supported on %s", runtime.GOOS) 137 continue 138 } 139 t.Fatal(err) 140 } else { 141 m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n]) 142 if err != nil { 143 t.Fatal(err) 144 } 145 if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho { 146 // On Linux we must handle own sent packets. 147 goto loop 148 } 149 if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { 150 t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) 151 } 152 } 153 } 154 } 155 156 func TestRawConnReadWriteUnicastICMP(t *testing.T) { 157 switch runtime.GOOS { 158 case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": 159 t.Skipf("not supported on %s", runtime.GOOS) 160 } 161 if !nettest.SupportsRawSocket() { 162 t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) 163 } 164 if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil { 165 t.Skipf("not available on %s", runtime.GOOS) 166 } 167 168 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") 169 if err != nil { 170 t.Fatal(err) 171 } 172 defer c.Close() 173 174 dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") 175 if err != nil { 176 t.Fatal(err) 177 } 178 r, err := ipv4.NewRawConn(c) 179 if err != nil { 180 t.Fatal(err) 181 } 182 defer r.Close() 183 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface 184 185 for i, toggle := range []bool{true, false, true} { 186 wb, err := (&icmp.Message{ 187 Type: ipv4.ICMPTypeEcho, Code: 0, 188 Body: &icmp.Echo{ 189 ID: os.Getpid() & 0xffff, Seq: i + 1, 190 Data: []byte("HELLO-R-U-THERE"), 191 }, 192 }).Marshal(nil) 193 if err != nil { 194 t.Fatal(err) 195 } 196 wh := &ipv4.Header{ 197 Version: ipv4.Version, 198 Len: ipv4.HeaderLen, 199 TOS: i + 1, 200 TotalLen: ipv4.HeaderLen + len(wb), 201 TTL: i + 1, 202 Protocol: 1, 203 Dst: dst.IP, 204 } 205 if err := r.SetControlMessage(cf, toggle); err != nil { 206 if protocolNotSupported(err) { 207 t.Logf("not supported on %s", runtime.GOOS) 208 continue 209 } 210 t.Fatal(err) 211 } 212 if err := r.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { 213 t.Fatal(err) 214 } 215 if err := r.WriteTo(wh, wb, nil); err != nil { 216 t.Fatal(err) 217 } 218 rb := make([]byte, ipv4.HeaderLen+128) 219 loop: 220 if err := r.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { 221 t.Fatal(err) 222 } 223 if _, b, _, err := r.ReadFrom(rb); err != nil { 224 switch runtime.GOOS { 225 case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket 226 t.Logf("not supported on %s", runtime.GOOS) 227 continue 228 } 229 t.Fatal(err) 230 } else { 231 m, err := icmp.ParseMessage(iana.ProtocolICMP, b) 232 if err != nil { 233 t.Fatal(err) 234 } 235 if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho { 236 // On Linux we must handle own sent packets. 237 goto loop 238 } 239 if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { 240 t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) 241 } 242 } 243 } 244 }