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
5package net
6
7import (
8	"internal/testenv"
9	"reflect"
10	"testing"
11)
12
13// The full stack test cases for IPConn have been moved to the
14// following:
15//	golang.org/x/net/ipv4
16//	golang.org/x/net/ipv6
17//	golang.org/x/net/icmp
18
19type resolveIPAddrTest struct {
20	network       string
21	litAddrOrName string
22	addr          *IPAddr
23	err           error
24}
25
26var resolveIPAddrTests = []resolveIPAddrTest{
27	{"ip", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
28	{"ip4", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
29	{"ip4:icmp", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
30
31	{"ip", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
32	{"ip6", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
33	{"ip6:ipv6-icmp", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
34	{"ip6:IPv6-ICMP", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
35
36	{"ip", "::1%en0", &IPAddr{IP: ParseIP("::1"), Zone: "en0"}, nil},
37	{"ip6", "::1%911", &IPAddr{IP: ParseIP("::1"), Zone: "911"}, nil},
38
39	{"", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, // Go 1.0 behavior
40	{"", "::1", &IPAddr{IP: ParseIP("::1")}, nil},           // Go 1.0 behavior
41
42	{"ip4:icmp", "", &IPAddr{}, nil},
43
44	{"l2tp", "127.0.0.1", nil, UnknownNetworkError("l2tp")},
45	{"l2tp:gre", "127.0.0.1", nil, UnknownNetworkError("l2tp:gre")},
46	{"tcp", "1.2.3.4:123", nil, UnknownNetworkError("tcp")},
47
48	{"ip4", "2001:db8::1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
49	{"ip4:icmp", "2001:db8::1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
50	{"ip6", "127.0.0.1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
51	{"ip6", "::ffff:127.0.0.1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
52	{"ip6:ipv6-icmp", "127.0.0.1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
53	{"ip6:ipv6-icmp", "::ffff:127.0.0.1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
54}
55
56func TestResolveIPAddr(t *testing.T) {
57	if !testableNetwork("ip+nopriv") {
58		t.Skip("ip+nopriv test")
59	}
60
61	origTestHookLookupIP := testHookLookupIP
62	defer func() { testHookLookupIP = origTestHookLookupIP }()
63	testHookLookupIP = lookupLocalhost
64
65	for _, tt := range resolveIPAddrTests {
66		addr, err := ResolveIPAddr(tt.network, tt.litAddrOrName)
67		if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) {
68			t.Errorf("ResolveIPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err)
69			continue
70		}
71		if err == nil {
72			addr2, err := ResolveIPAddr(addr.Network(), addr.String())
73			if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err {
74				t.Errorf("(%q, %q): ResolveIPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err)
75			}
76		}
77	}
78}
79
80var ipConnLocalNameTests = []struct {
81	net   string
82	laddr *IPAddr
83}{
84	{"ip4:icmp", &IPAddr{IP: IPv4(127, 0, 0, 1)}},
85	{"ip4:icmp", &IPAddr{}},
86	{"ip4:icmp", nil},
87}
88
89func TestIPConnLocalName(t *testing.T) {
90	for _, tt := range ipConnLocalNameTests {
91		if !testableNetwork(tt.net) {
92			t.Logf("skipping %s test", tt.net)
93			continue
94		}
95		c, err := ListenIP(tt.net, tt.laddr)
96		if testenv.SyscallIsNotSupported(err) {
97			// May be inside a container that disallows creating a socket.
98			t.Logf("skipping %s test: %v", tt.net, err)
99			continue
100		} else if err != nil {
101			t.Fatal(err)
102		}
103		defer c.Close()
104		if la := c.LocalAddr(); la == nil {
105			t.Fatal("should not fail")
106		}
107	}
108}
109
110func TestIPConnRemoteName(t *testing.T) {
111	network := "ip:tcp"
112	if !testableNetwork(network) {
113		t.Skipf("skipping %s test", network)
114	}
115
116	raddr := &IPAddr{IP: IPv4(127, 0, 0, 1).To4()}
117	c, err := DialIP(network, &IPAddr{IP: IPv4(127, 0, 0, 1)}, raddr)
118	if testenv.SyscallIsNotSupported(err) {
119		// May be inside a container that disallows creating a socket.
120		t.Skipf("skipping %s test: %v", network, err)
121	} else if err != nil {
122		t.Fatal(err)
123	}
124	defer c.Close()
125	if !reflect.DeepEqual(raddr, c.RemoteAddr()) {
126		t.Fatalf("got %#v; want %#v", c.RemoteAddr(), raddr)
127	}
128}
129
130func TestDialListenIPArgs(t *testing.T) {
131	type test struct {
132		argLists   [][2]string
133		shouldFail bool
134	}
135	tests := []test{
136		{
137			argLists: [][2]string{
138				{"ip", "127.0.0.1"},
139				{"ip:", "127.0.0.1"},
140				{"ip::", "127.0.0.1"},
141				{"ip", "::1"},
142				{"ip:", "::1"},
143				{"ip::", "::1"},
144				{"ip4", "127.0.0.1"},
145				{"ip4:", "127.0.0.1"},
146				{"ip4::", "127.0.0.1"},
147				{"ip6", "::1"},
148				{"ip6:", "::1"},
149				{"ip6::", "::1"},
150			},
151			shouldFail: true,
152		},
153	}
154	if testableNetwork("ip") {
155		priv := test{shouldFail: false}
156		for _, tt := range []struct {
157			network, address string
158			args             [2]string
159		}{
160			{"ip4:47", "127.0.0.1", [2]string{"ip4:47", "127.0.0.1"}},
161			{"ip6:47", "::1", [2]string{"ip6:47", "::1"}},
162		} {
163			c, err := ListenPacket(tt.network, tt.address)
164			if err != nil {
165				continue
166			}
167			c.Close()
168			priv.argLists = append(priv.argLists, tt.args)
169		}
170		if len(priv.argLists) > 0 {
171			tests = append(tests, priv)
172		}
173	}
174
175	for _, tt := range tests {
176		for _, args := range tt.argLists {
177			_, err := Dial(args[0], args[1])
178			if tt.shouldFail != (err != nil) {
179				t.Errorf("Dial(%q, %q) = %v; want (err != nil) is %t", args[0], args[1], err, tt.shouldFail)
180			}
181			_, err = ListenPacket(args[0], args[1])
182			if tt.shouldFail != (err != nil) {
183				t.Errorf("ListenPacket(%q, %q) = %v; want (err != nil) is %t", args[0], args[1], err, tt.shouldFail)
184			}
185			a, err := ResolveIPAddr("ip", args[1])
186			if err != nil {
187				t.Errorf("ResolveIPAddr(\"ip\", %q) = %v", args[1], err)
188				continue
189			}
190			_, err = DialIP(args[0], nil, a)
191			if tt.shouldFail != (err != nil) {
192				t.Errorf("DialIP(%q, %v) = %v; want (err != nil) is %t", args[0], a, err, tt.shouldFail)
193			}
194			_, err = ListenIP(args[0], a)
195			if tt.shouldFail != (err != nil) {
196				t.Errorf("ListenIP(%q, %v) = %v; want (err != nil) is %t", args[0], a, err, tt.shouldFail)
197			}
198		}
199	}
200}
201