go.net/ipv6: make it work with Go 1.1

This CL makes use of built-in syscall stuff to allow go.net/ipv6
to work together with Go 1.1. Also it's able to improve the package
without churning the Go standard library.

Fixes golang/go#6548.

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/15040044
diff --git a/ipv6/control_rfc2292_darwin.go b/ipv6/control_rfc2292_unix.go
similarity index 78%
rename from ipv6/control_rfc2292_darwin.go
rename to ipv6/control_rfc2292_unix.go
index f09ad7b..eef3968 100644
--- a/ipv6/control_rfc2292_darwin.go
+++ b/ipv6/control_rfc2292_unix.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build darwin
+
 package ipv6
 
 import (
@@ -47,23 +49,23 @@
 		l += syscall.CmsgSpace(4)
 	}
 	if opt.isset(pktinfo) {
-		l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
+		l += syscall.CmsgSpace(sysSizeofPacketInfo)
 	}
 	if l > 0 {
 		oob = make([]byte, l)
 		if opt.isset(FlagHopLimit) {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_2292HOPLIMIT
+			m.Type = sysSockopt2292HopLimit
 			m.SetLen(syscall.CmsgLen(4))
 			off += syscall.CmsgSpace(4)
 		}
 		if opt.isset(pktinfo) {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_2292PKTINFO
-			m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
-			off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
+			m.Type = sysSockopt2292PacketInfo
+			m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
+			off += syscall.CmsgSpace(sysSizeofPacketInfo)
 		}
 	}
 	return
@@ -83,12 +85,12 @@
 			continue
 		}
 		switch m.Header.Type {
-		case syscall.IPV6_2292HOPLIMIT:
+		case sysSockopt2292HopLimit:
 			cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
-		case syscall.IPV6_2292PKTINFO:
-			pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&m.Data[0]))
-			cm.IfIndex = int(pi.Ifindex)
-			cm.Dst = pi.Addr[:]
+		case sysSockopt2292PacketInfo:
+			pi := (*sysPacketInfo)(unsafe.Pointer(&m.Data[0]))
+			cm.IfIndex = int(pi.IfIndex)
+			cm.Dst = pi.IP[:]
 		}
 	}
 	return cm, nil
@@ -105,7 +107,7 @@
 	pion := false
 	if cm.Src.To4() == nil && cm.Src.To16() != nil || cm.IfIndex != 0 {
 		pion = true
-		l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
+		l += syscall.CmsgSpace(sysSizeofPacketInfo)
 	}
 	if len(cm.NextHop) == net.IPv6len {
 		l += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
@@ -115,7 +117,7 @@
 		if cm.HopLimit > 0 {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_2292HOPLIMIT
+			m.Type = sysSockopt2292HopLimit
 			m.SetLen(syscall.CmsgLen(4))
 			data := oob[off+syscall.CmsgLen(0):]
 			*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.HopLimit)
@@ -124,21 +126,21 @@
 		if pion {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_2292PKTINFO
-			m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
-			pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
+			m.Type = sysSockopt2292PacketInfo
+			m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
+			pi := (*sysPacketInfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
 			if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
-				copy(pi.Addr[:], ip)
+				copy(pi.IP[:], ip)
 			}
 			if cm.IfIndex != 0 {
-				pi.Ifindex = uint32(cm.IfIndex)
+				pi.IfIndex = uint32(cm.IfIndex)
 			}
-			off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
+			off += syscall.CmsgSpace(sysSizeofPacketInfo)
 		}
 		if len(cm.NextHop) == net.IPv6len {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_2292NEXTHOP
+			m.Type = sysSockopt2292NextHop
 			m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
 			sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
 			sa.Len = syscall.SizeofSockaddrInet6
diff --git a/ipv6/control_rfc3542_linux.go b/ipv6/control_rfc3542_linux.go
deleted file mode 100644
index 3e73f3b..0000000
--- a/ipv6/control_rfc3542_linux.go
+++ /dev/null
@@ -1,217 +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"
-	"os"
-	"syscall"
-	"unsafe"
-)
-
-const (
-	// See /usr/include/linux/in6.h.
-	syscall_IPV6_RECVPATHMTU = syscall.IPV6_DSTOPTS + 1 + iota
-	syscall_IPV6_PATHMTU
-	syscall_IPV6_DONTFRAG
-)
-
-const pktinfo = FlagDst | FlagInterface
-
-func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
-	opt.Lock()
-	defer opt.Unlock()
-	if cf&FlagTrafficClass != 0 {
-		if err := setIPv6ReceiveTrafficClass(fd, on); err != nil {
-			return err
-		}
-		if on {
-			opt.set(FlagTrafficClass)
-		} else {
-			opt.clear(FlagTrafficClass)
-		}
-	}
-	if cf&FlagHopLimit != 0 {
-		if err := setIPv6ReceiveHopLimit(fd, on); err != nil {
-			return err
-		}
-		if on {
-			opt.set(FlagHopLimit)
-		} else {
-			opt.clear(FlagHopLimit)
-		}
-	}
-	if cf&pktinfo != 0 {
-		if err := setIPv6ReceivePacketInfo(fd, on); err != nil {
-			return err
-		}
-		if on {
-			opt.set(cf & pktinfo)
-		} else {
-			opt.clear(cf & pktinfo)
-		}
-	}
-	if cf&FlagPathMTU != 0 {
-		if err := setIPv6ReceivePathMTU(fd, on); err != nil {
-			return err
-		}
-		if on {
-			opt.set(FlagPathMTU)
-		} else {
-			opt.clear(FlagPathMTU)
-		}
-	}
-	return nil
-}
-
-func newControlMessage(opt *rawOpt) (oob []byte) {
-	opt.Lock()
-	defer opt.Unlock()
-	l, off := 0, 0
-	if opt.isset(FlagTrafficClass) {
-		l += syscall.CmsgSpace(4)
-	}
-	if opt.isset(FlagHopLimit) {
-		l += syscall.CmsgSpace(4)
-	}
-	if opt.isset(pktinfo) {
-		l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
-	}
-	if opt.isset(FlagPathMTU) {
-		l += syscall.CmsgSpace(syscall.SizeofIPv6MTUInfo)
-	}
-	if l > 0 {
-		oob = make([]byte, l)
-		if opt.isset(FlagTrafficClass) {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_RECVTCLASS
-			m.SetLen(syscall.CmsgLen(4))
-			off += syscall.CmsgSpace(4)
-		}
-		if opt.isset(FlagHopLimit) {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_RECVHOPLIMIT
-			m.SetLen(syscall.CmsgLen(4))
-			off += syscall.CmsgSpace(4)
-		}
-		if opt.isset(pktinfo) {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_RECVPKTINFO
-			m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
-			off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
-		}
-		if opt.isset(FlagPathMTU) {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIPv6
-			m.Type = syscall_IPV6_RECVPATHMTU
-			m.SetLen(syscall.CmsgLen(syscall.SizeofIPv6MTUInfo))
-			off += syscall.CmsgSpace(syscall.SizeofIPv6MTUInfo)
-		}
-	}
-	return
-}
-
-func parseControlMessage(b []byte) (*ControlMessage, error) {
-	if len(b) == 0 {
-		return nil, nil
-	}
-	cmsgs, err := syscall.ParseSocketControlMessage(b)
-	if err != nil {
-		return nil, os.NewSyscallError("parse socket control message", err)
-	}
-	cm := &ControlMessage{}
-	for _, m := range cmsgs {
-		if m.Header.Level != ianaProtocolIPv6 {
-			continue
-		}
-		switch m.Header.Type {
-		case syscall.IPV6_TCLASS:
-			cm.TrafficClass = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
-		case syscall.IPV6_HOPLIMIT:
-			cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
-		case syscall.IPV6_PKTINFO:
-			pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&m.Data[0]))
-			cm.Dst = pi.Addr[:]
-			cm.IfIndex = int(pi.Ifindex)
-		case syscall_IPV6_PATHMTU:
-			mi := (*syscall.IPv6MTUInfo)(unsafe.Pointer(&m.Data[0]))
-			cm.Dst = mi.Addr.Addr[:]
-			cm.IfIndex = int(mi.Addr.Scope_id)
-			cm.MTU = int(mi.Mtu)
-		}
-	}
-	return cm, nil
-}
-
-func marshalControlMessage(cm *ControlMessage) (oob []byte) {
-	if cm == nil {
-		return
-	}
-	l, off := 0, 0
-	if cm.TrafficClass > 0 {
-		l += syscall.CmsgSpace(4)
-	}
-	if cm.HopLimit > 0 {
-		l += syscall.CmsgSpace(4)
-	}
-	pion := false
-	if cm.Src.To4() == nil && cm.Src.To16() != nil || cm.IfIndex != 0 {
-		pion = true
-		l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
-	}
-	if len(cm.NextHop) == net.IPv6len {
-		l += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
-	}
-	if l > 0 {
-		oob = make([]byte, l)
-		if cm.TrafficClass > 0 {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_TCLASS
-			m.SetLen(syscall.CmsgLen(4))
-			data := oob[off+syscall.CmsgLen(0):]
-			*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.TrafficClass)
-			off += syscall.CmsgSpace(4)
-		}
-		if cm.HopLimit > 0 {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_HOPLIMIT
-			m.SetLen(syscall.CmsgLen(4))
-			data := oob[off+syscall.CmsgLen(0):]
-			*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.HopLimit)
-			off += syscall.CmsgSpace(4)
-		}
-		if pion {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_PKTINFO
-			m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
-			pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
-			if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
-				copy(pi.Addr[:], ip)
-			}
-			if cm.IfIndex != 0 {
-				pi.Ifindex = uint32(cm.IfIndex)
-			}
-			off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
-		}
-		if len(cm.NextHop) == net.IPv6len {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_NEXTHOP
-			m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
-			sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
-			sa.Family = syscall.AF_INET6
-			copy(sa.Addr[:], cm.NextHop)
-			sa.Scope_id = uint32(cm.IfIndex)
-			off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
-		}
-	}
-	return
-}
diff --git a/ipv6/control_rfc3542_bsd.go b/ipv6/control_rfc3542_unix.go
similarity index 74%
rename from ipv6/control_rfc3542_bsd.go
rename to ipv6/control_rfc3542_unix.go
index 0b42c0b..882a77b 100644
--- a/ipv6/control_rfc3542_bsd.go
+++ b/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 freebsd netbsd openbsd
+// +build freebsd linux netbsd openbsd
 
 package ipv6
 
@@ -72,40 +72,40 @@
 		l += syscall.CmsgSpace(4)
 	}
 	if opt.isset(pktinfo) {
-		l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
+		l += syscall.CmsgSpace(sysSizeofPacketInfo)
 	}
 	if opt.isset(FlagPathMTU) {
-		l += syscall.CmsgSpace(syscall.SizeofIPv6MTUInfo)
+		l += syscall.CmsgSpace(sysSizeofMTUInfo)
 	}
 	if l > 0 {
 		oob = make([]byte, l)
 		if opt.isset(FlagTrafficClass) {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_RECVTCLASS
+			m.Type = sysSockoptReceiveTrafficClass
 			m.SetLen(syscall.CmsgLen(4))
 			off += syscall.CmsgSpace(4)
 		}
 		if opt.isset(FlagHopLimit) {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_RECVHOPLIMIT
+			m.Type = sysSockoptReceiveHopLimit
 			m.SetLen(syscall.CmsgLen(4))
 			off += syscall.CmsgSpace(4)
 		}
 		if opt.isset(pktinfo) {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_RECVPKTINFO
-			m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
-			off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
+			m.Type = sysSockoptReceivePacketInfo
+			m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
+			off += syscall.CmsgSpace(sysSizeofPacketInfo)
 		}
 		if opt.isset(FlagPathMTU) {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_RECVPATHMTU
-			m.SetLen(syscall.CmsgLen(syscall.SizeofIPv6MTUInfo))
-			off += syscall.CmsgSpace(syscall.SizeofIPv6MTUInfo)
+			m.Type = sysSockoptReceivePathMTU
+			m.SetLen(syscall.CmsgLen(sysSizeofMTUInfo))
+			off += syscall.CmsgSpace(sysSizeofMTUInfo)
 		}
 	}
 	return
@@ -125,19 +125,19 @@
 			continue
 		}
 		switch m.Header.Type {
-		case syscall.IPV6_TCLASS:
+		case sysSockoptTrafficClass:
 			cm.TrafficClass = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
-		case syscall.IPV6_HOPLIMIT:
+		case sysSockoptHopLimit:
 			cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
-		case syscall.IPV6_PKTINFO:
-			pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&m.Data[0]))
-			cm.Dst = pi.Addr[:]
-			cm.IfIndex = int(pi.Ifindex)
-		case syscall.IPV6_PATHMTU:
-			mi := (*syscall.IPv6MTUInfo)(unsafe.Pointer(&m.Data[0]))
+		case sysSockoptPacketInfo:
+			pi := (*sysPacketInfo)(unsafe.Pointer(&m.Data[0]))
+			cm.Dst = pi.IP[:]
+			cm.IfIndex = int(pi.IfIndex)
+		case sysSockoptPathMTU:
+			mi := (*sysMTUInfo)(unsafe.Pointer(&m.Data[0]))
 			cm.Dst = mi.Addr.Addr[:]
 			cm.IfIndex = int(mi.Addr.Scope_id)
-			cm.MTU = int(mi.Mtu)
+			cm.MTU = int(mi.MTU)
 		}
 	}
 	return cm, nil
@@ -157,7 +157,7 @@
 	pion := false
 	if cm.Src.To4() == nil && cm.Src.To16() != nil || cm.IfIndex != 0 {
 		pion = true
-		l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
+		l += syscall.CmsgSpace(sysSizeofPacketInfo)
 	}
 	if len(cm.NextHop) == net.IPv6len {
 		l += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
@@ -167,7 +167,7 @@
 		if cm.TrafficClass > 0 {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_TCLASS
+			m.Type = sysSockoptTrafficClass
 			m.SetLen(syscall.CmsgLen(4))
 			data := oob[off+syscall.CmsgLen(0):]
 			*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.TrafficClass)
@@ -176,7 +176,7 @@
 		if cm.HopLimit > 0 {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_HOPLIMIT
+			m.Type = sysSockoptHopLimit
 			m.SetLen(syscall.CmsgLen(4))
 			data := oob[off+syscall.CmsgLen(0):]
 			*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.HopLimit)
@@ -185,27 +185,24 @@
 		if pion {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_PKTINFO
-			m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
-			pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
+			m.Type = sysSockoptPacketInfo
+			m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
+			pi := (*sysPacketInfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
 			if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
-				copy(pi.Addr[:], ip)
+				copy(pi.IP[:], ip)
 			}
 			if cm.IfIndex != 0 {
-				pi.Ifindex = uint32(cm.IfIndex)
+				pi.IfIndex = uint32(cm.IfIndex)
 			}
-			off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
+			off += syscall.CmsgSpace(sysSizeofPacketInfo)
 		}
 		if len(cm.NextHop) == net.IPv6len {
 			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 			m.Level = ianaProtocolIPv6
-			m.Type = syscall.IPV6_NEXTHOP
+			m.Type = sysSockoptNextHop
 			m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
 			sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
-			sa.Len = syscall.SizeofSockaddrInet6
-			sa.Family = syscall.AF_INET6
-			copy(sa.Addr[:], cm.NextHop)
-			sa.Scope_id = uint32(cm.IfIndex)
+			setSockaddr(sa, cm.NextHop, cm.IfIndex)
 			off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
 		}
 	}
diff --git a/ipv6/icmp.go b/ipv6/icmp.go
index 9fb6a48..b45486f 100644
--- a/ipv6/icmp.go
+++ b/ipv6/icmp.go
@@ -21,26 +21,27 @@
 // packets.
 type ICMPFilter struct {
 	mu sync.RWMutex
-	rawICMPFilter
+	sysICMPFilter
 }
 
 // Set sets the ICMP type and filter action to the filter.
 func (f *ICMPFilter) Set(typ ICMPType, block bool) {
 	f.mu.Lock()
-	defer f.mu.Unlock()
 	f.set(typ, block)
+	f.mu.Unlock()
 }
 
 // SetAll sets the filter action to the filter.
 func (f *ICMPFilter) SetAll(block bool) {
 	f.mu.Lock()
-	defer f.mu.Unlock()
 	f.setAll(block)
+	f.mu.Unlock()
 }
 
 // WillBlock reports whether the ICMP type will be blocked.
 func (f *ICMPFilter) WillBlock(typ ICMPType) bool {
 	f.mu.RLock()
-	defer f.mu.RUnlock()
-	return f.willBlock(typ)
+	ok := f.willBlock(typ)
+	f.mu.RUnlock()
+	return ok
 }
diff --git a/ipv6/icmp_bsd.go b/ipv6/icmp_bsd.go
index fd5f83e..b92e0d9 100644
--- a/ipv6/icmp_bsd.go
+++ b/ipv6/icmp_bsd.go
@@ -6,13 +6,11 @@
 
 package ipv6
 
-import "syscall"
-
-type rawICMPFilter struct {
-	syscall.ICMPv6Filter
+type sysICMPFilter struct {
+	Filt [8]uint32
 }
 
-func (f *rawICMPFilter) set(typ ICMPType, block bool) {
+func (f *sysICMPFilter) set(typ ICMPType, block bool) {
 	if block {
 		f.Filt[typ>>5] &^= 1 << (uint32(typ) & 31)
 	} else {
@@ -20,7 +18,7 @@
 	}
 }
 
-func (f *rawICMPFilter) setAll(block bool) {
+func (f *sysICMPFilter) setAll(block bool) {
 	for i := range f.Filt {
 		if block {
 			f.Filt[i] = 0
@@ -30,6 +28,6 @@
 	}
 }
 
-func (f *rawICMPFilter) willBlock(typ ICMPType) bool {
+func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
 	return f.Filt[typ>>5]&(1<<(uint32(typ)&31)) == 0
 }
diff --git a/ipv6/icmp_linux.go b/ipv6/icmp_linux.go
index 0a70f5f..7b3e2bd 100644
--- a/ipv6/icmp_linux.go
+++ b/ipv6/icmp_linux.go
@@ -4,13 +4,11 @@
 
 package ipv6
 
-import "syscall"
-
-type rawICMPFilter struct {
-	syscall.ICMPv6Filter
+type sysICMPFilter struct {
+	Data [8]uint32
 }
 
-func (f *rawICMPFilter) set(typ ICMPType, block bool) {
+func (f *sysICMPFilter) set(typ ICMPType, block bool) {
 	if block {
 		f.Data[typ>>5] |= 1 << (uint32(typ) & 31)
 	} else {
@@ -18,7 +16,7 @@
 	}
 }
 
-func (f *rawICMPFilter) setAll(block bool) {
+func (f *sysICMPFilter) setAll(block bool) {
 	for i := range f.Data {
 		if block {
 			f.Data[i] = 1<<32 - 1
@@ -28,6 +26,6 @@
 	}
 }
 
-func (f *rawICMPFilter) willBlock(typ ICMPType) bool {
+func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
 	return f.Data[typ>>5]&(1<<(uint32(typ)&31)) != 0
 }
diff --git a/ipv6/icmp_plan9.go b/ipv6/icmp_plan9.go
index b97c828..cf4ea4c 100644
--- a/ipv6/icmp_plan9.go
+++ b/ipv6/icmp_plan9.go
@@ -4,19 +4,19 @@
 
 package ipv6
 
-type rawICMPFilter struct {
+type sysICMPFilter struct {
 	// TODO(mikio): Implement this
 }
 
-func (f *rawICMPFilter) set(typ ICMPType, block bool) {
+func (f *sysICMPFilter) set(typ ICMPType, block bool) {
 	// TODO(mikio): Implement this
 }
 
-func (f *rawICMPFilter) setAll(block bool) {
+func (f *sysICMPFilter) setAll(block bool) {
 	// TODO(mikio): Implement this
 }
 
-func (f *rawICMPFilter) willBlock(typ ICMPType) bool {
+func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
 	// TODO(mikio): Implement this
 	return false
 }
diff --git a/ipv6/icmp_windows.go b/ipv6/icmp_windows.go
index b97c828..cf4ea4c 100644
--- a/ipv6/icmp_windows.go
+++ b/ipv6/icmp_windows.go
@@ -4,19 +4,19 @@
 
 package ipv6
 
-type rawICMPFilter struct {
+type sysICMPFilter struct {
 	// TODO(mikio): Implement this
 }
 
-func (f *rawICMPFilter) set(typ ICMPType, block bool) {
+func (f *sysICMPFilter) set(typ ICMPType, block bool) {
 	// TODO(mikio): Implement this
 }
 
-func (f *rawICMPFilter) setAll(block bool) {
+func (f *sysICMPFilter) setAll(block bool) {
 	// TODO(mikio): Implement this
 }
 
-func (f *rawICMPFilter) willBlock(typ ICMPType) bool {
+func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
 	// TODO(mikio): Implement this
 	return false
 }
diff --git a/ipv6/sockopt_rfc2292_darwin.go b/ipv6/sockopt_rfc2292_darwin.go
deleted file mode 100644
index f21802c..0000000
--- a/ipv6/sockopt_rfc2292_darwin.go
+++ /dev/null
@@ -1,66 +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 (
-	"os"
-	"syscall"
-)
-
-func ipv6ReceiveTrafficClass(fd int) (bool, error) {
-	return false, errNotSupported
-}
-
-func setIPv6ReceiveTrafficClass(fd int, v bool) error {
-	return errNotSupported
-}
-
-func ipv6ReceiveHopLimit(fd int) (bool, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_2292HOPLIMIT)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv6ReceiveHopLimit(fd int, v bool) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_2292HOPLIMIT, boolint(v)))
-}
-
-func ipv6ReceivePacketInfo(fd int) (bool, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_2292PKTINFO)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv6ReceivePacketInfo(fd int, v bool) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_2292PKTINFO, boolint(v)))
-}
-
-func ipv6PathMTU(fd int) (int, error) {
-	return 0, errNotSupported
-}
-
-func ipv6ReceivePathMTU(fd int) (bool, error) {
-	return false, errNotSupported
-}
-
-func setIPv6ReceivePathMTU(fd int, v bool) error {
-	return errNotSupported
-}
-
-func ipv6ICMPFilter(fd int) (*ICMPFilter, error) {
-	v, err := syscall.GetsockoptICMPv6Filter(fd, ianaProtocolIPv6ICMP, syscall.ICMP6_FILTER)
-	if err != nil {
-		return nil, os.NewSyscallError("getsockopt", err)
-	}
-	return &ICMPFilter{rawICMPFilter: rawICMPFilter{*v}}, nil
-}
-
-func setIPv6ICMPFilter(fd int, f *ICMPFilter) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptICMPv6Filter(fd, ianaProtocolIPv6ICMP, syscall.ICMP6_FILTER, &f.rawICMPFilter.ICMPv6Filter))
-}
diff --git a/ipv6/sockopt_rfc2292_unix.go b/ipv6/sockopt_rfc2292_unix.go
new file mode 100644
index 0000000..827e943
--- /dev/null
+++ b/ipv6/sockopt_rfc2292_unix.go
@@ -0,0 +1,73 @@
+// 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
+
+package ipv6
+
+import (
+	"os"
+	"unsafe"
+)
+
+func ipv6ReceiveTrafficClass(fd int) (bool, error) {
+	return false, errNotSupported
+}
+
+func setIPv6ReceiveTrafficClass(fd int, v bool) error {
+	return errNotSupported
+}
+
+func ipv6ReceiveHopLimit(fd int) (bool, error) {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockopt2292HopLimit, uintptr(unsafe.Pointer(&v)), &l); err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv6ReceiveHopLimit(fd int, v bool) error {
+	vv := int32(boolint(v))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockopt2292HopLimit, uintptr(unsafe.Pointer(&vv)), 4))
+}
+
+func ipv6ReceivePacketInfo(fd int) (bool, error) {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockopt2292PacketInfo, uintptr(unsafe.Pointer(&v)), &l); err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv6ReceivePacketInfo(fd int, v bool) error {
+	vv := int32(boolint(v))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockopt2292PacketInfo, uintptr(unsafe.Pointer(&vv)), 4))
+}
+
+func ipv6PathMTU(fd int) (int, error) {
+	return 0, errNotSupported
+}
+
+func ipv6ReceivePathMTU(fd int) (bool, error) {
+	return false, errNotSupported
+}
+
+func setIPv6ReceivePathMTU(fd int, v bool) error {
+	return errNotSupported
+}
+
+func ipv6ICMPFilter(fd int) (*ICMPFilter, error) {
+	var v ICMPFilter
+	l := sysSockoptLen(sysSizeofICMPFilter)
+	if err := getsockopt(fd, ianaProtocolIPv6ICMP, sysSockoptICMPFilter, uintptr(unsafe.Pointer(&v.sysICMPFilter)), &l); err != nil {
+		return nil, os.NewSyscallError("getsockopt", err)
+	}
+	return &v, nil
+}
+
+func setIPv6ICMPFilter(fd int, f *ICMPFilter) error {
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6ICMP, sysSockoptICMPFilter, uintptr(unsafe.Pointer(&f.sysICMPFilter)), sysSizeofICMPFilter))
+}
diff --git a/ipv6/sockopt_rfc3493_bsd.go b/ipv6/sockopt_rfc3493_bsd.go
index aa5e6e3..352a161 100644
--- a/ipv6/sockopt_rfc3493_bsd.go
+++ b/ipv6/sockopt_rfc3493_bsd.go
@@ -8,12 +8,13 @@
 
 import (
 	"os"
-	"syscall"
+	"unsafe"
 )
 
 func setIPv6Checksum(fd int, on bool, offset int) error {
 	if !on {
 		offset = -1
 	}
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_CHECKSUM, offset))
+	v := int32(offset)
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptChecksum, uintptr(unsafe.Pointer(&v)), 4))
 }
diff --git a/ipv6/sockopt_rfc3493_linux.go b/ipv6/sockopt_rfc3493_linux.go
index b2557e8..f13a28f 100644
--- a/ipv6/sockopt_rfc3493_linux.go
+++ b/ipv6/sockopt_rfc3493_linux.go
@@ -6,12 +6,13 @@
 
 import (
 	"os"
-	"syscall"
+	"unsafe"
 )
 
 func setIPv6Checksum(fd int, on bool, offset int) error {
 	if !on {
 		offset = -1
 	}
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolReserved, syscall.IPV6_CHECKSUM, offset))
+	v := int32(offset)
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolReserved, sysSockoptChecksum, uintptr(unsafe.Pointer(&v)), 4))
 }
diff --git a/ipv6/sockopt_rfc3493_unix.go b/ipv6/sockopt_rfc3493_unix.go
index b055cf0..a9f5e11 100644
--- a/ipv6/sockopt_rfc3493_unix.go
+++ b/ipv6/sockopt_rfc3493_unix.go
@@ -9,66 +9,74 @@
 import (
 	"net"
 	"os"
-	"syscall"
+	"unsafe"
 )
 
 func ipv6TrafficClass(fd int) (int, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_TCLASS)
-	if err != nil {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptTrafficClass, uintptr(unsafe.Pointer(&v)), &l); err != nil {
 		return 0, os.NewSyscallError("getsockopt", err)
 	}
-	return v, nil
+	return int(v), nil
 }
 
 func setIPv6TrafficClass(fd, v int) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_TCLASS, v))
+	vv := int32(v)
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptTrafficClass, uintptr(unsafe.Pointer(&vv)), 4))
 }
 
 func ipv6HopLimit(fd int) (int, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_UNICAST_HOPS)
-	if err != nil {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, uintptr(unsafe.Pointer(&v)), &l); err != nil {
 		return 0, os.NewSyscallError("getsockopt", err)
 	}
-	return v, nil
+	return int(v), nil
 }
 
 func setIPv6HopLimit(fd, v int) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_UNICAST_HOPS, v))
+	vv := int32(v)
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, uintptr(unsafe.Pointer(&vv)), 4))
 }
 
 func ipv6Checksum(fd int) (bool, int, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_CHECKSUM)
-	if err != nil {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptChecksum, uintptr(unsafe.Pointer(&v)), &l); err != nil {
 		return false, 0, os.NewSyscallError("getsockopt", err)
 	}
 	on := true
 	if v == -1 {
 		on = false
 	}
-	return on, v, nil
+	return on, int(v), nil
 }
 
 func ipv6MulticastHopLimit(fd int) (int, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_HOPS)
-	if err != nil {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, uintptr(unsafe.Pointer(&v)), &l); err != nil {
 		return 0, os.NewSyscallError("getsockopt", err)
 	}
-	return v, nil
+	return int(v), nil
 }
 
 func setIPv6MulticastHopLimit(fd, v int) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_HOPS, v))
+	vv := int32(v)
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, uintptr(unsafe.Pointer(&vv)), 4))
 }
 
 func ipv6MulticastInterface(fd int) (*net.Interface, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_IF)
-	if err != nil {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface, uintptr(unsafe.Pointer(&v)), &l); err != nil {
 		return nil, os.NewSyscallError("getsockopt", err)
 	}
 	if v == 0 {
 		return nil, nil
 	}
-	ifi, err := net.InterfaceByIndex(v)
+	ifi, err := net.InterfaceByIndex(int(v))
 	if err != nil {
 		return nil, err
 	}
@@ -76,39 +84,41 @@
 }
 
 func setIPv6MulticastInterface(fd int, ifi *net.Interface) error {
-	var v int
+	var v int32
 	if ifi != nil {
-		v = ifi.Index
+		v = int32(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_IF, v))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface, uintptr(unsafe.Pointer(&v)), 4))
 }
 
 func ipv6MulticastLoopback(fd int) (bool, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_LOOP)
-	if err != nil {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback, uintptr(unsafe.Pointer(&v)), &l); err != nil {
 		return false, os.NewSyscallError("getsockopt", err)
 	}
 	return v == 1, nil
 }
 
 func setIPv6MulticastLoopback(fd int, v bool) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_LOOP, boolint(v)))
+	vv := int32(boolint(v))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback, uintptr(unsafe.Pointer(&vv)), 4))
 }
 
 func joinIPv6Group(fd int, ifi *net.Interface, grp net.IP) error {
-	mreq := syscall.IPv6Mreq{}
-	copy(mreq.Multiaddr[:], grp)
+	mreq := sysMulticastReq{}
+	copy(mreq.IP[:], grp)
 	if ifi != nil {
-		mreq.Interface = uint32(ifi.Index)
+		mreq.IfIndex = uint32(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd, ianaProtocolIPv6, syscall.IPV6_JOIN_GROUP, &mreq))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptJoinGroup, uintptr(unsafe.Pointer(&mreq)), sysSizeofMulticastReq))
 }
 
 func leaveIPv6Group(fd int, ifi *net.Interface, grp net.IP) error {
-	mreq := syscall.IPv6Mreq{}
-	copy(mreq.Multiaddr[:], grp)
+	mreq := sysMulticastReq{}
+	copy(mreq.IP[:], grp)
 	if ifi != nil {
-		mreq.Interface = uint32(ifi.Index)
+		mreq.IfIndex = uint32(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd, ianaProtocolIPv6, syscall.IPV6_LEAVE_GROUP, &mreq))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptLeaveGroup, uintptr(unsafe.Pointer(&mreq)), sysSizeofMulticastReq))
 }
diff --git a/ipv6/sockopt_rfc3493_windows.go b/ipv6/sockopt_rfc3493_windows.go
index 04d4526..aeac8b6 100644
--- a/ipv6/sockopt_rfc3493_windows.go
+++ b/ipv6/sockopt_rfc3493_windows.go
@@ -24,7 +24,7 @@
 func ipv6HopLimit(fd syscall.Handle) (int, error) {
 	var v int32
 	l := int32(4)
-	if err := syscall.Getsockopt(fd, ianaProtocolIPv6, syscall.IPV6_UNICAST_HOPS, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
+	if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
 		return 0, os.NewSyscallError("getsockopt", err)
 	}
 	return int(v), nil
@@ -32,7 +32,7 @@
 
 func setIPv6HopLimit(fd syscall.Handle, v int) error {
 	vv := int32(v)
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, syscall.IPV6_UNICAST_HOPS, (*byte)(unsafe.Pointer(&vv)), 4))
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, (*byte)(unsafe.Pointer(&vv)), 4))
 }
 
 func ipv6Checksum(fd syscall.Handle) (bool, int, error) {
@@ -43,7 +43,7 @@
 func ipv6MulticastHopLimit(fd syscall.Handle) (int, error) {
 	var v int32
 	l := int32(4)
-	if err := syscall.Getsockopt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_HOPS, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
+	if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
 		return 0, os.NewSyscallError("getsockopt", err)
 	}
 	return int(v), nil
@@ -51,13 +51,13 @@
 
 func setIPv6MulticastHopLimit(fd syscall.Handle, v int) error {
 	vv := int32(v)
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_HOPS, (*byte)(unsafe.Pointer(&vv)), 4))
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, (*byte)(unsafe.Pointer(&vv)), 4))
 }
 
 func ipv6MulticastInterface(fd syscall.Handle) (*net.Interface, error) {
 	var v int32
 	l := int32(4)
-	if err := syscall.Getsockopt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_IF, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
+	if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
 		return nil, os.NewSyscallError("getsockopt", err)
 	}
 	if v == 0 {
@@ -75,13 +75,13 @@
 	if ifi != nil {
 		v = int32(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_IF, (*byte)(unsafe.Pointer(&v)), 4))
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface, (*byte)(unsafe.Pointer(&v)), 4))
 }
 
 func ipv6MulticastLoopback(fd syscall.Handle) (bool, error) {
 	var v int32
 	l := int32(4)
-	if err := syscall.Getsockopt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_LOOP, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
+	if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
 		return false, os.NewSyscallError("getsockopt", err)
 	}
 	return v == 1, nil
@@ -89,25 +89,25 @@
 
 func setIPv6MulticastLoopback(fd syscall.Handle, v bool) error {
 	vv := int32(boolint(v))
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_LOOP, (*byte)(unsafe.Pointer(&vv)), 4))
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback, (*byte)(unsafe.Pointer(&vv)), 4))
 }
 
 func joinIPv6Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
-	mreq := syscall.IPv6Mreq{}
-	copy(mreq.Multiaddr[:], grp)
+	mreq := sysMulticastReq{}
+	copy(mreq.IP[:], grp)
 	if ifi != nil {
-		mreq.Interface = uint32(ifi.Index)
+		mreq.IfIndex = uint32(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, syscall.IPV6_JOIN_GROUP, (*byte)(unsafe.Pointer(&mreq)), int32(unsafe.Sizeof(mreq))))
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptJoinGroup, (*byte)(unsafe.Pointer(&mreq)), int32(sysSizeofMulticastReq)))
 }
 
 func leaveIPv6Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
-	mreq := syscall.IPv6Mreq{}
-	copy(mreq.Multiaddr[:], grp)
+	mreq := sysMulticastReq{}
+	copy(mreq.IP[:], grp)
 	if ifi != nil {
-		mreq.Interface = uint32(ifi.Index)
+		mreq.IfIndex = uint32(ifi.Index)
 	}
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, syscall.IPV6_LEAVE_GROUP, (*byte)(unsafe.Pointer(&mreq)), int32(unsafe.Sizeof(mreq))))
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptLeaveGroup, (*byte)(unsafe.Pointer(&mreq)), int32(sysSizeofMulticastReq)))
 }
 
 func setIPv6Checksum(fd syscall.Handle, on bool, offset int) error {
diff --git a/ipv6/sockopt_rfc3542_bsd.go b/ipv6/sockopt_rfc3542_bsd.go
deleted file mode 100644
index 61073b1..0000000
--- a/ipv6/sockopt_rfc3542_bsd.go
+++ /dev/null
@@ -1,44 +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 freebsd netbsd openbsd
-
-package ipv6
-
-import (
-	"os"
-	"syscall"
-)
-
-func ipv6PathMTU(fd int) (int, error) {
-	v, err := syscall.GetsockoptIPv6MTUInfo(fd, ianaProtocolIPv6, syscall.IPV6_PATHMTU)
-	if err != nil {
-		return 0, os.NewSyscallError("getsockopt", err)
-	}
-	return int(v.Mtu), nil
-}
-
-func ipv6ReceivePathMTU(fd int) (bool, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_RECVPATHMTU)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv6ReceivePathMTU(fd int, v bool) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_RECVPATHMTU, boolint(v)))
-}
-
-func ipv6ICMPFilter(fd int) (*ICMPFilter, error) {
-	v, err := syscall.GetsockoptICMPv6Filter(fd, ianaProtocolIPv6ICMP, syscall.ICMP6_FILTER)
-	if err != nil {
-		return nil, os.NewSyscallError("getsockopt", err)
-	}
-	return &ICMPFilter{rawICMPFilter: rawICMPFilter{*v}}, nil
-}
-
-func setIPv6ICMPFilter(fd int, f *ICMPFilter) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptICMPv6Filter(fd, ianaProtocolIPv6ICMP, syscall.ICMP6_FILTER, &f.rawICMPFilter.ICMPv6Filter))
-}
diff --git a/ipv6/sockopt_rfc3542_linux.go b/ipv6/sockopt_rfc3542_linux.go
deleted file mode 100644
index 9cea683..0000000
--- a/ipv6/sockopt_rfc3542_linux.go
+++ /dev/null
@@ -1,42 +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 (
-	"os"
-	"syscall"
-)
-
-func ipv6PathMTU(fd int) (int, error) {
-	v, err := syscall.GetsockoptIPv6MTUInfo(fd, ianaProtocolIPv6, syscall_IPV6_PATHMTU)
-	if err != nil {
-		return 0, os.NewSyscallError("getsockopt", err)
-	}
-	return int(v.Mtu), nil
-}
-
-func ipv6ReceivePathMTU(fd int) (bool, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall_IPV6_RECVPATHMTU)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv6ReceivePathMTU(fd int, v bool) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall_IPV6_RECVPATHMTU, boolint(v)))
-}
-
-func ipv6ICMPFilter(fd int) (*ICMPFilter, error) {
-	v, err := syscall.GetsockoptICMPv6Filter(fd, ianaProtocolIPv6ICMP, syscall.ICMPV6_FILTER)
-	if err != nil {
-		return nil, os.NewSyscallError("getsockopt", err)
-	}
-	return &ICMPFilter{rawICMPFilter: rawICMPFilter{*v}}, nil
-}
-
-func setIPv6ICMPFilter(fd int, f *ICMPFilter) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptICMPv6Filter(fd, ianaProtocolIPv6ICMP, syscall.ICMPV6_FILTER, &f.rawICMPFilter.ICMPv6Filter))
-}
diff --git a/ipv6/sockopt_rfc3542_unix.go b/ipv6/sockopt_rfc3542_unix.go
index 463f426..da9111c 100644
--- a/ipv6/sockopt_rfc3542_unix.go
+++ b/ipv6/sockopt_rfc3542_unix.go
@@ -8,41 +8,83 @@
 
 import (
 	"os"
-	"syscall"
+	"unsafe"
 )
 
 func ipv6ReceiveTrafficClass(fd int) (bool, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_RECVTCLASS)
-	if err != nil {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptReceiveTrafficClass, uintptr(unsafe.Pointer(&v)), &l); err != nil {
 		return false, os.NewSyscallError("getsockopt", err)
 	}
 	return v == 1, nil
 }
 
 func setIPv6ReceiveTrafficClass(fd int, v bool) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_RECVTCLASS, boolint(v)))
+	vv := int32(boolint(v))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptReceiveTrafficClass, uintptr(unsafe.Pointer(&vv)), 4))
 }
 
 func ipv6ReceiveHopLimit(fd int) (bool, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_RECVHOPLIMIT)
-	if err != nil {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptReceiveHopLimit, uintptr(unsafe.Pointer(&v)), &l); err != nil {
 		return false, os.NewSyscallError("getsockopt", err)
 	}
 	return v == 1, nil
 }
 
 func setIPv6ReceiveHopLimit(fd int, v bool) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_RECVHOPLIMIT, boolint(v)))
+	vv := int32(boolint(v))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptReceiveHopLimit, uintptr(unsafe.Pointer(&vv)), 4))
 }
 
 func ipv6ReceivePacketInfo(fd int) (bool, error) {
-	v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_RECVPKTINFO)
-	if err != nil {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptReceivePacketInfo, uintptr(unsafe.Pointer(&v)), &l); err != nil {
 		return false, os.NewSyscallError("getsockopt", err)
 	}
 	return v == 1, nil
 }
 
 func setIPv6ReceivePacketInfo(fd int, v bool) error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_RECVPKTINFO, boolint(v)))
+	vv := int32(boolint(v))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptReceivePacketInfo, uintptr(unsafe.Pointer(&vv)), 4))
+}
+
+func ipv6PathMTU(fd int) (int, error) {
+	var v sysMTUInfo
+	l := sysSockoptLen(sysSizeofMTUInfo)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptPathMTU, uintptr(unsafe.Pointer(&v)), &l); err != nil {
+		return 0, os.NewSyscallError("getsockopt", err)
+	}
+	return int(v.MTU), nil
+}
+
+func ipv6ReceivePathMTU(fd int) (bool, error) {
+	var v int32
+	l := sysSockoptLen(4)
+	if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptReceivePathMTU, uintptr(unsafe.Pointer(&v)), &l); err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv6ReceivePathMTU(fd int, v bool) error {
+	vv := int32(boolint(v))
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptReceivePathMTU, uintptr(unsafe.Pointer(&vv)), 4))
+}
+
+func ipv6ICMPFilter(fd int) (*ICMPFilter, error) {
+	var v ICMPFilter
+	l := sysSockoptLen(sysSizeofICMPFilter)
+	if err := getsockopt(fd, ianaProtocolIPv6ICMP, sysSockoptICMPFilter, uintptr(unsafe.Pointer(&v.sysICMPFilter)), &l); err != nil {
+		return nil, os.NewSyscallError("getsockopt", err)
+	}
+	return &v, nil
+}
+
+func setIPv6ICMPFilter(fd int, f *ICMPFilter) error {
+	return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6ICMP, sysSockoptICMPFilter, uintptr(unsafe.Pointer(&f.sysICMPFilter)), sysSizeofICMPFilter))
 }