Browse Source

ipv6: add support for solaris

This change adds support for Solaris.

To read and write IPv6 ancillary data using ControlMessage, ipv6 pacakge
requires https://go-review.googlesource.com/30171/

Note: Unlike other platforms, Solaris seems to have a few restrictions
on ICMP property access via raw IP sockets. At least applications are
prohibited from using IPV6_CHECKSUM option for ICMP transport.

Fixes golang/go#17324.

Change-Id: Ie014665d94ae6e4955c95d3eea88db90332e20bd
Reviewed-on: https://go-review.googlesource.com/30176
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Mikio Hara 9 years ago
parent
commit
a7769702ac

+ 1 - 1
ipv6/control_rfc3542_unix.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package ipv6
 

+ 1 - 1
ipv6/control_stub.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build nacl plan9 solaris
+// +build nacl plan9
 
 package ipv6
 

+ 1 - 1
ipv6/control_unix.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package ipv6
 

+ 22 - 4
ipv6/defs_solaris.go

@@ -9,6 +9,8 @@
 package ipv6
 
 /*
+#include <sys/socket.h>
+
 #include <netinet/in.h>
 #include <netinet/icmp6.h>
 */
@@ -53,6 +55,13 @@ const (
 
 	sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
 
+	sysMCAST_JOIN_GROUP         = C.MCAST_JOIN_GROUP
+	sysMCAST_LEAVE_GROUP        = C.MCAST_LEAVE_GROUP
+	sysMCAST_BLOCK_SOURCE       = C.MCAST_BLOCK_SOURCE
+	sysMCAST_UNBLOCK_SOURCE     = C.MCAST_UNBLOCK_SOURCE
+	sysMCAST_JOIN_SOURCE_GROUP  = C.MCAST_JOIN_SOURCE_GROUP
+	sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
+
 	sysIPV6_PREFER_SRC_HOME   = C.IPV6_PREFER_SRC_HOME
 	sysIPV6_PREFER_SRC_COA    = C.IPV6_PREFER_SRC_COA
 	sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
@@ -76,15 +85,20 @@ const (
 
 	sysICMP6_FILTER = C.ICMP6_FILTER
 
-	sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
-	sysSizeofInet6Pktinfo  = C.sizeof_struct_in6_pktinfo
-	sysSizeofIPv6Mtuinfo   = C.sizeof_struct_ip6_mtuinfo
+	sysSizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+	sysSizeofSockaddrInet6   = C.sizeof_struct_sockaddr_in6
+	sysSizeofInet6Pktinfo    = C.sizeof_struct_in6_pktinfo
+	sysSizeofIPv6Mtuinfo     = C.sizeof_struct_ip6_mtuinfo
 
-	sysSizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+	sysSizeofIPv6Mreq       = C.sizeof_struct_ipv6_mreq
+	sysSizeofGroupReq       = C.sizeof_struct_group_req
+	sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
 
 	sysSizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
 )
 
+type sysSockaddrStorage C.struct_sockaddr_storage
+
 type sysSockaddrInet6 C.struct_sockaddr_in6
 
 type sysInet6Pktinfo C.struct_in6_pktinfo
@@ -93,4 +107,8 @@ type sysIPv6Mtuinfo C.struct_ip6_mtuinfo
 
 type sysIPv6Mreq C.struct_ipv6_mreq
 
+type sysGroupReq C.struct_group_req
+
+type sysGroupSourceReq C.struct_group_source_req
+
 type sysICMPv6Filter C.struct_icmp6_filter

+ 1 - 1
ipv6/dgramopt_posix.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows solaris
 
 package ipv6
 

+ 1 - 1
ipv6/dgramopt_stub.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build nacl plan9 solaris
+// +build nacl plan9
 
 package ipv6
 

+ 1 - 1
ipv6/genericopt_posix.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
 
 package ipv6
 

+ 1 - 1
ipv6/genericopt_stub.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build nacl plan9 solaris
+// +build nacl plan9
 
 package ipv6
 

+ 10 - 5
ipv6/icmp_solaris.go

@@ -7,18 +7,23 @@
 package ipv6
 
 func (f *sysICMPv6Filter) accept(typ ICMPType) {
-	// TODO(mikio): implement this
+	f.X__icmp6_filt[typ>>5] |= 1 << (uint32(typ) & 31)
 }
 
 func (f *sysICMPv6Filter) block(typ ICMPType) {
-	// TODO(mikio): implement this
+	f.X__icmp6_filt[typ>>5] &^= 1 << (uint32(typ) & 31)
 }
 
 func (f *sysICMPv6Filter) setAll(block bool) {
-	// TODO(mikio): implement this
+	for i := range f.X__icmp6_filt {
+		if block {
+			f.X__icmp6_filt[i] = 0
+		} else {
+			f.X__icmp6_filt[i] = 1<<32 - 1
+		}
+	}
 }
 
 func (f *sysICMPv6Filter) willBlock(typ ICMPType) bool {
-	// TODO(mikio): implement this
-	return false
+	return f.X__icmp6_filt[typ>>5]&(1<<(uint32(typ)&31)) == 0
 }

+ 2 - 2
ipv6/icmp_test.go

@@ -34,7 +34,7 @@ func TestICMPString(t *testing.T) {
 
 func TestICMPFilter(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 
@@ -61,7 +61,7 @@ func TestICMPFilter(t *testing.T) {
 
 func TestSetICMPFilter(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {

+ 7 - 3
ipv6/multicast_test.go

@@ -32,7 +32,7 @@ func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
 	case "freebsd": // due to a bug on loopback marking
 		// See http://www.freebsd.org/cgi/query-pr.cgi?pr=180065.
 		t.Skipf("not supported on %s", runtime.GOOS)
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -132,7 +132,7 @@ func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
 	case "freebsd": // due to a bug on loopback marking
 		// See http://www.freebsd.org/cgi/query-pr.cgi?pr=180065.
 		t.Skipf("not supported on %s", runtime.GOOS)
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -205,7 +205,11 @@ func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
 			if toggle {
 				psh = nil
 				if err := p.SetChecksum(true, 2); err != nil {
-					t.Fatal(err)
+					// Solaris never allows to
+					// modify ICMP properties.
+					if runtime.GOOS != "solaris" {
+						t.Fatal(err)
+					}
 				}
 			} else {
 				psh = pshicmp

+ 5 - 5
ipv6/multicastlistener_test.go

@@ -22,7 +22,7 @@ var udpMultipleGroupListenerTests = []net.Addr{
 
 func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -62,7 +62,7 @@ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
 
 func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -114,7 +114,7 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
 
 func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -157,7 +157,7 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
 
 func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -201,7 +201,7 @@ func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
 	switch runtime.GOOS {
 	case "darwin", "dragonfly", "openbsd": // platforms that return fe80::1%lo0: bind: can't assign requested address
 		t.Skipf("not supported on %s", runtime.GOOS)
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {

+ 1 - 1
ipv6/multicastsockopt_test.go

@@ -26,7 +26,7 @@ var packetConnMulticastSocketOptionTests = []struct {
 
 func TestPacketConnMulticastSocketOptions(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {

+ 1 - 1
ipv6/readwrite_test.go

@@ -102,7 +102,7 @@ func benchmarkReadWriteIPv6UDP(b *testing.B, p *ipv6.PacketConn, wb, rb []byte,
 
 func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {

+ 1 - 1
ipv6/sockopt_asmreq_posix.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
 
 package ipv6
 

+ 1 - 1
ipv6/sockopt_posix.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
 
 package ipv6
 

+ 1 - 1
ipv6/sockopt_ssmreq_stub.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !darwin,!freebsd,!linux
+// +build !darwin,!freebsd,!linux,!solaris
 
 package ipv6
 

+ 1 - 1
ipv6/sockopt_ssmreq_unix.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux
+// +build darwin freebsd linux solaris
 
 package ipv6
 

+ 1 - 1
ipv6/sockopt_stub.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build nacl plan9 solaris
+// +build nacl plan9
 
 package ipv6
 

+ 3 - 3
ipv6/sockopt_test.go

@@ -19,7 +19,7 @@ var supportsIPv6 bool = nettest.SupportsIPv6()
 
 func TestConnInitiatorPathMTU(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -57,7 +57,7 @@ func TestConnInitiatorPathMTU(t *testing.T) {
 
 func TestConnResponderPathMTU(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -95,7 +95,7 @@ func TestConnResponderPathMTU(t *testing.T) {
 
 func TestPacketConnChecksum(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {

+ 73 - 0
ipv6/sys_solaris.go

@@ -0,0 +1,73 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ipv6
+
+import (
+	"net"
+	"syscall"
+	"unsafe"
+
+	"golang.org/x/net/internal/iana"
+)
+
+var (
+	ctlOpts = [ctlMax]ctlOpt{
+		ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
+		ctlHopLimit:     {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
+		ctlPacketInfo:   {sysIPV6_PKTINFO, sysSizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
+		ctlNextHop:      {sysIPV6_NEXTHOP, sysSizeofSockaddrInet6, marshalNextHop, parseNextHop},
+		ctlPathMTU:      {sysIPV6_PATHMTU, sysSizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU},
+	}
+
+	sockOpts = [ssoMax]sockOpt{
+		ssoTrafficClass:        {iana.ProtocolIPv6, sysIPV6_TCLASS, ssoTypeInt},
+		ssoHopLimit:            {iana.ProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
+		ssoMulticastInterface:  {iana.ProtocolIPv6, sysIPV6_MULTICAST_IF, ssoTypeInterface},
+		ssoMulticastHopLimit:   {iana.ProtocolIPv6, sysIPV6_MULTICAST_HOPS, ssoTypeInt},
+		ssoMulticastLoopback:   {iana.ProtocolIPv6, sysIPV6_MULTICAST_LOOP, ssoTypeInt},
+		ssoReceiveTrafficClass: {iana.ProtocolIPv6, sysIPV6_RECVTCLASS, ssoTypeInt},
+		ssoReceiveHopLimit:     {iana.ProtocolIPv6, sysIPV6_RECVHOPLIMIT, ssoTypeInt},
+		ssoReceivePacketInfo:   {iana.ProtocolIPv6, sysIPV6_RECVPKTINFO, ssoTypeInt},
+		ssoReceivePathMTU:      {iana.ProtocolIPv6, sysIPV6_RECVPATHMTU, ssoTypeInt},
+		ssoPathMTU:             {iana.ProtocolIPv6, sysIPV6_PATHMTU, ssoTypeMTUInfo},
+		ssoChecksum:            {iana.ProtocolIPv6, sysIPV6_CHECKSUM, ssoTypeInt},
+		ssoICMPFilter:          {iana.ProtocolIPv6ICMP, sysICMP6_FILTER, ssoTypeICMPFilter},
+		ssoJoinGroup:           {iana.ProtocolIPv6, sysMCAST_JOIN_GROUP, ssoTypeGroupReq},
+		ssoLeaveGroup:          {iana.ProtocolIPv6, sysMCAST_LEAVE_GROUP, ssoTypeGroupReq},
+		ssoJoinSourceGroup:     {iana.ProtocolIPv6, sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq},
+		ssoLeaveSourceGroup:    {iana.ProtocolIPv6, sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq},
+		ssoBlockSourceGroup:    {iana.ProtocolIPv6, sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq},
+		ssoUnblockSourceGroup:  {iana.ProtocolIPv6, sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq},
+	}
+)
+
+func (sa *sysSockaddrInet6) setSockaddr(ip net.IP, i int) {
+	sa.Family = syscall.AF_INET6
+	copy(sa.Addr[:], ip)
+	sa.Scope_id = uint32(i)
+}
+
+func (pi *sysInet6Pktinfo) setIfindex(i int) {
+	pi.Ifindex = uint32(i)
+}
+
+func (mreq *sysIPv6Mreq) setIfindex(i int) {
+	mreq.Interface = uint32(i)
+}
+
+func (gr *sysGroupReq) setGroup(grp net.IP) {
+	sa := (*sysSockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gr)) + 4))
+	sa.Family = syscall.AF_INET6
+	copy(sa.Addr[:], grp)
+}
+
+func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
+	sa := (*sysSockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 4))
+	sa.Family = syscall.AF_INET6
+	copy(sa.Addr[:], grp)
+	sa = (*sysSockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 260))
+	sa.Family = syscall.AF_INET6
+	copy(sa.Addr[:], src)
+}

+ 8 - 0
ipv6/sys_solaris_amd64.s

@@ -0,0 +1,8 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT ·sysvicall6(SB),NOSPLIT,$0-88
+	JMP	syscall·sysvicall6(SB)

+ 1 - 1
ipv6/sys_stub.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build nacl plan9 solaris
+// +build nacl plan9
 
 package ipv6
 

+ 40 - 0
ipv6/syscall_solaris.go

@@ -0,0 +1,40 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+package ipv6
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+//go:cgo_import_dynamic libc___xnet_getsockopt __xnet_getsockopt "libsocket.so"
+//go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so"
+
+//go:linkname procGetsockopt libc___xnet_getsockopt
+//go:linkname procSetsockopt libc_setsockopt
+
+var (
+	procGetsockopt uintptr
+	procSetsockopt uintptr
+)
+
+func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno)
+
+func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
+	_, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procGetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0)
+	if errno != 0 {
+		return error(errno)
+	}
+	return nil
+}
+
+func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
+	if _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procSetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
+		return error(errno)
+	}
+	return nil
+}

+ 7 - 3
ipv6/unicast_test.go

@@ -20,7 +20,7 @@ import (
 
 func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -81,7 +81,7 @@ func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
 
 func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -127,7 +127,11 @@ func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
 		if toggle {
 			psh = nil
 			if err := p.SetChecksum(true, 2); err != nil {
-				t.Fatal(err)
+				// Solaris never allows to modify
+				// ICMP properties.
+				if runtime.GOOS != "solaris" {
+					t.Fatal(err)
+				}
 			}
 		} else {
 			psh = pshicmp

+ 2 - 2
ipv6/unicastsockopt_test.go

@@ -16,7 +16,7 @@ import (
 
 func TestConnUnicastSocketOptions(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {
@@ -52,7 +52,7 @@ var packetConnUnicastSocketOptionTests = []struct {
 
 func TestPacketConnUnicastSocketOptions(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9", "solaris", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 	if !supportsIPv6 {

+ 32 - 4
ipv6/zsys_solaris.go

@@ -44,6 +44,13 @@ const (
 
 	sysIPV6_RECVDSTOPTS = 0x28
 
+	sysMCAST_JOIN_GROUP         = 0x29
+	sysMCAST_LEAVE_GROUP        = 0x2a
+	sysMCAST_BLOCK_SOURCE       = 0x2b
+	sysMCAST_UNBLOCK_SOURCE     = 0x2c
+	sysMCAST_JOIN_SOURCE_GROUP  = 0x2d
+	sysMCAST_LEAVE_SOURCE_GROUP = 0x2e
+
 	sysIPV6_PREFER_SRC_HOME   = 0x1
 	sysIPV6_PREFER_SRC_COA    = 0x2
 	sysIPV6_PREFER_SRC_PUBLIC = 0x4
@@ -67,15 +74,25 @@ const (
 
 	sysICMP6_FILTER = 0x1
 
-	sysSizeofSockaddrInet6 = 0x20
-	sysSizeofInet6Pktinfo  = 0x14
-	sysSizeofIPv6Mtuinfo   = 0x24
+	sysSizeofSockaddrStorage = 0x100
+	sysSizeofSockaddrInet6   = 0x20
+	sysSizeofInet6Pktinfo    = 0x14
+	sysSizeofIPv6Mtuinfo     = 0x24
 
-	sysSizeofIPv6Mreq = 0x14
+	sysSizeofIPv6Mreq       = 0x14
+	sysSizeofGroupReq       = 0x104
+	sysSizeofGroupSourceReq = 0x204
 
 	sysSizeofICMPv6Filter = 0x20
 )
 
+type sysSockaddrStorage struct {
+	Family     uint16
+	X_ss_pad1  [6]int8
+	X_ss_align float64
+	X_ss_pad2  [240]int8
+}
+
 type sysSockaddrInet6 struct {
 	Family         uint16
 	Port           uint16
@@ -100,6 +117,17 @@ type sysIPv6Mreq struct {
 	Interface uint32
 }
 
+type sysGroupReq struct {
+	Interface uint32
+	Pad_cgo_0 [256]byte
+}
+
+type sysGroupSourceReq struct {
+	Interface uint32
+	Pad_cgo_0 [256]byte
+	Pad_cgo_1 [256]byte
+}
+
 type sysICMPv6Filter struct {
 	X__icmp6_filt [8]uint32
 }