github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/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  	for _, tt := range resolveIPAddrTests {
    72  		addr, err := ResolveIPAddr(tt.net, tt.litAddrOrName)
    73  		if err != tt.err {
    74  			t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddrOrName, err)
    75  		} else if !reflect.DeepEqual(addr, tt.addr) {
    76  			t.Fatalf("got %#v; expected %#v", addr, tt.addr)
    77  		}
    78  	}
    79  }
    80  
    81  var icmpEchoTests = []struct {
    82  	net   string
    83  	laddr string
    84  	raddr string
    85  }{
    86  	{"ip4:icmp", "0.0.0.0", "127.0.0.1"},
    87  	{"ip6:ipv6-icmp", "::", "::1"},
    88  }
    89  
    90  func TestConnICMPEcho(t *testing.T) {
    91  	if skip, skipmsg := skipRawSocketTest(t); skip {
    92  		t.Skip(skipmsg)
    93  	}
    94  
    95  	for i, tt := range icmpEchoTests {
    96  		net, _, err := parseNetwork(tt.net)
    97  		if err != nil {
    98  			t.Fatalf("parseNetwork failed: %v", err)
    99  		}
   100  		if net == "ip6" && !supportsIPv6 {
   101  			continue
   102  		}
   103  
   104  		c, err := Dial(tt.net, tt.raddr)
   105  		if err != nil {
   106  			t.Fatalf("Dial failed: %v", err)
   107  		}
   108  		c.SetDeadline(time.Now().Add(100 * time.Millisecond))
   109  		defer c.Close()
   110  
   111  		typ := icmpv4EchoRequest
   112  		if net == "ip6" {
   113  			typ = icmpv6EchoRequest
   114  		}
   115  		xid, xseq := os.Getpid()&0xffff, i+1
   116  		wb, err := (&icmpMessage{
   117  			Type: typ, Code: 0,
   118  			Body: &icmpEcho{
   119  				ID: xid, Seq: xseq,
   120  				Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
   121  			},
   122  		}).Marshal()
   123  		if err != nil {
   124  			t.Fatalf("icmpMessage.Marshal failed: %v", err)
   125  		}
   126  		if _, err := c.Write(wb); err != nil {
   127  			t.Fatalf("Conn.Write failed: %v", err)
   128  		}
   129  		var m *icmpMessage
   130  		rb := make([]byte, 20+len(wb))
   131  		for {
   132  			if _, err := c.Read(rb); err != nil {
   133  				t.Fatalf("Conn.Read failed: %v", err)
   134  			}
   135  			if net == "ip4" {
   136  				rb = ipv4Payload(rb)
   137  			}
   138  			if m, err = parseICMPMessage(rb); err != nil {
   139  				t.Fatalf("parseICMPMessage failed: %v", err)
   140  			}
   141  			switch m.Type {
   142  			case icmpv4EchoRequest, icmpv6EchoRequest:
   143  				continue
   144  			}
   145  			break
   146  		}
   147  		switch p := m.Body.(type) {
   148  		case *icmpEcho:
   149  			if p.ID != xid || p.Seq != xseq {
   150  				t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
   151  			}
   152  		default:
   153  			t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
   154  		}
   155  	}
   156  }
   157  
   158  func TestPacketConnICMPEcho(t *testing.T) {
   159  	if skip, skipmsg := skipRawSocketTest(t); skip {
   160  		t.Skip(skipmsg)
   161  	}
   162  
   163  	for i, tt := range icmpEchoTests {
   164  		net, _, err := parseNetwork(tt.net)
   165  		if err != nil {
   166  			t.Fatalf("parseNetwork failed: %v", err)
   167  		}
   168  		if net == "ip6" && !supportsIPv6 {
   169  			continue
   170  		}
   171  
   172  		c, err := ListenPacket(tt.net, tt.laddr)
   173  		if err != nil {
   174  			t.Fatalf("ListenPacket failed: %v", err)
   175  		}
   176  		c.SetDeadline(time.Now().Add(100 * time.Millisecond))
   177  		defer c.Close()
   178  
   179  		ra, err := ResolveIPAddr(tt.net, tt.raddr)
   180  		if err != nil {
   181  			t.Fatalf("ResolveIPAddr failed: %v", err)
   182  		}
   183  		typ := icmpv4EchoRequest
   184  		if net == "ip6" {
   185  			typ = icmpv6EchoRequest
   186  		}
   187  		xid, xseq := os.Getpid()&0xffff, i+1
   188  		wb, err := (&icmpMessage{
   189  			Type: typ, Code: 0,
   190  			Body: &icmpEcho{
   191  				ID: xid, Seq: xseq,
   192  				Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
   193  			},
   194  		}).Marshal()
   195  		if err != nil {
   196  			t.Fatalf("icmpMessage.Marshal failed: %v", err)
   197  		}
   198  		if _, err := c.WriteTo(wb, ra); err != nil {
   199  			t.Fatalf("PacketConn.WriteTo failed: %v", err)
   200  		}
   201  		var m *icmpMessage
   202  		rb := make([]byte, 20+len(wb))
   203  		for {
   204  			if _, _, err := c.ReadFrom(rb); err != nil {
   205  				t.Fatalf("PacketConn.ReadFrom failed: %v", err)
   206  			}
   207  			// See BUG section.
   208  			//if net == "ip4" {
   209  			//	rb = ipv4Payload(rb)
   210  			//}
   211  			if m, err = parseICMPMessage(rb); err != nil {
   212  				t.Fatalf("parseICMPMessage failed: %v", err)
   213  			}
   214  			switch m.Type {
   215  			case icmpv4EchoRequest, icmpv6EchoRequest:
   216  				continue
   217  			}
   218  			break
   219  		}
   220  		switch p := m.Body.(type) {
   221  		case *icmpEcho:
   222  			if p.ID != xid || p.Seq != xseq {
   223  				t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
   224  			}
   225  		default:
   226  			t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
   227  		}
   228  	}
   229  }
   230  
   231  func ipv4Payload(b []byte) []byte {
   232  	if len(b) < 20 {
   233  		return b
   234  	}
   235  	hdrlen := int(b[0]&0x0f) << 2
   236  	return b[hdrlen:]
   237  }
   238  
   239  var ipConnLocalNameTests = []struct {
   240  	net   string
   241  	laddr *IPAddr
   242  }{
   243  	{"ip4:icmp", &IPAddr{IP: IPv4(127, 0, 0, 1)}},
   244  	{"ip4:icmp", &IPAddr{}},
   245  	{"ip4:icmp", nil},
   246  }
   247  
   248  func TestIPConnLocalName(t *testing.T) {
   249  	switch runtime.GOOS {
   250  	case "plan9", "windows":
   251  		t.Skipf("skipping test on %q", runtime.GOOS)
   252  	default:
   253  		if os.Getuid() != 0 {
   254  			t.Skip("skipping test; must be root")
   255  		}
   256  	}
   257  
   258  	for _, tt := range ipConnLocalNameTests {
   259  		c, err := ListenIP(tt.net, tt.laddr)
   260  		if err != nil {
   261  			t.Fatalf("ListenIP failed: %v", err)
   262  		}
   263  		defer c.Close()
   264  		if la := c.LocalAddr(); la == nil {
   265  			t.Fatal("IPConn.LocalAddr failed")
   266  		}
   267  	}
   268  }
   269  
   270  func TestIPConnRemoteName(t *testing.T) {
   271  	switch runtime.GOOS {
   272  	case "plan9", "windows":
   273  		t.Skipf("skipping test on %q", runtime.GOOS)
   274  	default:
   275  		if os.Getuid() != 0 {
   276  			t.Skip("skipping test; must be root")
   277  		}
   278  	}
   279  
   280  	raddr := &IPAddr{IP: IPv4(127, 0, 0, 10).To4()}
   281  	c, err := DialIP("ip:tcp", &IPAddr{IP: IPv4(127, 0, 0, 1)}, raddr)
   282  	if err != nil {
   283  		t.Fatalf("DialIP failed: %v", err)
   284  	}
   285  	defer c.Close()
   286  	if !reflect.DeepEqual(raddr, c.RemoteAddr()) {
   287  		t.Fatalf("got %#v, expected %#v", c.RemoteAddr(), raddr)
   288  	}
   289  }