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