1// Copyright 2013 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 ipv6_test
6
7import (
8	"net"
9	"runtime"
10	"testing"
11
12	"golang.org/x/net/internal/iana"
13	"golang.org/x/net/ipv6"
14	"golang.org/x/net/nettest"
15)
16
17func TestConnUnicastSocketOptions(t *testing.T) {
18	switch runtime.GOOS {
19	case "fuchsia", "hurd", "js", "nacl", "plan9", "windows":
20		t.Skipf("not supported on %s", runtime.GOOS)
21	}
22	if !nettest.SupportsIPv6() {
23		t.Skip("ipv6 is not supported")
24	}
25
26	ln, err := net.Listen("tcp6", "[::1]:0")
27	if err != nil {
28		t.Fatal(err)
29	}
30	defer ln.Close()
31
32	errc := make(chan error, 1)
33	go func() {
34		c, err := ln.Accept()
35		if err != nil {
36			errc <- err
37			return
38		}
39		errc <- c.Close()
40	}()
41
42	c, err := net.Dial("tcp6", ln.Addr().String())
43	if err != nil {
44		t.Fatal(err)
45	}
46	defer c.Close()
47
48	testUnicastSocketOptions(t, ipv6.NewConn(c))
49
50	if err := <-errc; err != nil {
51		t.Errorf("server: %v", err)
52	}
53}
54
55var packetConnUnicastSocketOptionTests = []struct {
56	net, proto, addr string
57}{
58	{"udp6", "", "[::1]:0"},
59	{"ip6", ":ipv6-icmp", "::1"},
60}
61
62func TestPacketConnUnicastSocketOptions(t *testing.T) {
63	switch runtime.GOOS {
64	case "fuchsia", "hurd", "js", "nacl", "plan9", "windows":
65		t.Skipf("not supported on %s", runtime.GOOS)
66	}
67	if !nettest.SupportsIPv6() {
68		t.Skip("ipv6 is not supported")
69	}
70
71	ok := nettest.SupportsRawSocket()
72	for _, tt := range packetConnUnicastSocketOptionTests {
73		if tt.net == "ip6" && !ok {
74			t.Logf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
75			continue
76		}
77		c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
78		if err != nil {
79			t.Fatal(err)
80		}
81		defer c.Close()
82
83		testUnicastSocketOptions(t, ipv6.NewPacketConn(c))
84	}
85}
86
87type testIPv6UnicastConn interface {
88	TrafficClass() (int, error)
89	SetTrafficClass(int) error
90	HopLimit() (int, error)
91	SetHopLimit(int) error
92}
93
94func testUnicastSocketOptions(t *testing.T, c testIPv6UnicastConn) {
95	t.Helper()
96
97	tclass := iana.DiffServCS0 | iana.NotECNTransport
98	if err := c.SetTrafficClass(tclass); err != nil {
99		switch runtime.GOOS {
100		case "darwin": // older darwin kernels don't support IPV6_TCLASS option
101			t.Logf("not supported on %s", runtime.GOOS)
102			goto next
103		}
104		t.Fatal(err)
105	}
106	if v, err := c.TrafficClass(); err != nil {
107		t.Fatal(err)
108	} else if v != tclass {
109		t.Fatalf("got %v; want %v", v, tclass)
110	}
111
112next:
113	hoplim := 255
114	if err := c.SetHopLimit(hoplim); err != nil {
115		t.Fatal(err)
116	}
117	if v, err := c.HopLimit(); err != nil {
118		t.Fatal(err)
119	} else if v != hoplim {
120		t.Fatalf("got %v; want %v", v, hoplim)
121	}
122}
123