Update dependencies

This commit is contained in:
Jakob Borg
2014-03-22 21:58:10 +01:00
parent 145c8e4063
commit 75cfa4c33e
69 changed files with 2605 additions and 917 deletions

View File

@@ -12,7 +12,6 @@ import (
)
var (
errNotSupported = errors.New("not supported")
errMissingAddress = errors.New("missing address")
errInvalidConnType = errors.New("invalid conn type")
errNoSuchInterface = errors.New("no such interface")

View File

@@ -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 @@ func newControlMessage(opt *rawOpt) (oob []byte) {
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 @@ func parseControlMessage(b []byte) (*ControlMessage, error) {
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 @@ func marshalControlMessage(cm *ControlMessage) (oob []byte) {
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 @@ func marshalControlMessage(cm *ControlMessage) (oob []byte) {
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,26 +126,24 @@ func marshalControlMessage(cm *ControlMessage) (oob []byte) {
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
sa.Family = syscall.AF_INET6
copy(sa.Addr[:], cm.NextHop)
setSockaddr(sa, cm.NextHop, cm.IfIndex)
off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
}
}

View File

@@ -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
}

View File

@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv6
// +build dragonfly plan9 solaris
import "syscall"
package ipv6
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}
func newControlMessage(opt *rawOpt) (oob []byte) {
@@ -18,7 +18,7 @@ func newControlMessage(opt *rawOpt) (oob []byte) {
func parseControlMessage(b []byte) (*ControlMessage, error) {
// TODO(mikio): Implement this
return nil, syscall.EPLAN9
return nil, errOpNoSupport
}
func marshalControlMessage(cm *ControlMessage) (oob []byte) {

View File

@@ -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 @@ func newControlMessage(opt *rawOpt) (oob []byte) {
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 @@ func parseControlMessage(b []byte) (*ControlMessage, error) {
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 @@ func marshalControlMessage(cm *ControlMessage) (oob []byte) {
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 @@ func marshalControlMessage(cm *ControlMessage) (oob []byte) {
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 @@ func marshalControlMessage(cm *ControlMessage) (oob []byte) {
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 @@ func marshalControlMessage(cm *ControlMessage) (oob []byte) {
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)
}
}

View File

@@ -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 (
"sync"
"testing"
)
func TestControlFlags(t *testing.T) {
tf := FlagInterface | FlagPathMTU
opt := rawOpt{cflags: tf | FlagHopLimit}
// This loop runs methods of raw.Opt concurrently for testing
// concurrent access to the rawOpt. The first entry shold be
// opt.set and the last entry should be opt.clear.
tfns := []func(ControlFlags){opt.set, opt.clear, opt.clear}
ch := make(chan bool)
var wg sync.WaitGroup
for i, fn := range tfns {
wg.Add(1)
go func(i int, fn func(ControlFlags)) {
defer wg.Done()
switch i {
case 0:
close(ch)
case len(tfns) - 1:
<-ch
}
opt.Lock()
defer opt.Unlock()
fn(tf)
}(i, fn)
}
wg.Wait()
if opt.isset(tf) {
t.Fatalf("got %#x; expected %#x", opt.cflags, FlagHopLimit)
}
}

View File

@@ -2,53 +2,52 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build dragonfly plan9 solaris
package ipv6
import (
"net"
"syscall"
)
import "net"
// MulticastHopLimit returns the hop limit field value for outgoing
// multicast packets.
func (c *dgramOpt) MulticastHopLimit() (int, error) {
// TODO(mikio): Implement this
return 0, syscall.EPLAN9
return 0, errOpNoSupport
}
// SetMulticastHopLimit sets the hop limit field value for future
// outgoing multicast packets.
func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}
// MulticastInterface returns the default interface for multicast
// packet transmissions.
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
// TODO(mikio): Implement this
return nil, syscall.EPLAN9
return nil, errOpNoSupport
}
// SetMulticastInterface sets the default interface for future
// multicast packet transmissions.
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}
// MulticastLoopback reports whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) MulticastLoopback() (bool, error) {
// TODO(mikio): Implement this
return false, syscall.EPLAN9
return false, errOpNoSupport
}
// SetMulticastLoopback sets whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}
// JoinGroup joins the group address group on the interface ifi.
@@ -57,13 +56,13 @@ func (c *dgramOpt) SetMulticastLoopback(on bool) error {
// platforms and sometimes it might require routing configuration.
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}
// LeaveGroup leaves the group address group on the interface ifi.
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}
// Checksum reports whether the kernel will compute, store or verify a
@@ -72,7 +71,7 @@ func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
// field is located.
func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
// TODO(mikio): Implement this
return false, 0, syscall.EPLAN9
return false, 0, errOpNoSupport
}
// SetChecksum enables the kernel checksum processing. If on is ture,
@@ -80,17 +79,17 @@ func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
// checksum field is located.
func (c *dgramOpt) SetChecksum(on bool, offset int) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}
// ICMPFilter returns an ICMP filter.
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
// TODO(mikio): Implement this
return nil, syscall.EPLAN9
return nil, errOpNoSupport
}
// SetICMPFilter deploys the ICMP filter.
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}

View File

@@ -2,33 +2,33 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv6
// +build dragonfly plan9 solaris
import "syscall"
package ipv6
// TrafficClass returns the traffic class field value for outgoing
// packets.
func (c *genericOpt) TrafficClass() (int, error) {
// TODO(mikio): Implement this
return 0, syscall.EPLAN9
return 0, errOpNoSupport
}
// SetTrafficClass sets the traffic class field value for future
// outgoing packets.
func (c *genericOpt) SetTrafficClass(tclass int) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}
// HopLimit returns the hop limit field value for outgoing packets.
func (c *genericOpt) HopLimit() (int, error) {
// TODO(mikio): Implement this
return 0, syscall.EPLAN9
return 0, errOpNoSupport
}
// SetHopLimit sets the hop limit field value for future outgoing
// packets.
func (c *genericOpt) SetHopLimit(hoplim int) error {
// TODO(mikio): Implement this
return syscall.EPLAN9
return errOpNoSupport
}

View File

@@ -4,7 +4,12 @@
package ipv6
import "net"
import (
"errors"
"net"
)
var errOpNoSupport = errors.New("operation not supported")
func boolint(b bool) int {
if b {

View File

@@ -2,21 +2,21 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv6
// +build dragonfly plan9 solaris
import "syscall"
package ipv6
func (c *genericOpt) sysfd() (int, error) {
// TODO(mikio): Implement this
return 0, syscall.EPLAN9
return 0, errOpNoSupport
}
func (c *dgramOpt) sysfd() (int, error) {
// TODO(mikio): Implement this
return 0, syscall.EPLAN9
return 0, errOpNoSupport
}
func (c *payloadHandler) sysfd() (int, error) {
// TODO(mikio): Implement this
return 0, syscall.EPLAN9
return 0, errOpNoSupport
}

View File

@@ -21,26 +21,27 @@ func (typ ICMPType) String() string {
// 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
}

View File

@@ -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) set(typ ICMPType, block bool) {
}
}
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) setAll(block bool) {
}
}
func (f *rawICMPFilter) willBlock(typ ICMPType) bool {
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
return f.Filt[typ>>5]&(1<<(uint32(typ)&31)) == 0
}

View File

@@ -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) set(typ ICMPType, block bool) {
}
}
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) setAll(block bool) {
}
}
func (f *rawICMPFilter) willBlock(typ ICMPType) bool {
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
return f.Data[typ>>5]&(1<<(uint32(typ)&31)) != 0
}

View File

@@ -2,21 +2,23 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build dragonfly plan9 solaris
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
}

View File

@@ -14,9 +14,27 @@ import (
"testing"
)
var icmpStringTests = []struct {
in ipv6.ICMPType
out string
}{
{ipv6.ICMPTypeDestinationUnreachable, "destination unreachable"},
{256, "<nil>"},
}
func TestICMPString(t *testing.T) {
for _, tt := range icmpStringTests {
s := tt.in.String()
if s != tt.out {
t.Errorf("got %s; expected %s", s, tt.out)
}
}
}
func TestICMPFilter(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
@@ -49,7 +67,7 @@ func TestICMPFilter(t *testing.T) {
func TestSetICMPFilter(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {

View File

@@ -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
}

View File

@@ -7,8 +7,22 @@ package ipv6_test
import (
"code.google.com/p/go.net/ipv6"
"errors"
"net"
)
const (
ipv6PseudoHeaderLen = 2*net.IPv6len + 8
ianaProtocolIPv6ICMP = 58
)
func ipv6PseudoHeader(src, dst net.IP, nextHeader int) []byte {
b := make([]byte, ipv6PseudoHeaderLen)
copy(b[:net.IPv6len], src)
copy(b[net.IPv6len:], dst)
b[len(b)-1] = byte(nextHeader)
return b
}
// icmpMessage represents an ICMP message.
type icmpMessage struct {
Type ipv6.ICMPType // type
@@ -25,8 +39,11 @@ type icmpMessageBody interface {
// Marshal returns the binary enconding of the ICMP echo request or
// reply message m.
func (m *icmpMessage) Marshal() ([]byte, error) {
func (m *icmpMessage) Marshal(psh []byte) ([]byte, error) {
b := []byte{byte(m.Type), byte(m.Code), 0, 0}
if psh != nil {
b = append(psh, b...)
}
if m.Body != nil && m.Body.Len() != 0 {
mb, err := m.Body.Marshal()
if err != nil {
@@ -34,10 +51,11 @@ func (m *icmpMessage) Marshal() ([]byte, error) {
}
b = append(b, mb...)
}
switch m.Type {
case ipv6.ICMPTypeEchoRequest, ipv6.ICMPTypeEchoReply:
if psh == nil {
return b, nil
}
off, l := 2*net.IPv6len, len(b)-len(psh)
b[off], b[off+1], b[off+2], b[off+3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
csumcv := len(b) - 1 // checksum coverage
s := uint32(0)
for i := 0; i < csumcv; i += 2 {
@@ -50,9 +68,9 @@ func (m *icmpMessage) Marshal() ([]byte, error) {
s = s + s>>16
// Place checksum back in header; using ^= avoids the
// assumption the checksum bytes are zero.
b[2] ^= byte(^s)
b[3] ^= byte(^s >> 8)
return b, nil
b[len(psh)+2] ^= byte(^s)
b[len(psh)+3] ^= byte(^s >> 8)
return b[len(psh):], nil
}
// parseICMPMessage parses b as an ICMP message.

View File

@@ -86,25 +86,3 @@ func acceptor(t *testing.T, ln net.Listener, done chan<- bool) {
}
c.Close()
}
func transponder(t *testing.T, ln net.Listener, done chan<- bool) {
defer func() { done <- true }()
c, err := ln.Accept()
if err != nil {
t.Errorf("net.Listener.Accept failed: %v", err)
return
}
defer c.Close()
b := make([]byte, 128)
n, err := c.Read(b)
if err != nil {
t.Errorf("net.Conn.Read failed: %v", err)
return
}
if _, err := c.Write(b[:n]); err != nil {
t.Errorf("net.Conn.Write failed: %v", err)
return
}
}

View File

@@ -5,11 +5,13 @@
package ipv6_test
import (
"bytes"
"code.google.com/p/go.net/ipv6"
"net"
"os"
"runtime"
"testing"
"time"
)
func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
@@ -17,7 +19,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 %q", runtime.GOOS)
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
@@ -44,33 +46,49 @@ func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
}
p := ipv6.NewPacketConn(c)
defer p.Close()
if err := p.JoinGroup(ifi, dst); err != nil {
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
}
if err := p.SetMulticastInterface(ifi); err != nil {
t.Fatalf("ipv6.PacketConn.SetMulticastInterface failed: %v", err)
}
if _, err := p.MulticastInterface(); err != nil {
t.Fatalf("ipv6.PacketConn.MulticastInterface failed: %v", err)
}
if err := p.SetMulticastLoopback(true); err != nil {
t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err)
}
if _, err := p.MulticastLoopback(); err != nil {
t.Fatalf("ipv6.PacketConn.MulticastLoopback failed: %v", err)
}
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
Src: net.IPv6loopback,
IfIndex: ifi.Index,
}
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
wb := []byte("HELLO-R-U-THERE")
for i, toggle := range []bool{true, false, true} {
if err := p.SetControlMessage(cf, toggle); err != nil {
t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
}
cm.HopLimit = i + 1
if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatalf("ipv6.PacketConn.SetDeadline failed: %v", err)
}
b := make([]byte, 128)
if _, cm, _, err := p.ReadFrom(b); err != nil {
cm.HopLimit = i + 1
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
} else if n != len(wb) {
t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
}
rb := make([]byte, 128)
if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
} else if !bytes.Equal(rb[:n], wb) {
t.Fatalf("got %v; expected %v", rb[:n], wb)
} else {
t.Logf("rcvd cmsg: %v", cm)
}
@@ -79,7 +97,7 @@ func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
@@ -104,22 +122,31 @@ func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
t.Fatalf("net.ResolveIPAddr failed: %v", err)
}
pshicmp := ipv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP, ianaProtocolIPv6ICMP)
p := ipv6.NewPacketConn(c)
defer p.Close()
if err := p.JoinGroup(ifi, dst); err != nil {
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
}
if err := p.SetMulticastInterface(ifi); err != nil {
t.Fatalf("ipv6.PacketConn.SetMulticastInterface failed: %v", err)
}
if _, err := p.MulticastInterface(); err != nil {
t.Fatalf("ipv6.PacketConn.MulticastInterface failed: %v", err)
}
if err := p.SetMulticastLoopback(true); err != nil {
t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err)
}
if _, err := p.MulticastLoopback(); err != nil {
t.Fatalf("ipv6.PacketConn.MulticastLoopback failed: %v", err)
}
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
Src: net.IPv6loopback,
IfIndex: ifi.Index,
}
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
var f ipv6.ICMPFilter
f.SetAll(true)
@@ -128,30 +155,47 @@ func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
t.Fatalf("ipv6.PacketConn.SetICMPFilter failed: %v", err)
}
var psh []byte
for i, toggle := range []bool{true, false, true} {
if toggle {
psh = nil
if err := p.SetChecksum(true, 2); err != nil {
t.Fatalf("ipv6.PacketConn.SetChecksum failed: %v", err)
}
} else {
psh = pshicmp
// Some platforms never allow to disable the
// kernel checksum processing.
p.SetChecksum(false, -1)
}
wb, err := (&icmpMessage{
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
Body: &icmpEcho{
ID: os.Getpid() & 0xffff, Seq: i + 1,
Data: []byte("HELLO-R-U-THERE"),
},
}).Marshal()
}).Marshal(psh)
if err != nil {
t.Fatalf("icmpMessage.Marshal failed: %v", err)
}
if err := p.SetControlMessage(cf, toggle); err != nil {
t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
}
cm.HopLimit = i + 1
if _, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatalf("ipv6.PacketConn.SetDeadline failed: %v", err)
}
b := make([]byte, 128)
if n, cm, _, err := p.ReadFrom(b); err != nil {
cm.HopLimit = i + 1
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
} else if n != len(wb) {
t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
}
rb := make([]byte, 128)
if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
if m, err := parseICMPMessage(b[:n]); err != nil {
if m, err := parseICMPMessage(rb[:n]); err != nil {
t.Fatalf("parseICMPMessage failed: %v", err)
} else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)

View File

@@ -21,7 +21,7 @@ var udpMultipleGroupListenerTests = []net.Addr{
func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
@@ -59,9 +59,9 @@ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
}
}
func TestUDPMultipleConnWithMultipleGroupListeners(t *testing.T) {
func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
@@ -113,14 +113,14 @@ func TestUDPMultipleConnWithMultipleGroupListeners(t *testing.T) {
func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
t.Skip("ipv6 is not supported")
}
gaddr := &net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
type ml struct {
c *ipv6.PacketConn
ifi *net.Interface
@@ -142,13 +142,13 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
}
defer c.Close()
p := ipv6.NewPacketConn(c)
if err := p.JoinGroup(&ifi, gaddr); err != nil {
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
}
mlt = append(mlt, &ml{p, &ift[i]})
}
for _, m := range mlt {
if err := m.c.LeaveGroup(m.ifi, gaddr); err != nil {
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", m.ifi, err)
}
}
@@ -156,7 +156,7 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
@@ -166,14 +166,14 @@ func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
t.Skip("must be root")
}
c, err := net.ListenPacket("ip6:ipv6-icmp", "::")
c, err := net.ListenPacket("ip6:ipv6-icmp", "::") // wildcard address
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
p := ipv6.NewPacketConn(c)
gaddr := &net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
var mift []*net.Interface
ift, err := net.Interfaces()
@@ -184,14 +184,60 @@ func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
if _, ok := isMulticastAvailable(&ifi); !ok {
continue
}
if err := p.JoinGroup(&ifi, gaddr); err != nil {
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
}
mift = append(mift, &ift[i])
}
for _, ifi := range mift {
if err := p.LeaveGroup(ifi, gaddr); err != nil {
if err := p.LeaveGroup(ifi, &gaddr); err != nil {
t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", ifi, err)
}
}
}
func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
switch runtime.GOOS {
case "darwin", "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
t.Skip("ipv6 is not supported")
}
if os.Getuid() != 0 {
t.Skip("must be root")
}
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
type ml struct {
c *ipv6.PacketConn
ifi *net.Interface
}
var mlt []*ml
ift, err := net.Interfaces()
if err != nil {
t.Fatalf("net.Interfaces failed: %v", err)
}
for i, ifi := range ift {
ip, ok := isMulticastAvailable(&ifi)
if !ok {
continue
}
c, err := net.ListenPacket("ip6:ipv6-icmp", fmt.Sprintf("%s%%%s", ip.String(), ifi.Name)) // unicast address
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
p := ipv6.NewPacketConn(c)
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
}
mlt = append(mlt, &ml{p, &ift[i]})
}
for _, m := range mlt {
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", m.ifi, err)
}
}
}

View File

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

View File

@@ -0,0 +1,168 @@
// 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_test
import (
"bytes"
"code.google.com/p/go.net/ipv6"
"net"
"runtime"
"sync"
"testing"
)
func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
c, err := net.ListenPacket("udp6", "[::1]:0")
if err != nil {
return nil, nil, err
}
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
if err != nil {
c.Close()
return nil, nil, err
}
return c, dst, nil
}
func BenchmarkReadWriteNetUDP(b *testing.B) {
c, dst, err := benchmarkUDPListener()
if err != nil {
b.Fatalf("benchmarkUDPListener failed: %v", err)
}
defer c.Close()
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
b.ResetTimer()
for i := 0; i < b.N; i++ {
benchmarkReadWriteNetUDP(b, c, wb, rb, dst)
}
}
func benchmarkReadWriteNetUDP(b *testing.B, c net.PacketConn, wb, rb []byte, dst net.Addr) {
if _, err := c.WriteTo(wb, dst); err != nil {
b.Fatalf("net.PacketConn.WriteTo failed: %v", err)
}
if _, _, err := c.ReadFrom(rb); err != nil {
b.Fatalf("net.PacketConn.ReadFrom failed: %v", err)
}
}
func BenchmarkReadWriteIPv6UDP(b *testing.B) {
c, dst, err := benchmarkUDPListener()
if err != nil {
b.Fatalf("benchmarkUDPListener failed: %v", err)
}
defer c.Close()
p := ipv6.NewPacketConn(c)
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
if err := p.SetControlMessage(cf, true); err != nil {
b.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
}
ifi := loopbackInterface()
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
b.ResetTimer()
for i := 0; i < b.N; i++ {
benchmarkReadWriteIPv6UDP(b, p, wb, rb, dst, ifi)
}
}
func benchmarkReadWriteIPv6UDP(b *testing.B, p *ipv6.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
HopLimit: 1,
}
if ifi != nil {
cm.IfIndex = ifi.Index
}
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
b.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
} else if n != len(wb) {
b.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
}
if _, _, _, err := p.ReadFrom(rb); err != nil {
b.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
}
}
func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
switch runtime.GOOS {
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
t.Skip("ipv6 is not supported")
}
c, err := net.ListenPacket("udp6", "[::1]:0")
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
p := ipv6.NewPacketConn(c)
defer p.Close()
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
if err != nil {
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
}
ifi := loopbackInterface()
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
wb := []byte("HELLO-R-U-THERE")
var wg sync.WaitGroup
reader := func() {
defer wg.Done()
rb := make([]byte, 128)
if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Errorf("ipv6.PacketConn.ReadFrom failed: %v", err)
return
} else if !bytes.Equal(rb[:n], wb) {
t.Errorf("got %v; expected %v", rb[:n], wb)
return
} else {
t.Logf("rcvd cmsg: %v", cm)
}
}
writer := func(toggle bool) {
defer wg.Done()
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
Src: net.IPv6loopback,
Dst: net.IPv6loopback,
}
if ifi != nil {
cm.IfIndex = ifi.Index
}
if err := p.SetControlMessage(cf, toggle); err != nil {
t.Errorf("ipv6.PacketConn.SetControlMessage failed: %v", err)
return
}
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Errorf("ipv6.PacketConn.WriteTo failed: %v", err)
return
} else if n != len(wb) {
t.Errorf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
return
}
}
const N = 10
wg.Add(N)
for i := 0; i < N; i++ {
go reader()
}
wg.Add(2 * N)
for i := 0; i < 2*N; i++ {
go writer(i%2 != 0)
}
wg.Add(N)
for i := 0; i < N; i++ {
go reader()
}
wg.Wait()
}

View File

@@ -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))
}

View File

@@ -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, errOpNoSupport
}
func setIPv6ReceiveTrafficClass(fd int, v bool) error {
return errOpNoSupport
}
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, errOpNoSupport
}
func ipv6ReceivePathMTU(fd int) (bool, error) {
return false, errOpNoSupport
}
func setIPv6ReceivePathMTU(fd int, v bool) error {
return errOpNoSupport
}
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))
}

View File

@@ -8,12 +8,13 @@ package ipv6
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))
}

View File

@@ -6,12 +6,13 @@ package ipv6
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))
}

View File

@@ -9,66 +9,74 @@ package ipv6
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 ipv6MulticastInterface(fd int) (*net.Interface, error) {
}
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))
}

View File

@@ -24,7 +24,7 @@ func setIPv6TrafficClass(fd syscall.Handle, v int) error {
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 ipv6HopLimit(fd syscall.Handle) (int, error) {
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 ipv6Checksum(fd syscall.Handle) (bool, int, error) {
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 ipv6MulticastHopLimit(fd syscall.Handle) (int, error) {
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 @@ func setIPv6MulticastInterface(fd syscall.Handle, ifi *net.Interface) error {
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 ipv6MulticastLoopback(fd syscall.Handle) (bool, error) {
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 {

View File

@@ -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))
}

View File

@@ -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))
}

View File

@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv6
// +build dragonfly plan9 solaris
import "syscall"
package ipv6
func ipv6PathMTU(fd int) (int, error) {
// TODO(mikio): Implement this
return 0, syscall.EPLAN9
return 0, errOpNoSupport
}

View File

@@ -8,41 +8,83 @@ package ipv6
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))
}

View File

@@ -24,7 +24,7 @@ func init() {
var condFatalf = func() func(*testing.T, string, ...interface{}) {
// A few APIs are not implemented yet on some platforms.
switch runtime.GOOS {
case "darwin", "plan9", "windows":
case "darwin", "dragonfly", "plan9", "solaris", "windows":
return (*testing.T).Logf
}
return (*testing.T).Fatalf
@@ -32,7 +32,7 @@ var condFatalf = func() func(*testing.T, string, ...interface{}) {
func TestConnInitiatorPathMTU(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
@@ -65,7 +65,7 @@ func TestConnInitiatorPathMTU(t *testing.T) {
func TestConnResponderPathMTU(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
@@ -98,7 +98,7 @@ func TestConnResponderPathMTU(t *testing.T) {
func TestPacketConnChecksum(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {

View File

@@ -0,0 +1,23 @@
// 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
type sysSockoptLen uint32
const (
sysSizeofPacketInfo = 0x14
sysSizeofMulticastReq = 0x14
sysSizeofICMPFilter = 0x20
)
type sysPacketInfo struct {
IP [16]byte
IfIndex uint32
}
type sysMulticastReq struct {
IP [16]byte
IfIndex uint32
}

View File

@@ -0,0 +1,48 @@
// 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 (
"net"
"syscall"
)
// RFC 3493 options
const (
// See /usr/include/netinet6/in6.h.
sysSockoptUnicastHopLimit = 0x4
sysSockoptMulticastHopLimit = 0xa
sysSockoptMulticastInterface = 0x9
sysSockoptMulticastLoopback = 0xb
sysSockoptJoinGroup = 0xc
sysSockoptLeaveGroup = 0xd
)
// RFC 3542 options
const (
// See /usr/include/netinet6/in6.h.
sysSockoptReceiveTrafficClass = 0x39
sysSockoptTrafficClass = 0x3d
sysSockoptReceiveHopLimit = 0x25
sysSockoptHopLimit = 0x2f
sysSockoptReceivePacketInfo = 0x24
sysSockoptPacketInfo = 0x2e
sysSockoptReceivePathMTU = 0x2b
sysSockoptPathMTU = 0x2c
sysSockoptNextHop = 0x30
sysSockoptChecksum = 0x1a
// See /usr/include/netinet6/in6.h.
sysSockoptICMPFilter = 0x12
)
func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) {
sa.Len = syscall.SizeofSockaddrInet6
sa.Family = syscall.AF_INET6
copy(sa.Addr[:], ip)
sa.Scope_id = uint32(ifindex)
}

View File

@@ -0,0 +1,54 @@
// 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"
"syscall"
)
// RFC 2292 options
const (
// See /usr/include/netinet6/in6.h.
sysSockopt2292HopLimit = 0x14
sysSockopt2292PacketInfo = 0x13
sysSockopt2292NextHop = 0x15
)
// RFC 3493 options
const (
// See /usr/include/netinet6/in6.h.
sysSockoptUnicastHopLimit = 0x4
sysSockoptMulticastHopLimit = 0xa
sysSockoptMulticastInterface = 0x9
sysSockoptMulticastLoopback = 0xb
sysSockoptJoinGroup = 0xc
sysSockoptLeaveGroup = 0xd
)
// RFC 3542 options
const (
// See /usr/include/netinet6/in6.h.
sysSockoptReceiveTrafficClass = 0x23
sysSockoptTrafficClass = 0x24
sysSockoptReceiveHopLimit = 0x25
sysSockoptHopLimit = 0x2f
sysSockoptReceivePacketInfo = 0x3d
sysSockoptPacketInfo = 0x2e
sysSockoptReceivePathMTU = 0x2b
sysSockoptPathMTU = 0x2c
sysSockoptNextHop = 0x30
sysSockoptChecksum = 0x1a
// See /usr/include/netinet6/in6.h.
sysSockoptICMPFilter = 0x12
)
func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) {
sa.Len = syscall.SizeofSockaddrInet6
sa.Family = syscall.AF_INET6
copy(sa.Addr[:], ip)
sa.Scope_id = uint32(ifindex)
}

View File

@@ -0,0 +1,45 @@
// 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"
"syscall"
)
// RFC 3493 options
const (
// See /usr/include/linux/in6.h.
sysSockoptUnicastHopLimit = 0x10
sysSockoptMulticastHopLimit = 0x12
sysSockoptMulticastInterface = 0x11
sysSockoptMulticastLoopback = 0x13
sysSockoptJoinGroup = 0x14
sysSockoptLeaveGroup = 0x15
)
// RFC 3542 options
const (
// See /usr/include/linux/ipv6.h,in6.h.
sysSockoptReceiveTrafficClass = 0x42
sysSockoptTrafficClass = 0x43
sysSockoptReceiveHopLimit = 0x33
sysSockoptHopLimit = 0x34
sysSockoptReceivePacketInfo = 0x31
sysSockoptPacketInfo = 0x32
sysSockoptReceivePathMTU = 0x3c
sysSockoptPathMTU = 0x3d
sysSockoptNextHop = 0x9
sysSockoptChecksum = 0x7
// See /usr/include/linux/icmpv6.h.
sysSockoptICMPFilter = 0x1
)
func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) {
sa.Family = syscall.AF_INET6
copy(sa.Addr[:], ip)
sa.Scope_id = uint32(ifindex)
}

View File

@@ -0,0 +1,16 @@
// 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 freebsd linux netbsd openbsd
package ipv6
import "syscall"
const sysSizeofMTUInfo = 0x20
type sysMTUInfo struct {
Addr syscall.RawSockaddrInet6
MTU uint32
}

View File

@@ -0,0 +1,33 @@
// 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"
"syscall"
)
// RFC 3493 options
const (
// See ws2tcpip.h.
sysSockoptUnicastHopLimit = 0x4
sysSockoptMulticastHopLimit = 0xa
sysSockoptMulticastInterface = 0x9
sysSockoptMulticastLoopback = 0xb
sysSockoptJoinGroup = 0xc
sysSockoptLeaveGroup = 0xd
)
// RFC 3542 options
const (
// See ws2tcpip.h.
sysSockoptPacketInfo = 0x13
)
func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) {
sa.Family = syscall.AF_INET6
copy(sa.Addr[:], ip)
sa.Scope_id = uint32(ifindex)
}

View File

@@ -0,0 +1,42 @@
// Copyright 2009 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.
// This code is a duplicate of syscall/syscall_linux_386.go with small
// modifications.
package ipv6
import (
"syscall"
"unsafe"
)
// On x86 Linux, all the socket calls go through an extra indirection,
// I think because the 5-register system call interface can't handle
// the 6-argument calls like sendto and recvfrom. Instead the
// arguments to the underlying system call are the number below and a
// pointer to an array of uintptr. We hide the pointer in the
// socketcall assembly to avoid allocation on every system call.
const (
// See /usr/include/linux/net.h.
_SETSOCKOPT = 14
_GETSOCKOPT = 15
)
var socketcall func(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
func getsockopt(fd int, level int, name int, v uintptr, l *sysSockoptLen) error {
if _, errno := socketcall(_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
return error(errno)
}
return nil
}
func setsockopt(fd int, level int, name int, v uintptr, l uintptr) error {
if _, errno := socketcall(_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), v, l, 0); errno != 0 {
return error(errno)
}
return nil
}

View File

@@ -0,0 +1,56 @@
// Copyright 2009 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.
// This code is a duplicate of syscall/syscall_linux_386.s with small
// modifications.
#define SYS_SOCKETCALL 102 // from zsysnum_linux_386.go
// func socketcallnosplit7(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
// Kernel interface gets call sub-number and pointer to a0 for Go 1.1.
TEXT ·socketcallnosplit7(SB),7,$0
CALL runtime·entersyscall(SB)
MOVL $SYS_SOCKETCALL, AX // syscall entry
MOVL 4(SP), BX // socket call number
LEAL 8(SP), CX // pointer to call arguments
MOVL $0, DX
MOVL $0, SI
MOVL $0, DI
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS ok1
MOVL $-1, 32(SP) // n
NEGL AX
MOVL AX, 36(SP) // errno
CALL runtime·exitsyscall(SB)
RET
ok1:
MOVL AX, 32(SP) // n
MOVL $0, 36(SP) // errno
CALL runtime·exitsyscall(SB)
RET
// func socketcallnosplit4(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
// Kernel interface gets call sub-number and pointer to a0 for Go 1.2.
TEXT ·socketcallnosplit4(SB),4,$0-40
CALL runtime·entersyscall(SB)
MOVL $SYS_SOCKETCALL, AX // syscall entry
MOVL 4(SP), BX // socket call number
LEAL 8(SP), CX // pointer to call arguments
MOVL $0, DX
MOVL $0, SI
MOVL $0, DI
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS ok2
MOVL $-1, 32(SP) // n
NEGL AX
MOVL AX, 36(SP) // errno
CALL runtime·exitsyscall(SB)
RET
ok2:
MOVL AX, 32(SP) // n
MOVL $0, 36(SP) // errno
CALL runtime·exitsyscall(SB)
RET

View File

@@ -0,0 +1,15 @@
// 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 go1.2
package ipv6
import "syscall"
func socketcallnosplit4(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
func init() {
socketcall = socketcallnosplit4
}

View File

@@ -0,0 +1,15 @@
// 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 go1.1,!go1.2
package ipv6
import "syscall"
func socketcallnosplit7(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
func init() {
socketcall = socketcallnosplit7
}

View File

@@ -0,0 +1,26 @@
// 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 freebsd linux,amd64 linux,arm netbsd openbsd
package ipv6
import (
"syscall"
"unsafe"
)
func getsockopt(fd int, level, name int, v uintptr, l *sysSockoptLen) error {
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
return error(errno)
}
return nil
}
func setsockopt(fd int, level int, name int, v uintptr, l uintptr) error {
if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
return error(errno)
}
return nil
}

View File

@@ -5,89 +5,18 @@
package ipv6_test
import (
"bytes"
"code.google.com/p/go.net/ipv6"
"net"
"os"
"runtime"
"testing"
"time"
)
func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
c, err := net.ListenPacket("udp6", "[::1]:0")
if err != nil {
return nil, nil, err
}
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
if err != nil {
c.Close()
return nil, nil, err
}
return c, dst, nil
}
func BenchmarkReadWriteNetUDP(b *testing.B) {
c, dst, err := benchmarkUDPListener()
if err != nil {
b.Fatalf("benchmarkUDPListener failed: %v", err)
}
defer c.Close()
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
b.ResetTimer()
for i := 0; i < b.N; i++ {
benchmarkReadWriteNetUDP(b, c, wb, rb, dst)
}
}
func benchmarkReadWriteNetUDP(b *testing.B, c net.PacketConn, wb, rb []byte, dst net.Addr) {
if _, err := c.WriteTo(wb, dst); err != nil {
b.Fatalf("net.PacketConn.WriteTo failed: %v", err)
}
if _, _, err := c.ReadFrom(rb); err != nil {
b.Fatalf("net.PacketConn.ReadFrom failed: %v", err)
}
}
func BenchmarkReadWriteIPv6UDP(b *testing.B) {
c, dst, err := benchmarkUDPListener()
if err != nil {
b.Fatalf("benchmarkUDPListener failed: %v", err)
}
defer c.Close()
p := ipv6.NewPacketConn(c)
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
if err := p.SetControlMessage(cf, true); err != nil {
b.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
}
ifi := loopbackInterface()
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
b.ResetTimer()
for i := 0; i < b.N; i++ {
benchmarkReadWriteIPv6UDP(b, p, wb, rb, dst, ifi)
}
}
func benchmarkReadWriteIPv6UDP(b *testing.B, p *ipv6.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
HopLimit: 1,
}
if ifi != nil {
cm.IfIndex = ifi.Index
}
if _, err := p.WriteTo(wb, &cm, dst); err != nil {
b.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
}
if _, _, _, err := p.ReadFrom(rb); err != nil {
b.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
}
}
func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
@@ -99,33 +28,47 @@ func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
p := ipv6.NewPacketConn(c)
defer p.Close()
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
if err != nil {
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
}
p := ipv6.NewPacketConn(c)
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
Src: net.IPv6loopback,
Dst: net.IPv6loopback,
}
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
ifi := loopbackInterface()
if ifi != nil {
cm.IfIndex = ifi.Index
}
wb := []byte("HELLO-R-U-THERE")
for i, toggle := range []bool{true, false, true} {
if err := p.SetControlMessage(cf, toggle); err != nil {
t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
}
cm.HopLimit = i + 1
if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv6.PacketConn.SetWriteDeadline failed: %v", err)
}
b := make([]byte, 128)
if _, cm, _, err := p.ReadFrom(b); err != nil {
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
} else if n != len(wb) {
t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
}
rb := make([]byte, 128)
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv6.PacketConn.SetReadDeadline failed: %v", err)
}
if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
} else if !bytes.Equal(rb[:n], wb) {
t.Fatalf("got %v; expected %v", rb[:n], wb)
} else {
t.Logf("rcvd cmsg: %v", cm)
}
@@ -134,7 +77,7 @@ func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
case "dragonfly", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
@@ -149,15 +92,21 @@ func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
p := ipv6.NewPacketConn(c)
defer p.Close()
dst, err := net.ResolveIPAddr("ip6", "::1")
if err != nil {
t.Fatalf("net.ResolveIPAddr failed: %v", err)
}
p := ipv6.NewPacketConn(c)
cm := ipv6.ControlMessage{TrafficClass: DiffServAF11 | CongestionExperienced}
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
pshicmp := ipv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP, ianaProtocolIPv6ICMP)
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
Src: net.IPv6loopback,
Dst: net.IPv6loopback,
}
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
ifi := loopbackInterface()
if ifi != nil {
cm.IfIndex = ifi.Index
@@ -170,14 +119,26 @@ func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
t.Fatalf("ipv6.PacketConn.SetICMPFilter failed: %v", err)
}
var psh []byte
for i, toggle := range []bool{true, false, true} {
if toggle {
psh = nil
if err := p.SetChecksum(true, 2); err != nil {
t.Fatalf("ipv6.PacketConn.SetChecksum failed: %v", err)
}
} else {
psh = pshicmp
// Some platforms never allow to disable the
// kernel checksum processing.
p.SetChecksum(false, -1)
}
wb, err := (&icmpMessage{
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
Body: &icmpEcho{
ID: os.Getpid() & 0xffff, Seq: i + 1,
Data: []byte("HELLO-R-U-THERE"),
},
}).Marshal()
}).Marshal(psh)
if err != nil {
t.Fatalf("icmpMessage.Marshal failed: %v", err)
}
@@ -185,15 +146,23 @@ func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
}
cm.HopLimit = i + 1
if _, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv6.PacketConn.SetWriteDeadline failed: %v", err)
}
b := make([]byte, 128)
if n, cm, _, err := p.ReadFrom(b); err != nil {
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
} else if n != len(wb) {
t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
}
rb := make([]byte, 128)
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv6.PacketConn.SetReadDeadline failed: %v", err)
}
if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
if m, err := parseICMPMessage(b[:n]); err != nil {
if m, err := parseICMPMessage(rb[:n]); err != nil {
t.Fatalf("parseICMPMessage failed: %v", err)
} else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)

View File

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