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