git » go-net » commit 7722dc0

ipv6: use of internal/netreflect package

author Mikio Hara
2016-08-24 21:40:08 UTC
committer Mikio Hara
2016-08-26 23:50:20 UTC
parent 7625277703ebeaf3dc01cb46c26ff09d76dcec89

ipv6: use of internal/netreflect package

Change-Id: Idb2a2eb354c2835e6cae7e269730c599abb1c8d7
Reviewed-on: https://go-review.googlesource.com/27735
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>

ipv6/bpfopt_linux.go +3 -2
ipv6/control_stub.go +1 -1
ipv6/control_unix.go +5 -5
ipv6/control_windows.go +1 -1
ipv6/dgramopt_posix.go +34 -32
ipv6/endpoint.go +6 -4
ipv6/genericopt_posix.go +13 -9
ipv6/helper_stub.go +0 -19
ipv6/helper_unix.go +0 -46
ipv6/helper_windows.go +0 -45
ipv6/sockopt_asmreq_unix.go +2 -2
ipv6/sockopt_asmreq_windows.go +2 -2
ipv6/sockopt_ssmreq_stub.go +2 -2
ipv6/sockopt_ssmreq_unix.go +4 -4
ipv6/sockopt_stub.go +1 -1
ipv6/sockopt_unix.go +19 -19
ipv6/sockopt_windows.go +14 -14
ipv6/syscall_linux_386.go +4 -4
ipv6/syscall_unix.go +4 -4

diff --git a/ipv6/bpfopt_linux.go b/ipv6/bpfopt_linux.go
index 066ef20..328427c 100644
--- a/ipv6/bpfopt_linux.go
+++ b/ipv6/bpfopt_linux.go
@@ -9,13 +9,14 @@ import (
 	"unsafe"
 
 	"golang.org/x/net/bpf"
+	"golang.org/x/net/internal/netreflect"
 )
 
 // SetBPF attaches a BPF program to the connection.
 //
 // Only supported on Linux.
 func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
@@ -23,5 +24,5 @@ func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
 		Len:    uint16(len(filter)),
 		Filter: (*sysSockFilter)(unsafe.Pointer(&filter[0])),
 	}
-	return os.NewSyscallError("setsockopt", setsockopt(fd, sysSOL_SOCKET, sysSO_ATTACH_FILTER, unsafe.Pointer(&prog), uint32(unsafe.Sizeof(prog))))
+	return os.NewSyscallError("setsockopt", setsockopt(s, sysSOL_SOCKET, sysSO_ATTACH_FILTER, unsafe.Pointer(&prog), uint32(unsafe.Sizeof(prog))))
 }
diff --git a/ipv6/control_stub.go b/ipv6/control_stub.go
index 2fecf7e..952b2bd 100644
--- a/ipv6/control_stub.go
+++ b/ipv6/control_stub.go
@@ -6,7 +6,7 @@
 
 package ipv6
 
-func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
+func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error {
 	return errOpNoSupport
 }
 
diff --git a/ipv6/control_unix.go b/ipv6/control_unix.go
index 2af5beb..46fbdcb 100644
--- a/ipv6/control_unix.go
+++ b/ipv6/control_unix.go
@@ -13,11 +13,11 @@ import (
 	"golang.org/x/net/internal/iana"
 )
 
-func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
+func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error {
 	opt.Lock()
 	defer opt.Unlock()
 	if cf&FlagTrafficClass != 0 && sockOpts[ssoReceiveTrafficClass].name > 0 {
-		if err := setInt(fd, &sockOpts[ssoReceiveTrafficClass], boolint(on)); err != nil {
+		if err := setInt(s, &sockOpts[ssoReceiveTrafficClass], boolint(on)); err != nil {
 			return err
 		}
 		if on {
@@ -27,7 +27,7 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
 		}
 	}
 	if cf&FlagHopLimit != 0 && sockOpts[ssoReceiveHopLimit].name > 0 {
-		if err := setInt(fd, &sockOpts[ssoReceiveHopLimit], boolint(on)); err != nil {
+		if err := setInt(s, &sockOpts[ssoReceiveHopLimit], boolint(on)); err != nil {
 			return err
 		}
 		if on {
@@ -37,7 +37,7 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
 		}
 	}
 	if cf&flagPacketInfo != 0 && sockOpts[ssoReceivePacketInfo].name > 0 {
-		if err := setInt(fd, &sockOpts[ssoReceivePacketInfo], boolint(on)); err != nil {
+		if err := setInt(s, &sockOpts[ssoReceivePacketInfo], boolint(on)); err != nil {
 			return err
 		}
 		if on {
@@ -47,7 +47,7 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
 		}
 	}
 	if cf&FlagPathMTU != 0 && sockOpts[ssoReceivePathMTU].name > 0 {
-		if err := setInt(fd, &sockOpts[ssoReceivePathMTU], boolint(on)); err != nil {
+		if err := setInt(s, &sockOpts[ssoReceivePathMTU], boolint(on)); err != nil {
 			return err
 		}
 		if on {
diff --git a/ipv6/control_windows.go b/ipv6/control_windows.go
index 72fdc1b..2773a52 100644
--- a/ipv6/control_windows.go
+++ b/ipv6/control_windows.go
@@ -6,7 +6,7 @@ package ipv6
 
 import "syscall"
 
-func setControlMessage(fd syscall.Handle, opt *rawOpt, cf ControlFlags, on bool) error {
+func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error {
 	// TODO(mikio): implement this
 	return syscall.EWINDOWS
 }
diff --git a/ipv6/dgramopt_posix.go b/ipv6/dgramopt_posix.go
index 93ff2f1..4ea7bc2 100644
--- a/ipv6/dgramopt_posix.go
+++ b/ipv6/dgramopt_posix.go
@@ -9,6 +9,8 @@ package ipv6
 import (
 	"net"
 	"syscall"
+
+	"golang.org/x/net/internal/netreflect"
 )
 
 // MulticastHopLimit returns the hop limit field value for outgoing
@@ -17,11 +19,11 @@ func (c *dgramOpt) MulticastHopLimit() (int, error) {
 	if !c.ok() {
 		return 0, syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return 0, err
 	}
-	return getInt(fd, &sockOpts[ssoMulticastHopLimit])
+	return getInt(s, &sockOpts[ssoMulticastHopLimit])
 }
 
 // SetMulticastHopLimit sets the hop limit field value for future
@@ -30,11 +32,11 @@ func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
-	return setInt(fd, &sockOpts[ssoMulticastHopLimit], hoplim)
+	return setInt(s, &sockOpts[ssoMulticastHopLimit], hoplim)
 }
 
 // MulticastInterface returns the default interface for multicast
@@ -43,11 +45,11 @@ func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
 	if !c.ok() {
 		return nil, syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return nil, err
 	}
-	return getInterface(fd, &sockOpts[ssoMulticastInterface])
+	return getInterface(s, &sockOpts[ssoMulticastInterface])
 }
 
 // SetMulticastInterface sets the default interface for future
@@ -56,11 +58,11 @@ func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
-	return setInterface(fd, &sockOpts[ssoMulticastInterface], ifi)
+	return setInterface(s, &sockOpts[ssoMulticastInterface], ifi)
 }
 
 // MulticastLoopback reports whether transmitted multicast packets
@@ -69,11 +71,11 @@ func (c *dgramOpt) MulticastLoopback() (bool, error) {
 	if !c.ok() {
 		return false, syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return false, err
 	}
-	on, err := getInt(fd, &sockOpts[ssoMulticastLoopback])
+	on, err := getInt(s, &sockOpts[ssoMulticastLoopback])
 	if err != nil {
 		return false, err
 	}
@@ -86,11 +88,11 @@ func (c *dgramOpt) SetMulticastLoopback(on bool) error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
-	return setInt(fd, &sockOpts[ssoMulticastLoopback], boolint(on))
+	return setInt(s, &sockOpts[ssoMulticastLoopback], boolint(on))
 }
 
 // JoinGroup joins the group address group on the interface ifi.
@@ -106,7 +108,7 @@ func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
@@ -114,7 +116,7 @@ func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
 	if grp == nil {
 		return errMissingAddress
 	}
-	return setGroup(fd, &sockOpts[ssoJoinGroup], ifi, grp)
+	return setGroup(s, &sockOpts[ssoJoinGroup], ifi, grp)
 }
 
 // LeaveGroup leaves the group address group on the interface ifi
@@ -124,7 +126,7 @@ func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
@@ -132,7 +134,7 @@ func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
 	if grp == nil {
 		return errMissingAddress
 	}
-	return setGroup(fd, &sockOpts[ssoLeaveGroup], ifi, grp)
+	return setGroup(s, &sockOpts[ssoLeaveGroup], ifi, grp)
 }
 
 // JoinSourceSpecificGroup joins the source-specific group comprising
@@ -145,7 +147,7 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
@@ -157,7 +159,7 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net
 	if src == nil {
 		return errMissingAddress
 	}
-	return setSourceGroup(fd, &sockOpts[ssoJoinSourceGroup], ifi, grp, src)
+	return setSourceGroup(s, &sockOpts[ssoJoinSourceGroup], ifi, grp, src)
 }
 
 // LeaveSourceSpecificGroup leaves the source-specific group on the
@@ -166,7 +168,7 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
@@ -178,7 +180,7 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne
 	if src == nil {
 		return errMissingAddress
 	}
-	return setSourceGroup(fd, &sockOpts[ssoLeaveSourceGroup], ifi, grp, src)
+	return setSourceGroup(s, &sockOpts[ssoLeaveSourceGroup], ifi, grp, src)
 }
 
 // ExcludeSourceSpecificGroup excludes the source-specific group from
@@ -188,7 +190,7 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
@@ -200,7 +202,7 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source
 	if src == nil {
 		return errMissingAddress
 	}
-	return setSourceGroup(fd, &sockOpts[ssoBlockSourceGroup], ifi, grp, src)
+	return setSourceGroup(s, &sockOpts[ssoBlockSourceGroup], ifi, grp, src)
 }
 
 // IncludeSourceSpecificGroup includes the excluded source-specific
@@ -209,7 +211,7 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
@@ -221,7 +223,7 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source
 	if src == nil {
 		return errMissingAddress
 	}
-	return setSourceGroup(fd, &sockOpts[ssoUnblockSourceGroup], ifi, grp, src)
+	return setSourceGroup(s, &sockOpts[ssoUnblockSourceGroup], ifi, grp, src)
 }
 
 // Checksum reports whether the kernel will compute, store or verify a
@@ -232,11 +234,11 @@ func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
 	if !c.ok() {
 		return false, 0, syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return false, 0, err
 	}
-	offset, err = getInt(fd, &sockOpts[ssoChecksum])
+	offset, err = getInt(s, &sockOpts[ssoChecksum])
 	if err != nil {
 		return false, 0, err
 	}
@@ -253,14 +255,14 @@ func (c *dgramOpt) SetChecksum(on bool, offset int) error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
 	if !on {
 		offset = -1
 	}
-	return setInt(fd, &sockOpts[ssoChecksum], offset)
+	return setInt(s, &sockOpts[ssoChecksum], offset)
 }
 
 // ICMPFilter returns an ICMP filter.
@@ -268,11 +270,11 @@ func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
 	if !c.ok() {
 		return nil, syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return nil, err
 	}
-	return getICMPFilter(fd, &sockOpts[ssoICMPFilter])
+	return getICMPFilter(s, &sockOpts[ssoICMPFilter])
 }
 
 // SetICMPFilter deploys the ICMP filter.
@@ -280,9 +282,9 @@ func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.PacketSocketOf(c.PacketConn)
 	if err != nil {
 		return err
 	}
-	return setICMPFilter(fd, &sockOpts[ssoICMPFilter], f)
+	return setICMPFilter(s, &sockOpts[ssoICMPFilter], f)
 }
diff --git a/ipv6/endpoint.go b/ipv6/endpoint.go
index 966eaa8..60e7d93 100644
--- a/ipv6/endpoint.go
+++ b/ipv6/endpoint.go
@@ -8,6 +8,8 @@ import (
 	"net"
 	"syscall"
 	"time"
+
+	"golang.org/x/net/internal/netreflect"
 )
 
 // A Conn represents a network endpoint that uses IPv6 transport.
@@ -29,11 +31,11 @@ func (c *Conn) PathMTU() (int, error) {
 	if !c.genericOpt.ok() {
 		return 0, syscall.EINVAL
 	}
-	fd, err := c.genericOpt.sysfd()
+	s, err := netreflect.SocketOf(c.genericOpt.Conn)
 	if err != nil {
 		return 0, err
 	}
-	_, mtu, err := getMTUInfo(fd, &sockOpts[ssoPathMTU])
+	_, mtu, err := getMTUInfo(s, &sockOpts[ssoPathMTU])
 	if err != nil {
 		return 0, err
 	}
@@ -70,11 +72,11 @@ func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error {
 	if !c.payloadHandler.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.payloadHandler.sysfd()
+	s, err := netreflect.PacketSocketOf(c.dgramOpt.PacketConn)
 	if err != nil {
 		return err
 	}
-	return setControlMessage(fd, &c.payloadHandler.rawOpt, cf, on)
+	return setControlMessage(s, &c.payloadHandler.rawOpt, cf, on)
 }
 
 // SetDeadline sets the read and write deadlines associated with the
diff --git a/ipv6/genericopt_posix.go b/ipv6/genericopt_posix.go
index dd77a01..513bd8c 100644
--- a/ipv6/genericopt_posix.go
+++ b/ipv6/genericopt_posix.go
@@ -6,7 +6,11 @@
 
 package ipv6
 
-import "syscall"
+import (
+	"syscall"
+
+	"golang.org/x/net/internal/netreflect"
+)
 
 // TrafficClass returns the traffic class field value for outgoing
 // packets.
@@ -14,11 +18,11 @@ func (c *genericOpt) TrafficClass() (int, error) {
 	if !c.ok() {
 		return 0, syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.SocketOf(c.Conn)
 	if err != nil {
 		return 0, err
 	}
-	return getInt(fd, &sockOpts[ssoTrafficClass])
+	return getInt(s, &sockOpts[ssoTrafficClass])
 }
 
 // SetTrafficClass sets the traffic class field value for future
@@ -27,11 +31,11 @@ func (c *genericOpt) SetTrafficClass(tclass int) error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.SocketOf(c.Conn)
 	if err != nil {
 		return err
 	}
-	return setInt(fd, &sockOpts[ssoTrafficClass], tclass)
+	return setInt(s, &sockOpts[ssoTrafficClass], tclass)
 }
 
 // HopLimit returns the hop limit field value for outgoing packets.
@@ -39,11 +43,11 @@ func (c *genericOpt) HopLimit() (int, error) {
 	if !c.ok() {
 		return 0, syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.SocketOf(c.Conn)
 	if err != nil {
 		return 0, err
 	}
-	return getInt(fd, &sockOpts[ssoHopLimit])
+	return getInt(s, &sockOpts[ssoHopLimit])
 }
 
 // SetHopLimit sets the hop limit field value for future outgoing
@@ -52,9 +56,9 @@ func (c *genericOpt) SetHopLimit(hoplim int) error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	fd, err := c.sysfd()
+	s, err := netreflect.SocketOf(c.Conn)
 	if err != nil {
 		return err
 	}
-	return setInt(fd, &sockOpts[ssoHopLimit], hoplim)
+	return setInt(s, &sockOpts[ssoHopLimit], hoplim)
 }
diff --git a/ipv6/helper_stub.go b/ipv6/helper_stub.go
deleted file mode 100644
index 20354ab..0000000
--- a/ipv6/helper_stub.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2013 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 nacl plan9 solaris
-
-package ipv6
-
-func (c *genericOpt) sysfd() (int, error) {
-	return 0, errOpNoSupport
-}
-
-func (c *dgramOpt) sysfd() (int, error) {
-	return 0, errOpNoSupport
-}
-
-func (c *payloadHandler) sysfd() (int, error) {
-	return 0, errOpNoSupport
-}
diff --git a/ipv6/helper_unix.go b/ipv6/helper_unix.go
deleted file mode 100644
index 92868ed..0000000
--- a/ipv6/helper_unix.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 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 darwin dragonfly freebsd linux netbsd openbsd
-
-package ipv6
-
-import (
-	"net"
-	"reflect"
-)
-
-func (c *genericOpt) sysfd() (int, error) {
-	switch p := c.Conn.(type) {
-	case *net.TCPConn, *net.UDPConn, *net.IPConn:
-		return sysfd(p)
-	}
-	return 0, errInvalidConnType
-}
-
-func (c *dgramOpt) sysfd() (int, error) {
-	switch p := c.PacketConn.(type) {
-	case *net.UDPConn, *net.IPConn:
-		return sysfd(p.(net.Conn))
-	}
-	return 0, errInvalidConnType
-}
-
-func (c *payloadHandler) sysfd() (int, error) {
-	return sysfd(c.PacketConn.(net.Conn))
-}
-
-func sysfd(c net.Conn) (int, error) {
-	cv := reflect.ValueOf(c)
-	switch ce := cv.Elem(); ce.Kind() {
-	case reflect.Struct:
-		nfd := ce.FieldByName("conn").FieldByName("fd")
-		switch fe := nfd.Elem(); fe.Kind() {
-		case reflect.Struct:
-			fd := fe.FieldByName("sysfd")
-			return int(fd.Int()), nil
-		}
-	}
-	return 0, errInvalidConnType
-}
diff --git a/ipv6/helper_windows.go b/ipv6/helper_windows.go
deleted file mode 100644
index 28c401b..0000000
--- a/ipv6/helper_windows.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 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"
-	"reflect"
-	"syscall"
-)
-
-func (c *genericOpt) sysfd() (syscall.Handle, error) {
-	switch p := c.Conn.(type) {
-	case *net.TCPConn, *net.UDPConn, *net.IPConn:
-		return sysfd(p)
-	}
-	return syscall.InvalidHandle, errInvalidConnType
-}
-
-func (c *dgramOpt) sysfd() (syscall.Handle, error) {
-	switch p := c.PacketConn.(type) {
-	case *net.UDPConn, *net.IPConn:
-		return sysfd(p.(net.Conn))
-	}
-	return syscall.InvalidHandle, errInvalidConnType
-}
-
-func (c *payloadHandler) sysfd() (syscall.Handle, error) {
-	return sysfd(c.PacketConn.(net.Conn))
-}
-
-func sysfd(c net.Conn) (syscall.Handle, error) {
-	cv := reflect.ValueOf(c)
-	switch ce := cv.Elem(); ce.Kind() {
-	case reflect.Struct:
-		netfd := ce.FieldByName("conn").FieldByName("fd")
-		switch fe := netfd.Elem(); fe.Kind() {
-		case reflect.Struct:
-			fd := fe.FieldByName("sysfd")
-			return syscall.Handle(fd.Uint()), nil
-		}
-	}
-	return syscall.InvalidHandle, errInvalidConnType
-}
diff --git a/ipv6/sockopt_asmreq_unix.go b/ipv6/sockopt_asmreq_unix.go
index b7fd4fe..4fcd7c5 100644
--- a/ipv6/sockopt_asmreq_unix.go
+++ b/ipv6/sockopt_asmreq_unix.go
@@ -12,11 +12,11 @@ import (
 	"unsafe"
 )
 
-func setsockoptIPMreq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
+func setsockoptIPMreq(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
 	var mreq sysIPv6Mreq
 	copy(mreq.Multiaddr[:], grp)
 	if ifi != nil {
 		mreq.setIfindex(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&mreq), sysSizeofIPv6Mreq))
+	return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, unsafe.Pointer(&mreq), sysSizeofIPv6Mreq))
 }
diff --git a/ipv6/sockopt_asmreq_windows.go b/ipv6/sockopt_asmreq_windows.go
index c03c731..88408ea 100644
--- a/ipv6/sockopt_asmreq_windows.go
+++ b/ipv6/sockopt_asmreq_windows.go
@@ -11,11 +11,11 @@ import (
 	"unsafe"
 )
 
-func setsockoptIPMreq(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
+func setsockoptIPMreq(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
 	var mreq sysIPv6Mreq
 	copy(mreq.Multiaddr[:], grp)
 	if ifi != nil {
 		mreq.setIfindex(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&mreq)), sysSizeofIPv6Mreq))
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(syscall.Handle(s), int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&mreq)), sysSizeofIPv6Mreq))
 }
diff --git a/ipv6/sockopt_ssmreq_stub.go b/ipv6/sockopt_ssmreq_stub.go
index 7732e49..a177232 100644
--- a/ipv6/sockopt_ssmreq_stub.go
+++ b/ipv6/sockopt_ssmreq_stub.go
@@ -8,10 +8,10 @@ package ipv6
 
 import "net"
 
-func setsockoptGroupReq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
+func setsockoptGroupReq(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
 	return errOpNoSupport
 }
 
-func setsockoptGroupSourceReq(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
+func setsockoptGroupSourceReq(s uintptr, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
 	return errOpNoSupport
 }
diff --git a/ipv6/sockopt_ssmreq_unix.go b/ipv6/sockopt_ssmreq_unix.go
index a36a7e0..88f118c 100644
--- a/ipv6/sockopt_ssmreq_unix.go
+++ b/ipv6/sockopt_ssmreq_unix.go
@@ -14,7 +14,7 @@ import (
 
 var freebsd32o64 bool
 
-func setsockoptGroupReq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
+func setsockoptGroupReq(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
 	var gr sysGroupReq
 	if ifi != nil {
 		gr.Interface = uint32(ifi.Index)
@@ -33,10 +33,10 @@ func setsockoptGroupReq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) er
 		p = unsafe.Pointer(&gr)
 		l = sysSizeofGroupReq
 	}
-	return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, p, l))
+	return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, p, l))
 }
 
-func setsockoptGroupSourceReq(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
+func setsockoptGroupSourceReq(s uintptr, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
 	var gsr sysGroupSourceReq
 	if ifi != nil {
 		gsr.Interface = uint32(ifi.Index)
@@ -55,5 +55,5 @@ func setsockoptGroupSourceReq(fd int, opt *sockOpt, ifi *net.Interface, grp, src
 		p = unsafe.Pointer(&gsr)
 		l = sysSizeofGroupSourceReq
 	}
-	return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, p, l))
+	return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, p, l))
 }
diff --git a/ipv6/sockopt_stub.go b/ipv6/sockopt_stub.go
index b8dacfd..b6b9c4b 100644
--- a/ipv6/sockopt_stub.go
+++ b/ipv6/sockopt_stub.go
@@ -8,6 +8,6 @@ package ipv6
 
 import "net"
 
-func getMTUInfo(fd int, opt *sockOpt) (*net.Interface, int, error) {
+func getMTUInfo(s uintptr, opt *sockOpt) (*net.Interface, int, error) {
 	return nil, 0, errOpNoSupport
 }
diff --git a/ipv6/sockopt_unix.go b/ipv6/sockopt_unix.go
index 7115b18..8563203 100644
--- a/ipv6/sockopt_unix.go
+++ b/ipv6/sockopt_unix.go
@@ -12,33 +12,33 @@ import (
 	"unsafe"
 )
 
-func getInt(fd int, opt *sockOpt) (int, error) {
+func getInt(s uintptr, opt *sockOpt) (int, error) {
 	if opt.name < 1 || opt.typ != ssoTypeInt {
 		return 0, errOpNoSupport
 	}
 	var i int32
 	l := uint32(4)
-	if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
+	if err := getsockopt(s, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
 		return 0, os.NewSyscallError("getsockopt", err)
 	}
 	return int(i), nil
 }
 
-func setInt(fd int, opt *sockOpt, v int) error {
+func setInt(s uintptr, opt *sockOpt, v int) error {
 	if opt.name < 1 || opt.typ != ssoTypeInt {
 		return errOpNoSupport
 	}
 	i := int32(v)
-	return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), 4))
+	return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, unsafe.Pointer(&i), 4))
 }
 
-func getInterface(fd int, opt *sockOpt) (*net.Interface, error) {
+func getInterface(s uintptr, opt *sockOpt) (*net.Interface, error) {
 	if opt.name < 1 || opt.typ != ssoTypeInterface {
 		return nil, errOpNoSupport
 	}
 	var i int32
 	l := uint32(4)
-	if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
+	if err := getsockopt(s, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
 		return nil, os.NewSyscallError("getsockopt", err)
 	}
 	if i == 0 {
@@ -51,7 +51,7 @@ func getInterface(fd int, opt *sockOpt) (*net.Interface, error) {
 	return ifi, nil
 }
 
-func setInterface(fd int, opt *sockOpt, ifi *net.Interface) error {
+func setInterface(s uintptr, opt *sockOpt, ifi *net.Interface) error {
 	if opt.name < 1 || opt.typ != ssoTypeInterface {
 		return errOpNoSupport
 	}
@@ -59,35 +59,35 @@ func setInterface(fd int, opt *sockOpt, ifi *net.Interface) error {
 	if ifi != nil {
 		i = int32(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), 4))
+	return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, unsafe.Pointer(&i), 4))
 }
 
-func getICMPFilter(fd int, opt *sockOpt) (*ICMPFilter, error) {
+func getICMPFilter(s uintptr, opt *sockOpt) (*ICMPFilter, error) {
 	if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
 		return nil, errOpNoSupport
 	}
 	var f ICMPFilter
 	l := uint32(sysSizeofICMPv6Filter)
-	if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), &l); err != nil {
+	if err := getsockopt(s, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), &l); err != nil {
 		return nil, os.NewSyscallError("getsockopt", err)
 	}
 	return &f, nil
 }
 
-func setICMPFilter(fd int, opt *sockOpt, f *ICMPFilter) error {
+func setICMPFilter(s uintptr, opt *sockOpt, f *ICMPFilter) error {
 	if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
 		return errOpNoSupport
 	}
-	return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), sysSizeofICMPv6Filter))
+	return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), sysSizeofICMPv6Filter))
 }
 
-func getMTUInfo(fd int, opt *sockOpt) (*net.Interface, int, error) {
+func getMTUInfo(s uintptr, opt *sockOpt) (*net.Interface, int, error) {
 	if opt.name < 1 || opt.typ != ssoTypeMTUInfo {
 		return nil, 0, errOpNoSupport
 	}
 	var mi sysIPv6Mtuinfo
 	l := uint32(sysSizeofIPv6Mtuinfo)
-	if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&mi), &l); err != nil {
+	if err := getsockopt(s, opt.level, opt.name, unsafe.Pointer(&mi), &l); err != nil {
 		return nil, 0, os.NewSyscallError("getsockopt", err)
 	}
 	if mi.Addr.Scope_id == 0 {
@@ -100,23 +100,23 @@ func getMTUInfo(fd int, opt *sockOpt) (*net.Interface, int, error) {
 	return ifi, int(mi.Mtu), nil
 }
 
-func setGroup(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
+func setGroup(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
 	if opt.name < 1 {
 		return errOpNoSupport
 	}
 	switch opt.typ {
 	case ssoTypeIPMreq:
-		return setsockoptIPMreq(fd, opt, ifi, grp)
+		return setsockoptIPMreq(s, opt, ifi, grp)
 	case ssoTypeGroupReq:
-		return setsockoptGroupReq(fd, opt, ifi, grp)
+		return setsockoptGroupReq(s, opt, ifi, grp)
 	default:
 		return errOpNoSupport
 	}
 }
 
-func setSourceGroup(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
+func setSourceGroup(s uintptr, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
 	if opt.name < 1 || opt.typ != ssoTypeGroupSourceReq {
 		return errOpNoSupport
 	}
-	return setsockoptGroupSourceReq(fd, opt, ifi, grp, src)
+	return setsockoptGroupSourceReq(s, opt, ifi, grp, src)
 }
diff --git a/ipv6/sockopt_windows.go b/ipv6/sockopt_windows.go
index 32c73b7..3e3331f 100644
--- a/ipv6/sockopt_windows.go
+++ b/ipv6/sockopt_windows.go
@@ -11,33 +11,33 @@ import (
 	"unsafe"
 )
 
-func getInt(fd syscall.Handle, opt *sockOpt) (int, error) {
+func getInt(s uintptr, opt *sockOpt) (int, error) {
 	if opt.name < 1 || opt.typ != ssoTypeInt {
 		return 0, errOpNoSupport
 	}
 	var i int32
 	l := int32(4)
-	if err := syscall.Getsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), &l); err != nil {
+	if err := syscall.Getsockopt(syscall.Handle(s), int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), &l); err != nil {
 		return 0, os.NewSyscallError("getsockopt", err)
 	}
 	return int(i), nil
 }
 
-func setInt(fd syscall.Handle, opt *sockOpt, v int) error {
+func setInt(s uintptr, opt *sockOpt, v int) error {
 	if opt.name < 1 || opt.typ != ssoTypeInt {
 		return errOpNoSupport
 	}
 	i := int32(v)
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), 4))
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(syscall.Handle(s), int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), 4))
 }
 
-func getInterface(fd syscall.Handle, opt *sockOpt) (*net.Interface, error) {
+func getInterface(s uintptr, opt *sockOpt) (*net.Interface, error) {
 	if opt.name < 1 || opt.typ != ssoTypeInterface {
 		return nil, errOpNoSupport
 	}
 	var i int32
 	l := int32(4)
-	if err := syscall.Getsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), &l); err != nil {
+	if err := syscall.Getsockopt(syscall.Handle(s), int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), &l); err != nil {
 		return nil, os.NewSyscallError("getsockopt", err)
 	}
 	if i == 0 {
@@ -50,7 +50,7 @@ func getInterface(fd syscall.Handle, opt *sockOpt) (*net.Interface, error) {
 	return ifi, nil
 }
 
-func setInterface(fd syscall.Handle, opt *sockOpt, ifi *net.Interface) error {
+func setInterface(s uintptr, opt *sockOpt, ifi *net.Interface) error {
 	if opt.name < 1 || opt.typ != ssoTypeInterface {
 		return errOpNoSupport
 	}
@@ -58,29 +58,29 @@ func setInterface(fd syscall.Handle, opt *sockOpt, ifi *net.Interface) error {
 	if ifi != nil {
 		i = int32(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), 4))
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(syscall.Handle(s), int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), 4))
 }
 
-func getICMPFilter(fd syscall.Handle, opt *sockOpt) (*ICMPFilter, error) {
+func getICMPFilter(s uintptr, opt *sockOpt) (*ICMPFilter, error) {
 	return nil, errOpNoSupport
 }
 
-func setICMPFilter(fd syscall.Handle, opt *sockOpt, f *ICMPFilter) error {
+func setICMPFilter(s uintptr, opt *sockOpt, f *ICMPFilter) error {
 	return errOpNoSupport
 }
 
-func getMTUInfo(fd syscall.Handle, opt *sockOpt) (*net.Interface, int, error) {
+func getMTUInfo(s uintptr, opt *sockOpt) (*net.Interface, int, error) {
 	return nil, 0, errOpNoSupport
 }
 
-func setGroup(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
+func setGroup(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
 	if opt.name < 1 || opt.typ != ssoTypeIPMreq {
 		return errOpNoSupport
 	}
-	return setsockoptIPMreq(fd, opt, ifi, grp)
+	return setsockoptIPMreq(s, opt, ifi, grp)
 }
 
-func setSourceGroup(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
+func setSourceGroup(s uintptr, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
 	// TODO(mikio): implement this
 	return errOpNoSupport
 }
diff --git a/ipv6/syscall_linux_386.go b/ipv6/syscall_linux_386.go
index 64a3c66..5184dbe 100644
--- a/ipv6/syscall_linux_386.go
+++ b/ipv6/syscall_linux_386.go
@@ -16,15 +16,15 @@ const (
 
 func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
 
-func getsockopt(fd, level, name int, v unsafe.Pointer, l *uint32) error {
-	if _, errno := socketcall(sysGETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
+func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
+	if _, errno := socketcall(sysGETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
 		return error(errno)
 	}
 	return nil
 }
 
-func setsockopt(fd, level, name int, v unsafe.Pointer, l uint32) error {
-	if _, errno := socketcall(sysSETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
+func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
+	if _, errno := socketcall(sysSETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
 		return error(errno)
 	}
 	return nil
diff --git a/ipv6/syscall_unix.go b/ipv6/syscall_unix.go
index 925fd2f..52eb9bd 100644
--- a/ipv6/syscall_unix.go
+++ b/ipv6/syscall_unix.go
@@ -11,15 +11,15 @@ import (
 	"unsafe"
 )
 
-func getsockopt(fd, level, name int, v unsafe.Pointer, l *uint32) error {
-	if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
+func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
+	if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
 		return error(errno)
 	}
 	return nil
 }
 
-func setsockopt(fd, level, name int, v unsafe.Pointer, l uint32) error {
-	if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
+func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
+	if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
 		return error(errno)
 	}
 	return nil