github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/src/net/ipraw_test.go (about)

     1  // Copyright 2009 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 net
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"os"
    11  	"reflect"
    12  	"runtime"
    13  	"testing"
    14  	"time"
    15  )
    16  
    17  type resolveIPAddrTest struct {
    18  	net           string
    19  	litAddrOrName string
    20  	addr          *IPAddr
    21  	err           error
    22  }
    23  
    24  var resolveIPAddrTests = []resolveIPAddrTest{
    25  	{"ip", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
    26  	{"ip4", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
    27  	{"ip4:icmp", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
    28  
    29  	{"ip", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
    30  	{"ip6", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
    31  	{"ip6:ipv6-icmp", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
    32  	{"ip6:IPv6-ICMP", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
    33  
    34  	{"ip", "::1%en0", &IPAddr{IP: ParseIP("::1"), Zone: "en0"}, nil},
    35  	{"ip6", "::1%911", &IPAddr{IP: ParseIP("::1"), Zone: "911"}, nil},
    36  
    37  	{"", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, // Go 1.0 behavior
    38  	{"", "::1", &IPAddr{IP: ParseIP("::1")}, nil},           // Go 1.0 behavior
    39  
    40  	{"l2tp", "127.0.0.1", nil, UnknownNetworkError("l2tp")},
    41  	{"l2tp:gre", "127.0.0.1", nil, UnknownNetworkError("l2tp:gre")},
    42  	{"tcp", "1.2.3.4:123", nil, UnknownNetworkError("tcp")},
    43  }
    44  
    45  func init() {
    46  	if ifi := loopbackInterface(); ifi != nil {
    47  		index := fmt.Sprintf("%v", ifi.Index)
    48  		resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
    49  			{"ip6", "fe80::1%" + ifi.Name, &IPAddr{IP: ParseIP("fe80::1"), Zone: zoneToString(ifi.Index)}, nil},
    50  			{"ip6", "fe80::1%" + index, &IPAddr{IP: ParseIP("fe80::1"), Zone: index}, nil},
    51  		}...)
    52  	}
    53  	if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
    54  		resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
    55  			{"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
    56  			{"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
    57  			{"ip6", "localhost", &IPAddr{IP: IPv6loopback}, nil},
    58  		}...)
    59  	}
    60  }
    61  
    62  func skipRawSocketTest(t *testing.T) (skip bool, skipmsg string) {
    63  	skip, skipmsg, err := skipRawSocketTests()
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	return skip, skipmsg
    68  }
    69  
    70  func TestResolveIPAddr(t *testing.T) {
    71  	switch runtime.GOOS {
    72  	case "nacl":
    73  		t.Skipf("skipping test on %q", runtime.GOOS)
    74  	}
    75  
    76  	for _, tt := range resolveIPAddrTests {
    77  		addr, err := ResolveIPAddr(tt.net, tt.litAddrOrName)
    78  		if err != tt.err {
    79  			t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddrOrName, err)
    80  		} else if !reflect.DeepEqual(addr, tt.addr) {
    81  			t.Fatalf("got %#v; expected %#v", addr, tt.addr)
    82  		}
    83  	}
    84  }
    85  
    86  var icmpEchoTests = []struct {
    87  	net   string
    88  	laddr string
    89  	raddr string
    90  }{
    91  	{"ip4:icmp", "0.0.0.0", "127.0.0.1"},
    92  	{"ip6:ipv6-icmp", "::", "::1"},
    93  }
    94  
    95  func TestConnICMPEcho(t *testing.T) {
    96  	if skip, skipmsg := skipRawSocketTest(t); skip {
    97  		t.Skip(skipmsg)
    98  	}
    99  
   100  	for i, tt := range icmpEchoTests {
   101  		net, _, err := parseNetwork(tt.net)
   102  		if err != nil {
   103  			t.Fatalf("parseNetwork failed: %v", err)
   104  		}
   105  		if net == "ip6" && !supportsIPv6 {
   106  			continue
   107  		}
   108  
   109  		c, err := Dial(tt.net, tt.raddr)
   110  		if err != nil {
   111  			t.Fatalf("Dial failed: %v", err)
   112  		}
   113  		c.SetDeadline(time.Now().Add(100 * time.Millisecond))
   114  		defer c.Close()
   115  
   116  		typ := icmpv4EchoRequest
   117  		if net == "ip6" {
   118  			typ = icmpv6EchoRequest
   119  		}
   120  		xid, xseq := os.Getpid()&0xffff, i+1
   121  		wb, err := (&icmpMessage{
   122  			Type: typ, Code: 0,
   123  			Body: &icmpEcho{
   124  				ID: xid, Seq: xseq,
   125  				Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
   126  			},
   127  		}).Marshal()
   128  		if err != nil {
   129  			t.Fatalf("icmpMessage.Marshal failed: %v", err)
   130  		}
   131  		if _, err := c.Write(wb); err != nil {
   132  			t.Fatalf("Conn.Write failed: %v", err)
   133  		}
   134  		var m *icmpMessage
   135  		rb := make([]byte, 20+len(wb))
   136  		for {
   137  			if _, err := c.Read(rb); err != nil {
   138  				t.Fatalf("Conn.Read failed: %v", err)
   139  			}
   140  			if net == "ip4" {
   141  				rb = ipv4Payload(rb)
   142  			}
   143  			if m, err = parseICMPMessage(rb); err != nil {
   144  				t.Fatalf("parseICMPMessage failed: %v", err)
   145  			}
   146  			switch m.Type {
   147  			case icmpv4EchoRequest, icmpv6EchoRequest:
   148  				continue
   149  			}
   150  			break
   151  		}
   152  		switch p := m.Body.(type) {
   153  		case *icmpEcho:
   154  			if p.ID != xid || p.Seq != xseq {
   155  				t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
   156  			}
   157  		default:
   158  			t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
   159  		}
   160  	}
   161  }
   162  
   163  func TestPacketConnICMPEcho(t *testing.T) {
   164  	if skip, skipmsg := skipRawSocketTest(t); skip {
   165  		t.Skip(skipmsg)
   166  	}
   167  
   168  	for i, tt := range icmpEchoTests {
   169  		net, _, err := parseNetwork(tt.net)
   170  		if err != nil {
   171  			t.Fatalf("parseNetwork failed: %v", err)
   172  		}
   173  		if net == "ip6" && !supportsIPv6 {
   174  			continue
   175  		}
   176  
   177  		c, err := ListenPacket(tt.net, tt.laddr)
   178  		if err != nil {
   179  			t.Fatalf("ListenPacket failed: %v", err)
   180  		}
   181  		c.SetDeadline(time.Now().Add(100 * time.Millisecond))
   182  		defer c.Close()
   183  
   184  		ra, err := ResolveIPAddr(tt.net, tt.raddr)
   185  		if err != nil {
   186  			t.Fatalf("ResolveIPAddr failed: %v", err)
   187  		}
   188  		typ := icmpv4EchoRequest
   189  		if net == "ip6" {
   190  			typ = icmpv6EchoRequest
   191  		}
   192  		xid, xseq := os.Getpid()&0xffff, i+1
   193  		wb, err := (&icmpMessage{
   194  			Type: typ, Code: 0,
   195  			Body: &icmpEcho{
   196  				ID: xid, Seq: xseq,
   197  				Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
   198  			},
   199  		}).Marshal()
   200  		if err != nil {
   201  			t.Fatalf("icmpMessage.Marshal failed: %v", err)
   202  		}
   203  		if _, err := c.WriteTo(wb, ra); err != nil {
   204  			t.Fatalf("PacketConn.WriteTo failed: %v", err)
   205  		}
   206  		var m *icmpMessage
   207  		rb := make([]byte, 20+len(wb))
   208  		for {
   209  			if _, _, err := c.ReadFrom(rb); err != nil {
   210  				t.Fatalf("PacketConn.ReadFrom failed: %v", err)
   211  			}
   212  			// See BUG section.
   213  			//if net == "ip4" {
   214  			//	rb = ipv4Payload(rb)
   215  			//}
   216  			if m, err = parseICMPMessage(rb); err != nil {
   217  				t.Fatalf("parseICMPMessage failed: %v", err)
   218  			}
   219  			switch m.Type {
   220  			case icmpv4EchoRequest, icmpv6EchoRequest:
   221  				continue
   222  			}
   223  			break
   224  		}
   225  		switch p := m.Body.(type) {
   226  		case *icmpEcho:
   227  			if p.ID != xid || p.Seq != xseq {
   228  				t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
   229  			}
   230  		default:
   231  			t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
   232  		}
   233  	}
   234  }
   235  
   236  func ipv4Payload(b []byte) []byte {
   237  	if len(b) < 20 {
   238  		return b
   239  	}
   240  	hdrlen := int(b[0]&0x0f) << 2
   241  	return b[hdrlen:]
   242  }
   243  
   244  var ipConnLocalNameTests = []struct {
   245  	net   string
   246  	laddr *IPAddr
   247  }{
   248  	{"ip4:icmp", &IPAddr{IP: IPv4(127, 0, 0, 1)}},
   249  	{"ip4:icmp", &IPAddr{}},
   250  	{"ip4:icmp", nil},
   251  }
   252  
   253  func TestIPConnLocalName(t *testing.T) {
   254  	switch runtime.GOOS {
   255  	case "nacl", "plan9", "windows":
   256  		t.Skipf("skipping test on %q", runtime.GOOS)
   257  	default:
   258  		if os.Getuid() != 0 {
   259  			t.Skip("skipping test; must be root")
   260  		}
   261  	}
   262  
   263  	for _, tt := range ipConnLocalNameTests {
   264  		c, err := ListenIP(tt.net, tt.laddr)
   265  		if err != nil {
   266  			t.Fatalf("ListenIP failed: %v", err)
   267  		}
   268  		defer c.Close()
   269  		if la := c.LocalAddr(); la == nil {
   270  			t.Fatal("IPConn.LocalAddr failed")
   271  		}
   272  	}
   273  }
   274  
   275  func TestIPConnRemoteName(t *testing.T) {
   276  	switch runtime.GOOS {
   277  	case "plan9", "windows":
   278  		t.Skipf("skipping test on %q", runtime.GOOS)
   279  	default:
   280  		if os.Getuid() != 0 {
   281  			t.Skip("skipping test; must be root")
   282  		}
   283  	}
   284  
   285  	raddr := &IPAddr{IP: IPv4(127, 0, 0, 1).To4()}
   286  	c, err := DialIP("ip:tcp", &IPAddr{IP: IPv4(127, 0, 0, 1)}, raddr)
   287  	if err != nil {
   288  		t.Fatalf("DialIP failed: %v", err)
   289  	}
   290  	defer c.Close()
   291  	if !reflect.DeepEqual(raddr, c.RemoteAddr()) {
   292  		t.Fatalf("got %#v, expected %#v", c.RemoteAddr(), raddr)
   293  	}
   294  }