1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-06-30 01:52:26 +08:00

mdns: use my fork of hashicorp/mdns

upstream didn't respond to the request to update their dependencies
This commit is contained in:
Henry
2015-05-29 01:27:42 +02:00
parent b3e73c62fe
commit 13a7d27b4c
203 changed files with 7255 additions and 4196 deletions

33
Godeps/Godeps.json generated
View File

@ -14,11 +14,6 @@
"Comment": "null-15",
"Rev": "35bc42037350f0078e3c974c6ea690f1926603ab"
},
{
"ImportPath": "code.google.com/p/go.net/internal/iana",
"Comment": "null-240",
"Rev": "937a34c9de13c766c814510f76bca091dee06028"
},
{
"ImportPath": "github.com/ActiveState/tail",
"Rev": "068b72961a6bc5b4a82cf4fc14ccc724c0cfa73a"
@ -68,6 +63,10 @@
"ImportPath": "github.com/crowdmob/goamz/s3",
"Rev": "82345796204222aa56be89cf930c316b1297f906"
},
{
"ImportPath": "github.com/cryptix/mdns",
"Rev": "04ff72a32679d57d009c0ac0fc5c4cda10350bad"
},
{
"ImportPath": "github.com/dustin/go-humanize",
"Rev": "00897f070f09f194c26d65afae734ba4c32404e8"
@ -97,22 +96,10 @@
"ImportPath": "github.com/h2so5/utp",
"Rev": "6ca83358f5c331028feb9b97c445e9c7354967b0"
},
{
"ImportPath": "github.com/hashicorp/go.net/ipv4",
"Rev": "cbad13bf000d0cbdbc71506b26e94bcc72bbe74d"
},
{
"ImportPath": "github.com/hashicorp/go.net/ipv6",
"Rev": "cbad13bf000d0cbdbc71506b26e94bcc72bbe74d"
},
{
"ImportPath": "github.com/hashicorp/golang-lru",
"Rev": "253b2dc1ca8bae42c3b5b6e53dd2eab1a7551116"
},
{
"ImportPath": "github.com/hashicorp/mdns",
"Rev": "2b439d37011456df8ff83a70ffd1cd6046410113"
},
{
"ImportPath": "github.com/hashicorp/yamux",
"Rev": "9feabe6854fadca1abec9cd3bd2a613fe9a34000"
@ -265,6 +252,18 @@
"ImportPath": "golang.org/x/net/context",
"Rev": "ff8eb9a34a5cbb9941ffc6f84a19a8014c2646ad"
},
{
"ImportPath": "golang.org/x/net/internal/iana",
"Rev": "ff8eb9a34a5cbb9941ffc6f84a19a8014c2646ad"
},
{
"ImportPath": "golang.org/x/net/ipv4",
"Rev": "ff8eb9a34a5cbb9941ffc6f84a19a8014c2646ad"
},
{
"ImportPath": "golang.org/x/net/ipv6",
"Rev": "ff8eb9a34a5cbb9941ffc6f84a19a8014c2646ad"
},
{
"ImportPath": "gopkg.in/fsnotify.v1",
"Comment": "v1.2.0",

View File

@ -8,9 +8,9 @@ import (
"sync"
"time"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/hashicorp/go.net/ipv4"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/hashicorp/go.net/ipv6"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/miekg/dns"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/ipv4"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/ipv6"
)
// ServiceEntry is returned after we query for a service

View File

@ -1,129 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd windows
package ipv4
import (
"net"
"syscall"
)
// MulticastTTL returns the time-to-live field value for outgoing
// multicast packets.
func (c *dgramOpt) MulticastTTL() (int, error) {
if !c.ok() {
return 0, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return 0, err
}
return getInt(fd, &sockOpts[ssoMulticastTTL])
}
// SetMulticastTTL sets the time-to-live field value for future
// outgoing multicast packets.
func (c *dgramOpt) SetMulticastTTL(ttl int) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setInt(fd, &sockOpts[ssoMulticastTTL], ttl)
}
// MulticastInterface returns the default interface for multicast
// packet transmissions.
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
if !c.ok() {
return nil, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return nil, err
}
return getInterface(fd, &sockOpts[ssoMulticastInterface])
}
// SetMulticastInterface sets the default interface for future
// multicast packet transmissions.
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setInterface(fd, &sockOpts[ssoMulticastInterface], ifi)
}
// MulticastLoopback reports whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) MulticastLoopback() (bool, error) {
if !c.ok() {
return false, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return false, err
}
on, err := getInt(fd, &sockOpts[ssoMulticastLoopback])
if err != nil {
return false, err
}
return on == 1, nil
}
// SetMulticastLoopback sets whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setInt(fd, &sockOpts[ssoMulticastLoopback], boolint(on))
}
// JoinGroup joins the group address group on the interface ifi.
// It uses the system assigned multicast interface when ifi is nil,
// although this is not recommended because the assignment depends on
// platforms and sometimes it might require routing configuration.
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP4(group)
if grp == nil {
return errMissingAddress
}
return setGroup(fd, &sockOpts[ssoJoinGroup], ifi, grp)
}
// LeaveGroup leaves the group address group on the interface ifi.
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP4(group)
if grp == nil {
return errMissingAddress
}
return setGroup(fd, &sockOpts[ssoLeaveGroup], ifi, grp)
}

View File

@ -1,49 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build nacl plan9 solaris
package ipv4
import "net"
func (c *dgramOpt) MulticastTTL() (int, error) {
// TODO(mikio): Implement this
return 0, errOpNoSupport
}
func (c *dgramOpt) SetMulticastTTL(ttl int) error {
// TODO(mikio): Implement this
return errOpNoSupport
}
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
// TODO(mikio): Implement this
return nil, errOpNoSupport
}
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
// TODO(mikio): Implement this
return errOpNoSupport
}
func (c *dgramOpt) MulticastLoopback() (bool, error) {
// TODO(mikio): Implement this
return false, errOpNoSupport
}
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
// TODO(mikio): Implement this
return errOpNoSupport
}
func (c *dgramOpt) JoinGroup(ifi *net.Interface, grp net.Addr) error {
// TODO(mikio): Implement this
return errOpNoSupport
}
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, grp net.Addr) error {
// TODO(mikio): Implement this
return errOpNoSupport
}

View File

@ -1,31 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package ipv4_test
import (
"os"
"syscall"
)
func protocolNotSupported(err error) bool {
switch err := err.(type) {
case syscall.Errno:
switch err {
case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
return true
}
case *os.SyscallError:
switch err := err.Err.(type) {
case syscall.Errno:
switch err {
case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
return true
}
}
}
return false
}

View File

@ -1,285 +0,0 @@
// Copyright 2012 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 ipv4_test
import (
"log"
"net"
"code.google.com/p/go.net/ipv4"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
)
func ExampleUnicastTCPListener() {
ln, err := net.Listen("tcp4", "0.0.0.0:1024")
if err != nil {
log.Fatal(err)
}
defer ln.Close()
for {
c, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
go func(c net.Conn) {
defer c.Close()
err := ipv4.NewConn(c).SetTOS(iana.DiffServAF11)
if err != nil {
log.Fatal(err)
}
_, err = c.Write([]byte("HELLO-R-U-THERE-ACK"))
if err != nil {
log.Fatal(err)
}
}(c)
}
}
func ExampleMulticastUDPListener() {
en0, err := net.InterfaceByName("en0")
if err != nil {
log.Fatal(err)
}
en1, err := net.InterfaceByIndex(911)
if err != nil {
log.Fatal(err)
}
group := net.IPv4(224, 0, 0, 250)
c, err := net.ListenPacket("udp4", "0.0.0.0:1024")
if err != nil {
log.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
err = p.JoinGroup(en0, &net.UDPAddr{IP: group})
if err != nil {
log.Fatal(err)
}
err = p.JoinGroup(en1, &net.UDPAddr{IP: group})
if err != nil {
log.Fatal(err)
}
err = p.SetControlMessage(ipv4.FlagDst, true)
if err != nil {
log.Fatal(err)
}
b := make([]byte, 1500)
for {
n, cm, src, err := p.ReadFrom(b)
if err != nil {
log.Fatal(err)
}
if cm.Dst.IsMulticast() {
if cm.Dst.Equal(group) {
// joined group, do something
} else {
// unknown group, discard
continue
}
}
p.SetTOS(iana.DiffServCS7)
p.SetTTL(16)
_, err = p.WriteTo(b[:n], nil, src)
if err != nil {
log.Fatal(err)
}
dst := &net.UDPAddr{IP: group, Port: 1024}
for _, ifi := range []*net.Interface{en0, en1} {
err := p.SetMulticastInterface(ifi)
if err != nil {
log.Fatal(err)
}
p.SetMulticastTTL(2)
_, err = p.WriteTo(b[:n], nil, dst)
if err != nil {
log.Fatal(err)
}
}
}
err = p.LeaveGroup(en1, &net.UDPAddr{IP: group})
if err != nil {
log.Fatal(err)
}
newgroup := net.IPv4(224, 0, 0, 249)
err = p.JoinGroup(en1, &net.UDPAddr{IP: newgroup})
if err != nil {
log.Fatal(err)
}
}
type OSPFHeader struct {
Version byte
Type byte
Len uint16
RouterID uint32
AreaID uint32
Checksum uint16
}
const (
OSPFHeaderLen = 14
OSPFHelloHeaderLen = 20
OSPF_VERSION = 2
OSPF_TYPE_HELLO = iota + 1
OSPF_TYPE_DB_DESCRIPTION
OSPF_TYPE_LS_REQUEST
OSPF_TYPE_LS_UPDATE
OSPF_TYPE_LS_ACK
)
var (
AllSPFRouters = net.IPv4(224, 0, 0, 5)
AllDRouters = net.IPv4(224, 0, 0, 6)
)
func ExampleIPOSPFListener() {
var ifs []*net.Interface
en0, err := net.InterfaceByName("en0")
if err != nil {
log.Fatal(err)
}
ifs = append(ifs, en0)
en1, err := net.InterfaceByIndex(911)
if err != nil {
log.Fatal(err)
}
ifs = append(ifs, en1)
c, err := net.ListenPacket("ip4:89", "0.0.0.0") // OSFP for IPv4
if err != nil {
log.Fatal(err)
}
defer c.Close()
r, err := ipv4.NewRawConn(c)
if err != nil {
log.Fatal(err)
}
for _, ifi := range ifs {
err := r.JoinGroup(ifi, &net.IPAddr{IP: AllSPFRouters})
if err != nil {
log.Fatal(err)
}
err = r.JoinGroup(ifi, &net.IPAddr{IP: AllDRouters})
if err != nil {
log.Fatal(err)
}
}
err = r.SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
if err != nil {
log.Fatal(err)
}
r.SetTOS(iana.DiffServCS6)
parseOSPFHeader := func(b []byte) *OSPFHeader {
if len(b) < OSPFHeaderLen {
return nil
}
return &OSPFHeader{
Version: b[0],
Type: b[1],
Len: uint16(b[2])<<8 | uint16(b[3]),
RouterID: uint32(b[4])<<24 | uint32(b[5])<<16 | uint32(b[6])<<8 | uint32(b[7]),
AreaID: uint32(b[8])<<24 | uint32(b[9])<<16 | uint32(b[10])<<8 | uint32(b[11]),
Checksum: uint16(b[12])<<8 | uint16(b[13]),
}
}
b := make([]byte, 1500)
for {
iph, p, _, err := r.ReadFrom(b)
if err != nil {
log.Fatal(err)
}
if iph.Version != ipv4.Version {
continue
}
if iph.Dst.IsMulticast() {
if !iph.Dst.Equal(AllSPFRouters) && !iph.Dst.Equal(AllDRouters) {
continue
}
}
ospfh := parseOSPFHeader(p)
if ospfh == nil {
continue
}
if ospfh.Version != OSPF_VERSION {
continue
}
switch ospfh.Type {
case OSPF_TYPE_HELLO:
case OSPF_TYPE_DB_DESCRIPTION:
case OSPF_TYPE_LS_REQUEST:
case OSPF_TYPE_LS_UPDATE:
case OSPF_TYPE_LS_ACK:
}
}
}
func ExampleWriteIPOSPFHello() {
var ifs []*net.Interface
en0, err := net.InterfaceByName("en0")
if err != nil {
log.Fatal(err)
}
ifs = append(ifs, en0)
en1, err := net.InterfaceByIndex(911)
if err != nil {
log.Fatal(err)
}
ifs = append(ifs, en1)
c, err := net.ListenPacket("ip4:89", "0.0.0.0") // OSPF for IPv4
if err != nil {
log.Fatal(err)
}
defer c.Close()
r, err := ipv4.NewRawConn(c)
if err != nil {
log.Fatal(err)
}
for _, ifi := range ifs {
err := r.JoinGroup(ifi, &net.IPAddr{IP: AllSPFRouters})
if err != nil {
log.Fatal(err)
}
err = r.JoinGroup(ifi, &net.IPAddr{IP: AllDRouters})
if err != nil {
log.Fatal(err)
}
}
hello := make([]byte, OSPFHelloHeaderLen)
ospf := make([]byte, OSPFHeaderLen)
ospf[0] = OSPF_VERSION
ospf[1] = OSPF_TYPE_HELLO
ospf = append(ospf, hello...)
iph := &ipv4.Header{}
iph.Version = ipv4.Version
iph.Len = ipv4.HeaderLen
iph.TOS = iana.DiffServCS6
iph.TotalLen = ipv4.HeaderLen + len(ospf)
iph.TTL = 1
iph.Protocol = 89
iph.Dst = AllSPFRouters
for _, ifi := range ifs {
err := r.SetMulticastInterface(ifi)
if err != nil {
return
}
err = r.WriteTo(iph, ospf, nil)
if err != nil {
return
}
}
}

View File

@ -1,16 +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 ipv4
// An ICMPType represents a type of ICMP message.
type ICMPType int
func (typ ICMPType) String() string {
s, ok := icmpTypes[typ]
if !ok {
return "<nil>"
}
return s
}

View File

@ -1,267 +0,0 @@
// Copyright 2012 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 ipv4_test
import (
"net"
"os"
"runtime"
"testing"
"time"
"code.google.com/p/go.net/internal/icmp"
"code.google.com/p/go.net/internal/nettest"
"code.google.com/p/go.net/ipv4"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
)
func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
c, err := net.ListenPacket("udp4", "224.0.0.0:0") // see RFC 4727
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
_, port, err := net.SplitHostPort(c.LocalAddr().String())
if err != nil {
t.Fatalf("net.SplitHostPort failed: %v", err)
}
dst, err := net.ResolveUDPAddr("udp4", "224.0.0.254:"+port) // see RFC 4727
if err != nil {
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
}
p := ipv4.NewPacketConn(c)
defer p.Close()
if err := p.JoinGroup(ifi, dst); err != nil {
t.Fatalf("ipv4.PacketConn.JoinGroup on %v failed: %v", ifi, err)
}
if err := p.SetMulticastInterface(ifi); err != nil {
t.Fatalf("ipv4.PacketConn.SetMulticastInterface failed: %v", err)
}
if _, err := p.MulticastInterface(); err != nil {
t.Fatalf("ipv4.PacketConn.MulticastInterface failed: %v", err)
}
if err := p.SetMulticastLoopback(true); err != nil {
t.Fatalf("ipv4.PacketConn.SetMulticastLoopback failed: %v", err)
}
if _, err := p.MulticastLoopback(); err != nil {
t.Fatalf("ipv4.PacketConn.MulticastLoopback failed: %v", err)
}
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
for i, toggle := range []bool{true, false, true} {
if err := p.SetControlMessage(cf, toggle); err != nil {
if protocolNotSupported(err) {
t.Skipf("not supported on %q", runtime.GOOS)
}
t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
}
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatalf("ipv4.PacketConn.SetDeadline failed: %v", err)
}
p.SetMulticastTTL(i + 1)
if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), nil, dst); err != nil {
t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
}
b := make([]byte, 128)
if _, cm, _, err := p.ReadFrom(b); err != nil {
t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
}
}
}
func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if os.Getuid() != 0 {
t.Skip("must be root")
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
dst, err := net.ResolveIPAddr("ip4", "224.0.0.254") // see RFC 4727
if err != nil {
t.Fatalf("net.ResolveIPAddr failed: %v", err)
}
p := ipv4.NewPacketConn(c)
defer p.Close()
if err := p.JoinGroup(ifi, dst); err != nil {
t.Fatalf("ipv4.PacketConn.JoinGroup on %v failed: %v", ifi, err)
}
if err := p.SetMulticastInterface(ifi); err != nil {
t.Fatalf("ipv4.PacketConn.SetMulticastInterface failed: %v", err)
}
if _, err := p.MulticastInterface(); err != nil {
t.Fatalf("ipv4.PacketConn.MulticastInterface failed: %v", err)
}
if err := p.SetMulticastLoopback(true); err != nil {
t.Fatalf("ipv4.PacketConn.SetMulticastLoopback failed: %v", err)
}
if _, err := p.MulticastLoopback(); err != nil {
t.Fatalf("ipv4.PacketConn.MulticastLoopback failed: %v", err)
}
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
for i, toggle := range []bool{true, false, true} {
wb, err := (&icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff, Seq: i + 1,
Data: []byte("HELLO-R-U-THERE"),
},
}).Marshal(nil)
if err != nil {
t.Fatalf("icmp.Message.Marshal failed: %v", err)
}
if err := p.SetControlMessage(cf, toggle); err != nil {
if protocolNotSupported(err) {
t.Skipf("not supported on %q", runtime.GOOS)
}
t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
}
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatalf("ipv4.PacketConn.SetDeadline failed: %v", err)
}
p.SetMulticastTTL(i + 1)
if _, err := p.WriteTo(wb, nil, dst); err != nil {
t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
}
b := make([]byte, 128)
if n, cm, _, err := p.ReadFrom(b); err != nil {
t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
m, err := icmp.ParseMessage(iana.ProtocolICMP, b[:n])
if err != nil {
t.Fatalf("icmp.ParseMessage failed: %v", err)
}
switch {
case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
default:
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
}
}
}
}
func TestRawConnReadWriteMulticastICMP(t *testing.T) {
if testing.Short() {
t.Skip("to avoid external network")
}
if os.Getuid() != 0 {
t.Skip("must be root")
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
dst, err := net.ResolveIPAddr("ip4", "224.0.0.254") // see RFC 4727
if err != nil {
t.Fatalf("ResolveIPAddr failed: %v", err)
}
r, err := ipv4.NewRawConn(c)
if err != nil {
t.Fatalf("ipv4.NewRawConn failed: %v", err)
}
defer r.Close()
if err := r.JoinGroup(ifi, dst); err != nil {
t.Fatalf("ipv4.RawConn.JoinGroup on %v failed: %v", ifi, err)
}
if err := r.SetMulticastInterface(ifi); err != nil {
t.Fatalf("ipv4.RawConn.SetMulticastInterface failed: %v", err)
}
if _, err := r.MulticastInterface(); err != nil {
t.Fatalf("ipv4.RawConn.MulticastInterface failed: %v", err)
}
if err := r.SetMulticastLoopback(true); err != nil {
t.Fatalf("ipv4.RawConn.SetMulticastLoopback failed: %v", err)
}
if _, err := r.MulticastLoopback(); err != nil {
t.Fatalf("ipv4.RawConn.MulticastLoopback failed: %v", err)
}
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
for i, toggle := range []bool{true, false, true} {
wb, err := (&icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff, Seq: i + 1,
Data: []byte("HELLO-R-U-THERE"),
},
}).Marshal(nil)
if err != nil {
t.Fatalf("icmp.Message.Marshal failed: %v", err)
}
wh := &ipv4.Header{
Version: ipv4.Version,
Len: ipv4.HeaderLen,
TOS: i + 1,
TotalLen: ipv4.HeaderLen + len(wb),
Protocol: 1,
Dst: dst.IP,
}
if err := r.SetControlMessage(cf, toggle); err != nil {
if protocolNotSupported(err) {
t.Skipf("not supported on %q", runtime.GOOS)
}
t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", err)
}
if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatalf("ipv4.RawConn.SetDeadline failed: %v", err)
}
r.SetMulticastTTL(i + 1)
if err := r.WriteTo(wh, wb, nil); err != nil {
t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err)
}
rb := make([]byte, ipv4.HeaderLen+128)
if rh, b, cm, err := r.ReadFrom(rb); err != nil {
t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
if err != nil {
t.Fatalf("icmp.ParseMessage failed: %v", err)
}
switch {
case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
default:
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
}
}
}
}

View File

@ -1,113 +0,0 @@
// Copyright 2012 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 ipv4_test
import (
"net"
"os"
"runtime"
"testing"
"code.google.com/p/go.net/internal/nettest"
"code.google.com/p/go.net/ipv4"
)
var packetConnMulticastSocketOptionTests = []struct {
net, proto, addr string
gaddr net.Addr
}{
{"udp4", "", "224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}}, // see RFC 4727
{"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}}, // see RFC 4727
}
func TestPacketConnMulticastSocketOptions(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris":
t.Skipf("not supported on %q", runtime.GOOS)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
for _, tt := range packetConnMulticastSocketOptionTests {
if tt.net == "ip4" && os.Getuid() != 0 {
t.Skip("must be root")
}
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
testMulticastSocketOptions(t, ipv4.NewPacketConn(c), ifi, tt.gaddr)
}
}
func TestRawConnMulticastSocketOptions(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris":
t.Skipf("not supported on %q", runtime.GOOS)
}
if os.Getuid() != 0 {
t.Skip("must be root")
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
r, err := ipv4.NewRawConn(c)
if err != nil {
t.Fatalf("ipv4.NewRawConn failed: %v", err)
}
testMulticastSocketOptions(t, r, ifi, &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}) /// see RFC 4727
}
type testIPv4MulticastConn interface {
MulticastTTL() (int, error)
SetMulticastTTL(ttl int) error
MulticastLoopback() (bool, error)
SetMulticastLoopback(bool) error
JoinGroup(*net.Interface, net.Addr) error
LeaveGroup(*net.Interface, net.Addr) error
}
func testMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, gaddr net.Addr) {
const ttl = 255
if err := c.SetMulticastTTL(ttl); err != nil {
t.Fatalf("ipv4.PacketConn.SetMulticastTTL failed: %v", err)
}
if v, err := c.MulticastTTL(); err != nil {
t.Fatalf("ipv4.PacketConn.MulticastTTL failed: %v", err)
} else if v != ttl {
t.Fatalf("got unexpected multicast TTL value %v; expected %v", v, ttl)
}
for _, toggle := range []bool{true, false} {
if err := c.SetMulticastLoopback(toggle); err != nil {
t.Fatalf("ipv4.PacketConn.SetMulticastLoopback failed: %v", err)
}
if v, err := c.MulticastLoopback(); err != nil {
t.Fatalf("ipv4.PacketConn.MulticastLoopback failed: %v", err)
} else if v != toggle {
t.Fatalf("got unexpected multicast loopback %v; expected %v", v, toggle)
}
}
if err := c.JoinGroup(ifi, gaddr); err != nil {
t.Fatalf("ipv4.PacketConn.JoinGroup(%v, %v) failed: %v", ifi, gaddr, err)
}
if err := c.LeaveGroup(ifi, gaddr); err != nil {
t.Fatalf("ipv4.PacketConn.LeaveGroup(%v, %v) failed: %v", ifi, gaddr, err)
}
}

View File

@ -1,29 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build nacl plan9 solaris
package ipv4
import "net"
func getInt(fd int, opt *sockOpt) (int, error) {
return 0, errOpNoSupport
}
func setInt(fd int, opt *sockOpt, v int) error {
return errOpNoSupport
}
func getInterface(fd int, opt *sockOpt) (*net.Interface, error) {
return nil, errOpNoSupport
}
func setInterface(fd int, opt *sockOpt, ifi *net.Interface) error {
return errOpNoSupport
}
func setGroup(fd int, opt *sockOpt, ifi *net.Interface, ip net.IP) error {
return errOpNoSupport
}

View File

@ -1,31 +0,0 @@
// Copyright 2014 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 ipv4
type sysSockoptLen int32
var (
ctlOpts = [ctlMax]ctlOpt{
ctlTTL: {sysIP_TTL, 1, marshalTTL, parseTTL},
ctlPacketInfo: {sysIP_PKTINFO, sysSizeofInetPktinfo, marshalPacketInfo, parsePacketInfo},
}
sockOpts = [ssoMax]sockOpt{
ssoTOS: {sysIP_TOS, ssoTypeInt},
ssoTTL: {sysIP_TTL, ssoTypeInt},
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeInt},
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeIPMreqn},
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt},
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt},
ssoPacketInfo: {sysIP_PKTINFO, ssoTypeInt},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreqn},
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreqn},
}
)
func (pi *sysInetPktinfo) setIfindex(i int) {
pi.Ifindex = int32(i)
}

View File

@ -1,300 +0,0 @@
// Copyright 2012 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 ipv4_test
import (
"net"
"os"
"runtime"
"testing"
"time"
"code.google.com/p/go.net/internal/icmp"
"code.google.com/p/go.net/internal/nettest"
"code.google.com/p/go.net/ipv4"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
)
func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
c, err := net.ListenPacket("udp4", "127.0.0.1:0")
if err != nil {
return nil, nil, err
}
dst, err := net.ResolveUDPAddr("udp4", 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 BenchmarkReadWriteIPv4UDP(b *testing.B) {
c, dst, err := benchmarkUDPListener()
if err != nil {
b.Fatalf("benchmarkUDPListener failed: %v", err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
defer p.Close()
cf := ipv4.FlagTTL | ipv4.FlagInterface
if err := p.SetControlMessage(cf, true); err != nil {
b.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
b.ResetTimer()
for i := 0; i < b.N; i++ {
benchmarkReadWriteIPv4UDP(b, p, wb, rb, dst, ifi)
}
}
func benchmarkReadWriteIPv4UDP(b *testing.B, p *ipv4.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
cm := ipv4.ControlMessage{TTL: 1}
if ifi != nil {
cm.IfIndex = ifi.Index
}
if _, err := p.WriteTo(wb, &cm, dst); err != nil {
b.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
}
if _, _, _, err := p.ReadFrom(rb); err != nil {
b.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
}
}
func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
c, err := net.ListenPacket("udp4", "127.0.0.1:0")
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
if err != nil {
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
}
p := ipv4.NewPacketConn(c)
defer p.Close()
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
for i, toggle := range []bool{true, false, true} {
if err := p.SetControlMessage(cf, toggle); err != nil {
if protocolNotSupported(err) {
t.Skipf("not supported on %q", runtime.GOOS)
}
t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
}
p.SetTTL(i + 1)
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv4.PacketConn.SetWriteDeadline failed: %v", err)
}
if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), nil, dst); err != nil {
t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
}
rb := make([]byte, 128)
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv4.PacketConn.SetReadDeadline failed: %v", err)
}
if _, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
}
}
}
func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if os.Getuid() != 0 {
t.Skip("must be root")
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
if err != nil {
t.Fatalf("ResolveIPAddr failed: %v", err)
}
p := ipv4.NewPacketConn(c)
defer p.Close()
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
for i, toggle := range []bool{true, false, true} {
wb, err := (&icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff, Seq: i + 1,
Data: []byte("HELLO-R-U-THERE"),
},
}).Marshal(nil)
if err != nil {
t.Fatalf("icmp.Message.Marshal failed: %v", err)
}
if err := p.SetControlMessage(cf, toggle); err != nil {
if protocolNotSupported(err) {
t.Skipf("not supported on %q", runtime.GOOS)
}
t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
}
p.SetTTL(i + 1)
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv4.PacketConn.SetWriteDeadline failed: %v", err)
}
if _, err := p.WriteTo(wb, nil, dst); err != nil {
t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
}
b := make([]byte, 128)
loop:
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv4.PacketConn.SetReadDeadline failed: %v", err)
}
if n, cm, _, err := p.ReadFrom(b); err != nil {
t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
m, err := icmp.ParseMessage(iana.ProtocolICMP, b[:n])
if err != nil {
t.Fatalf("icmp.ParseMessage failed: %v", err)
}
if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
// On Linux we must handle own sent packets.
goto loop
}
if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
}
}
}
}
func TestRawConnReadWriteUnicastICMP(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if os.Getuid() != 0 {
t.Skip("must be root")
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
if err != nil {
t.Fatalf("ResolveIPAddr failed: %v", err)
}
r, err := ipv4.NewRawConn(c)
if err != nil {
t.Fatalf("ipv4.NewRawConn failed: %v", err)
}
defer r.Close()
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
for i, toggle := range []bool{true, false, true} {
wb, err := (&icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff, Seq: i + 1,
Data: []byte("HELLO-R-U-THERE"),
},
}).Marshal(nil)
if err != nil {
t.Fatalf("icmp.Message.Marshal failed: %v", err)
}
wh := &ipv4.Header{
Version: ipv4.Version,
Len: ipv4.HeaderLen,
TOS: i + 1,
TotalLen: ipv4.HeaderLen + len(wb),
TTL: i + 1,
Protocol: 1,
Dst: dst.IP,
}
if err := r.SetControlMessage(cf, toggle); err != nil {
if protocolNotSupported(err) {
t.Skipf("not supported on %q", runtime.GOOS)
}
t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", err)
}
if err := r.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv4.RawConn.SetWriteDeadline failed: %v", err)
}
if err := r.WriteTo(wh, wb, nil); err != nil {
t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err)
}
rb := make([]byte, ipv4.HeaderLen+128)
loop:
if err := r.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
t.Fatalf("ipv4.RawConn.SetReadDeadline failed: %v", err)
}
if _, b, cm, err := r.ReadFrom(rb); err != nil {
t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
if err != nil {
t.Fatalf("icmp.ParseMessage failed: %v", err)
}
if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
// On Linux we must handle own sent packets.
goto loop
}
if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
}
}
}
}

View File

@ -1,151 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin
package ipv6
import (
"net"
"os"
"syscall"
"unsafe"
)
const pktinfo = FlagDst | FlagInterface
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
opt.Lock()
defer opt.Unlock()
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)
}
}
return nil
}
func newControlMessage(opt *rawOpt) (oob []byte) {
opt.Lock()
defer opt.Unlock()
l, off := 0, 0
if opt.isset(FlagHopLimit) {
l += syscall.CmsgSpace(4)
}
if opt.isset(pktinfo) {
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 = 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 = sysSockopt2292PacketInfo
m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
off += syscall.CmsgSpace(sysSizeofPacketInfo)
}
}
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 sysSockopt2292HopLimit:
cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
case sysSockopt2292PacketInfo:
pi := (*sysPacketInfo)(unsafe.Pointer(&m.Data[0]))
cm.IfIndex = int(pi.IfIndex)
cm.Dst = pi.IP[:]
}
}
return cm, nil
}
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
if cm == nil {
return
}
l, off := 0, 0
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(sysSizeofPacketInfo)
}
if len(cm.NextHop) == net.IPv6len {
l += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
}
if l > 0 {
oob = make([]byte, l)
if cm.HopLimit > 0 {
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
m.Level = ianaProtocolIPv6
m.Type = sysSockopt2292HopLimit
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 = 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.IP[:], ip)
}
if cm.IfIndex != 0 {
pi.IfIndex = uint32(cm.IfIndex)
}
off += syscall.CmsgSpace(sysSizeofPacketInfo)
}
if len(cm.NextHop) == net.IPv6len {
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
m.Level = ianaProtocolIPv6
m.Type = sysSockopt2292NextHop
m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
setSockaddr(sa, cm.NextHop, cm.IfIndex)
off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
}
}
return
}

View File

@ -1,210 +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 dragonfly freebsd linux netbsd openbsd
package ipv6
import (
"net"
"os"
"syscall"
"unsafe"
)
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(sysSizeofPacketInfo)
}
if opt.isset(FlagPathMTU) {
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 = 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 = 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 = 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 = sysSockoptReceivePathMTU
m.SetLen(syscall.CmsgLen(sysSizeofMTUInfo))
off += syscall.CmsgSpace(sysSizeofMTUInfo)
}
}
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 sysSockoptTrafficClass:
cm.TrafficClass = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
case sysSockoptHopLimit:
cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][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)
}
}
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(sysSizeofPacketInfo)
}
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 = sysSockoptTrafficClass
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 = sysSockoptHopLimit
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 = 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.IP[:], ip)
}
if cm.IfIndex != 0 {
pi.IfIndex = uint32(cm.IfIndex)
}
off += syscall.CmsgSpace(sysSizeofPacketInfo)
}
if len(cm.NextHop) == net.IPv6len {
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
m.Level = ianaProtocolIPv6
m.Type = sysSockoptNextHop
m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
setSockaddr(sa, cm.NextHop, cm.IfIndex)
off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
}
}
return
}

View File

@ -1,178 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd windows
package ipv6
import (
"net"
"syscall"
)
// MulticastHopLimit returns the hop limit field value for outgoing
// multicast packets.
func (c *dgramOpt) MulticastHopLimit() (int, error) {
if !c.ok() {
return 0, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return 0, err
}
return ipv6MulticastHopLimit(fd)
}
// SetMulticastHopLimit sets the hop limit field value for future
// outgoing multicast packets.
func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setIPv6MulticastHopLimit(fd, hoplim)
}
// MulticastInterface returns the default interface for multicast
// packet transmissions.
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
if !c.ok() {
return nil, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return nil, err
}
return ipv6MulticastInterface(fd)
}
// SetMulticastInterface sets the default interface for future
// multicast packet transmissions.
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setIPv6MulticastInterface(fd, ifi)
}
// MulticastLoopback reports whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) MulticastLoopback() (bool, error) {
if !c.ok() {
return false, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return false, err
}
return ipv6MulticastLoopback(fd)
}
// SetMulticastLoopback sets whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setIPv6MulticastLoopback(fd, on)
}
// JoinGroup joins the group address group on the interface ifi.
// It uses the system assigned multicast interface when ifi is nil,
// although this is not recommended because the assignment depends on
// platforms and sometimes it might require routing configuration.
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP16(group)
if grp == nil {
return errMissingAddress
}
return joinIPv6Group(fd, ifi, grp)
}
// LeaveGroup leaves the group address group on the interface ifi.
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP16(group)
if grp == nil {
return errMissingAddress
}
return leaveIPv6Group(fd, ifi, grp)
}
// Checksum reports whether the kernel will compute, store or verify a
// checksum for both incoming and outgoing packets. If on is true, it
// returns an offset in bytes into the data of where the checksum
// field is located.
func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
if !c.ok() {
return false, 0, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return false, 0, err
}
return ipv6Checksum(fd)
}
// SetChecksum enables the kernel checksum processing. If on is ture,
// the offset should be an offset in bytes into the data of where the
// checksum field is located.
func (c *dgramOpt) SetChecksum(on bool, offset int) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setIPv6Checksum(fd, on, offset)
}
// ICMPFilter returns an ICMP filter.
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
if !c.ok() {
return nil, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return nil, err
}
return ipv6ICMPFilter(fd)
}
// SetICMPFilter deploys the ICMP filter.
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setIPv6ICMPFilter(fd, f)
}

View File

@ -1,195 +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 ignore
// This program generates internet protocol constants by reading IANA
// protocol registries.
//
// Usage:
// go run gentest.go > iana_test.go
package main
import (
"bytes"
"encoding/xml"
"fmt"
"go/format"
"io"
"net/http"
"os"
"strconv"
"strings"
)
var registries = []struct {
url string
parse func(io.Writer, io.Reader) error
}{
{
"http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
parseDSCPRegistry,
},
{
"http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
parseTOSTCByte,
},
}
func main() {
var bb bytes.Buffer
fmt.Fprintf(&bb, "// go run gentest.go\n")
fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
fmt.Fprintf(&bb, "package ipv6_test\n\n")
for _, r := range registries {
resp, err := http.Get(r.url)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
os.Exit(1)
}
if err := r.parse(&bb, resp.Body); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Fprintf(&bb, "\n")
}
b, err := format.Source(bb.Bytes())
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
os.Stdout.Write(b)
}
func parseDSCPRegistry(w io.Writer, r io.Reader) error {
dec := xml.NewDecoder(r)
var dr dscpRegistry
if err := dec.Decode(&dr); err != nil {
return err
}
drs := dr.escape()
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
fmt.Fprintf(w, "const (\n")
for _, dr := range drs {
fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
fmt.Fprintf(w, "// %s\n", dr.OrigName)
}
fmt.Fprintf(w, ")\n")
return nil
}
type dscpRegistry struct {
XMLName xml.Name `xml:"registry"`
Title string `xml:"title"`
Updated string `xml:"updated"`
Note string `xml:"note"`
RegTitle string `xml:"registry>title"`
PoolRecords []struct {
Name string `xml:"name"`
Space string `xml:"space"`
} `xml:"registry>record"`
Records []struct {
Name string `xml:"name"`
Space string `xml:"space"`
} `xml:"registry>registry>record"`
}
type canonDSCPRecord struct {
OrigName string
Name string
Value int
}
func (drr *dscpRegistry) escape() []canonDSCPRecord {
drs := make([]canonDSCPRecord, len(drr.Records))
sr := strings.NewReplacer(
"+", "",
"-", "",
"/", "",
".", "",
" ", "",
)
for i, dr := range drr.Records {
s := strings.TrimSpace(dr.Name)
drs[i].OrigName = s
drs[i].Name = sr.Replace(s)
n, err := strconv.ParseUint(dr.Space, 2, 8)
if err != nil {
continue
}
drs[i].Value = int(n) << 2
}
return drs
}
func parseTOSTCByte(w io.Writer, r io.Reader) error {
dec := xml.NewDecoder(r)
var ttb tosTCByte
if err := dec.Decode(&ttb); err != nil {
return err
}
trs := ttb.escape()
fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
fmt.Fprintf(w, "const (\n")
for _, tr := range trs {
fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
}
fmt.Fprintf(w, ")\n")
return nil
}
type tosTCByte struct {
XMLName xml.Name `xml:"registry"`
Title string `xml:"title"`
Updated string `xml:"updated"`
Note string `xml:"note"`
RegTitle string `xml:"registry>title"`
Records []struct {
Binary string `xml:"binary"`
Keyword string `xml:"keyword"`
} `xml:"registry>record"`
}
type canonTOSTCByteRecord struct {
OrigKeyword string
Keyword string
Value int
}
func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
trs := make([]canonTOSTCByteRecord, len(ttb.Records))
sr := strings.NewReplacer(
"Capable", "",
"(", "",
")", "",
"+", "",
"-", "",
"/", "",
".", "",
" ", "",
)
for i, tr := range ttb.Records {
s := strings.TrimSpace(tr.Keyword)
trs[i].OrigKeyword = s
ss := strings.Split(s, " ")
if len(ss) > 1 {
trs[i].Keyword = strings.Join(ss[1:], " ")
} else {
trs[i].Keyword = ss[0]
}
trs[i].Keyword = sr.Replace(trs[i].Keyword)
n, err := strconv.ParseUint(tr.Binary, 2, 8)
if err != nil {
continue
}
trs[i].Value = int(n)
}
return trs
}

View File

@ -1,224 +0,0 @@
// go run gen.go
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package ipv6
// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2013-07-03
const (
ICMPTypeDestinationUnreachable ICMPType = 1 // Destination Unreachable
ICMPTypePacketTooBig ICMPType = 2 // Packet Too Big
ICMPTypeTimeExceeded ICMPType = 3 // Time Exceeded
ICMPTypeParameterProblem ICMPType = 4 // Parameter Problem
ICMPTypeEchoRequest ICMPType = 128 // Echo Request
ICMPTypeEchoReply ICMPType = 129 // Echo Reply
ICMPTypeMulticastListenerQuery ICMPType = 130 // Multicast Listener Query
ICMPTypeMulticastListenerReport ICMPType = 131 // Multicast Listener Report
ICMPTypeMulticastListenerDone ICMPType = 132 // Multicast Listener Done
ICMPTypeRouterSolicitation ICMPType = 133 // Router Solicitation
ICMPTypeRouterAdvertisement ICMPType = 134 // Router Advertisement
ICMPTypeNeighborSolicitation ICMPType = 135 // Neighbor Solicitation
ICMPTypeNeighborAdvertisement ICMPType = 136 // Neighbor Advertisement
ICMPTypeRedirect ICMPType = 137 // Redirect Message
ICMPTypeRouterRenumbering ICMPType = 138 // Router Renumbering
ICMPTypeNodeInformationQuery ICMPType = 139 // ICMP Node Information Query
ICMPTypeNodeInformationResponse ICMPType = 140 // ICMP Node Information Response
ICMPTypeInverseNeighborDiscoverySolicitation ICMPType = 141 // Inverse Neighbor Discovery Solicitation Message
ICMPTypeInverseNeighborDiscoveryAdvertisement ICMPType = 142 // Inverse Neighbor Discovery Advertisement Message
ICMPTypeVersion2MulticastListenerReport ICMPType = 143 // Version 2 Multicast Listener Report
ICMPTypeHomeAgentAddressDiscoveryRequest ICMPType = 144 // Home Agent Address Discovery Request Message
ICMPTypeHomeAgentAddressDiscoveryReply ICMPType = 145 // Home Agent Address Discovery Reply Message
ICMPTypeMobilePrefixSolicitation ICMPType = 146 // Mobile Prefix Solicitation
ICMPTypeMobilePrefixAdvertisement ICMPType = 147 // Mobile Prefix Advertisement
ICMPTypeCertificationPathSolicitation ICMPType = 148 // Certification Path Solicitation Message
ICMPTypeCertificationPathAdvertisement ICMPType = 149 // Certification Path Advertisement Message
ICMPTypeMulticastRouterAdvertisement ICMPType = 151 // Multicast Router Advertisement
ICMPTypeMulticastRouterSolicitation ICMPType = 152 // Multicast Router Solicitation
ICMPTypeMulticastRouterTermination ICMPType = 153 // Multicast Router Termination
ICMPTypeFMIPv6 ICMPType = 154 // FMIPv6 Messages
ICMPTypeRPLControl ICMPType = 155 // RPL Control Message
ICMPTypeILNPv6LocatorUpdate ICMPType = 156 // ILNPv6 Locator Update Message
ICMPTypeDuplicateAddressRequest ICMPType = 157 // Duplicate Address Request
ICMPTypeDuplicateAddressConfirmation ICMPType = 158 // Duplicate Address Confirmation
)
// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2013-07-03
var icmpTypes = map[ICMPType]string{
1: "destination unreachable",
2: "packet too big",
3: "time exceeded",
4: "parameter problem",
128: "echo request",
129: "echo reply",
130: "multicast listener query",
131: "multicast listener report",
132: "multicast listener done",
133: "router solicitation",
134: "router advertisement",
135: "neighbor solicitation",
136: "neighbor advertisement",
137: "redirect message",
138: "router renumbering",
139: "icmp node information query",
140: "icmp node information response",
141: "inverse neighbor discovery solicitation message",
142: "inverse neighbor discovery advertisement message",
143: "version 2 multicast listener report",
144: "home agent address discovery request message",
145: "home agent address discovery reply message",
146: "mobile prefix solicitation",
147: "mobile prefix advertisement",
148: "certification path solicitation message",
149: "certification path advertisement message",
151: "multicast router advertisement",
152: "multicast router solicitation",
153: "multicast router termination",
154: "fmipv6 messages",
155: "rpl control message",
156: "ilnpv6 locator update message",
157: "duplicate address request",
158: "duplicate address confirmation",
}
// Protocol Numbers, Updated: 2013-02-17
const (
ianaProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
ianaProtocolICMP = 1 // Internet Control Message
ianaProtocolIGMP = 2 // Internet Group Management
ianaProtocolGGP = 3 // Gateway-to-Gateway
ianaProtocolIPv4 = 4 // IPv4 encapsulation
ianaProtocolST = 5 // Stream
ianaProtocolTCP = 6 // Transmission Control
ianaProtocolCBT = 7 // CBT
ianaProtocolEGP = 8 // Exterior Gateway Protocol
ianaProtocolIGP = 9 // any private interior gateway (used by Cisco for their IGRP)
ianaProtocolBBNRCCMON = 10 // BBN RCC Monitoring
ianaProtocolNVPII = 11 // Network Voice Protocol
ianaProtocolPUP = 12 // PUP
ianaProtocolARGUS = 13 // ARGUS
ianaProtocolEMCON = 14 // EMCON
ianaProtocolXNET = 15 // Cross Net Debugger
ianaProtocolCHAOS = 16 // Chaos
ianaProtocolUDP = 17 // User Datagram
ianaProtocolMUX = 18 // Multiplexing
ianaProtocolDCNMEAS = 19 // DCN Measurement Subsystems
ianaProtocolHMP = 20 // Host Monitoring
ianaProtocolPRM = 21 // Packet Radio Measurement
ianaProtocolXNSIDP = 22 // XEROX NS IDP
ianaProtocolTRUNK1 = 23 // Trunk-1
ianaProtocolTRUNK2 = 24 // Trunk-2
ianaProtocolLEAF1 = 25 // Leaf-1
ianaProtocolLEAF2 = 26 // Leaf-2
ianaProtocolRDP = 27 // Reliable Data Protocol
ianaProtocolIRTP = 28 // Internet Reliable Transaction
ianaProtocolISOTP4 = 29 // ISO Transport Protocol Class 4
ianaProtocolNETBLT = 30 // Bulk Data Transfer Protocol
ianaProtocolMFENSP = 31 // MFE Network Services Protocol
ianaProtocolMERITINP = 32 // MERIT Internodal Protocol
ianaProtocolDCCP = 33 // Datagram Congestion Control Protocol
ianaProtocol3PC = 34 // Third Party Connect Protocol
ianaProtocolIDPR = 35 // Inter-Domain Policy Routing Protocol
ianaProtocolXTP = 36 // XTP
ianaProtocolDDP = 37 // Datagram Delivery Protocol
ianaProtocolIDPRCMTP = 38 // IDPR Control Message Transport Proto
ianaProtocolTPPP = 39 // TP++ Transport Protocol
ianaProtocolIL = 40 // IL Transport Protocol
ianaProtocolIPv6 = 41 // IPv6 encapsulation
ianaProtocolSDRP = 42 // Source Demand Routing Protocol
ianaProtocolIPv6Route = 43 // Routing Header for IPv6
ianaProtocolIPv6Frag = 44 // Fragment Header for IPv6
ianaProtocolIDRP = 45 // Inter-Domain Routing Protocol
ianaProtocolRSVP = 46 // Reservation Protocol
ianaProtocolGRE = 47 // Generic Routing Encapsulation
ianaProtocolDSR = 48 // Dynamic Source Routing Protocol
ianaProtocolBNA = 49 // BNA
ianaProtocolESP = 50 // Encap Security Payload
ianaProtocolAH = 51 // Authentication Header
ianaProtocolINLSP = 52 // Integrated Net Layer Security TUBA
ianaProtocolSWIPE = 53 // IP with Encryption
ianaProtocolNARP = 54 // NBMA Address Resolution Protocol
ianaProtocolMOBILE = 55 // IP Mobility
ianaProtocolTLSP = 56 // Transport Layer Security Protocol using Kryptonet key management
ianaProtocolSKIP = 57 // SKIP
ianaProtocolIPv6ICMP = 58 // ICMP for IPv6
ianaProtocolIPv6NoNxt = 59 // No Next Header for IPv6
ianaProtocolIPv6Opts = 60 // Destination Options for IPv6
ianaProtocolCFTP = 62 // CFTP
ianaProtocolSATEXPAK = 64 // SATNET and Backroom EXPAK
ianaProtocolKRYPTOLAN = 65 // Kryptolan
ianaProtocolRVD = 66 // MIT Remote Virtual Disk Protocol
ianaProtocolIPPC = 67 // Internet Pluribus Packet Core
ianaProtocolSATMON = 69 // SATNET Monitoring
ianaProtocolVISA = 70 // VISA Protocol
ianaProtocolIPCV = 71 // Internet Packet Core Utility
ianaProtocolCPNX = 72 // Computer Protocol Network Executive
ianaProtocolCPHB = 73 // Computer Protocol Heart Beat
ianaProtocolWSN = 74 // Wang Span Network
ianaProtocolPVP = 75 // Packet Video Protocol
ianaProtocolBRSATMON = 76 // Backroom SATNET Monitoring
ianaProtocolSUNND = 77 // SUN ND PROTOCOL-Temporary
ianaProtocolWBMON = 78 // WIDEBAND Monitoring
ianaProtocolWBEXPAK = 79 // WIDEBAND EXPAK
ianaProtocolISOIP = 80 // ISO Internet Protocol
ianaProtocolVMTP = 81 // VMTP
ianaProtocolSECUREVMTP = 82 // SECURE-VMTP
ianaProtocolVINES = 83 // VINES
ianaProtocolTTP = 84 // TTP
ianaProtocolIPTM = 84 // Protocol Internet Protocol Traffic Manager
ianaProtocolNSFNETIGP = 85 // NSFNET-IGP
ianaProtocolDGP = 86 // Dissimilar Gateway Protocol
ianaProtocolTCF = 87 // TCF
ianaProtocolEIGRP = 88 // EIGRP
ianaProtocolOSPFIGP = 89 // OSPFIGP
ianaProtocolSpriteRPC = 90 // Sprite RPC Protocol
ianaProtocolLARP = 91 // Locus Address Resolution Protocol
ianaProtocolMTP = 92 // Multicast Transport Protocol
ianaProtocolAX25 = 93 // AX.25 Frames
ianaProtocolIPIP = 94 // IP-within-IP Encapsulation Protocol
ianaProtocolMICP = 95 // Mobile Internetworking Control Pro.
ianaProtocolSCCSP = 96 // Semaphore Communications Sec. Pro.
ianaProtocolETHERIP = 97 // Ethernet-within-IP Encapsulation
ianaProtocolENCAP = 98 // Encapsulation Header
ianaProtocolGMTP = 100 // GMTP
ianaProtocolIFMP = 101 // Ipsilon Flow Management Protocol
ianaProtocolPNNI = 102 // PNNI over IP
ianaProtocolPIM = 103 // Protocol Independent Multicast
ianaProtocolARIS = 104 // ARIS
ianaProtocolSCPS = 105 // SCPS
ianaProtocolQNX = 106 // QNX
ianaProtocolAN = 107 // Active Networks
ianaProtocolIPComp = 108 // IP Payload Compression Protocol
ianaProtocolSNP = 109 // Sitara Networks Protocol
ianaProtocolCompaqPeer = 110 // Compaq Peer Protocol
ianaProtocolIPXinIP = 111 // IPX in IP
ianaProtocolVRRP = 112 // Virtual Router Redundancy Protocol
ianaProtocolPGM = 113 // PGM Reliable Transport Protocol
ianaProtocolL2TP = 115 // Layer Two Tunneling Protocol
ianaProtocolDDX = 116 // D-II Data Exchange (DDX)
ianaProtocolIATP = 117 // Interactive Agent Transfer Protocol
ianaProtocolSTP = 118 // Schedule Transfer Protocol
ianaProtocolSRP = 119 // SpectraLink Radio Protocol
ianaProtocolUTI = 120 // UTI
ianaProtocolSMP = 121 // Simple Message Protocol
ianaProtocolSM = 122 // SM
ianaProtocolPTP = 123 // Performance Transparency Protocol
ianaProtocolISIS = 124 // ISIS over IPv4
ianaProtocolFIRE = 125 // FIRE
ianaProtocolCRTP = 126 // Combat Radio Transport Protocol
ianaProtocolCRUDP = 127 // Combat Radio User Datagram
ianaProtocolSSCOPMCE = 128 // SSCOPMCE
ianaProtocolIPLT = 129 // IPLT
ianaProtocolSPS = 130 // Secure Packet Shield
ianaProtocolPIPE = 131 // Private IP Encapsulation within IP
ianaProtocolSCTP = 132 // Stream Control Transmission Protocol
ianaProtocolFC = 133 // Fibre Channel
ianaProtocolRSVPE2EIGNORE = 134 // RSVP-E2E-IGNORE
ianaProtocolMobilityHeader = 135 // Mobility Header
ianaProtocolUDPLite = 136 // UDPLite
ianaProtocolMPLSinIP = 137 // MPLS-in-IP
ianaProtocolMANET = 138 // MANET Protocols
ianaProtocolHIP = 139 // Host Identity Protocol
ianaProtocolShim6 = 140 // Shim6 Protocol
ianaProtocolWESP = 141 // Wrapped Encapsulating Security Payload
ianaProtocolROHC = 142 // Robust Header Compression
ianaProtocolReserved = 255 // Reserved
)

View File

@ -1,38 +0,0 @@
// go run gentest.go
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package ipv6_test
// Differentiated Services Field Codepoints (DSCP), Updated: 2013-06-25
const (
DiffServCS0 = 0x0 // CS0
DiffServCS1 = 0x20 // CS1
DiffServCS2 = 0x40 // CS2
DiffServCS3 = 0x60 // CS3
DiffServCS4 = 0x80 // CS4
DiffServCS5 = 0xa0 // CS5
DiffServCS6 = 0xc0 // CS6
DiffServCS7 = 0xe0 // CS7
DiffServAF11 = 0x28 // AF11
DiffServAF12 = 0x30 // AF12
DiffServAF13 = 0x38 // AF13
DiffServAF21 = 0x48 // AF21
DiffServAF22 = 0x50 // AF22
DiffServAF23 = 0x58 // AF23
DiffServAF31 = 0x68 // AF31
DiffServAF32 = 0x70 // AF32
DiffServAF33 = 0x78 // AF33
DiffServAF41 = 0x88 // AF41
DiffServAF42 = 0x90 // AF42
DiffServAF43 = 0x98 // AF43
DiffServEFPHB = 0xb8 // EF PHB
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
)
// IPv4 TOS Byte and IPv6 Traffic Class Octet, Updated: 2001-09-06
const (
NotECNTransport = 0x0 // Not-ECT (Not ECN-Capable Transport)
ECNTransport1 = 0x1 // ECT(1) (ECN-Capable Transport(1))
ECNTransport0 = 0x2 // ECT(0) (ECN-Capable Transport(0))
CongestionExperienced = 0x3 // CE (Congestion Experienced)
)

View File

@ -1,47 +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"
// An ICMPType represents a type of ICMP message.
type ICMPType int
func (typ ICMPType) String() string {
s, ok := icmpTypes[typ]
if !ok {
return "<nil>"
}
return s
}
// An ICMPFilter represents an ICMP message filter for incoming
// packets.
type ICMPFilter struct {
mu sync.RWMutex
sysICMPFilter
}
// Set sets the ICMP type and filter action to the filter.
func (f *ICMPFilter) Set(typ ICMPType, block bool) {
f.mu.Lock()
f.set(typ, block)
f.mu.Unlock()
}
// SetAll sets the filter action to the filter.
func (f *ICMPFilter) SetAll(block bool) {
f.mu.Lock()
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()
ok := f.willBlock(typ)
f.mu.RUnlock()
return ok
}

View File

@ -1,24 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build nacl plan9 solaris
package ipv6
type sysICMPFilter struct {
// TODO(mikio): Implement this
}
func (f *sysICMPFilter) set(typ ICMPType, block bool) {
// TODO(mikio): Implement this
}
func (f *sysICMPFilter) setAll(block bool) {
// TODO(mikio): Implement this
}
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
// TODO(mikio): Implement this
return false
}

View File

@ -1,130 +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_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
Code int // code
Checksum int // checksum
Body icmpMessageBody // body
}
// icmpMessageBody represents an ICMP message body.
type icmpMessageBody interface {
Len() int
Marshal() ([]byte, error)
}
// Marshal returns the binary enconding of the ICMP echo request or
// reply message m.
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 {
return nil, err
}
b = append(b, mb...)
}
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 {
s += uint32(b[i+1])<<8 | uint32(b[i])
}
if csumcv&1 == 0 {
s += uint32(b[csumcv])
}
s = s>>16 + s&0xffff
s = s + s>>16
// Place checksum back in header; using ^= avoids the
// assumption the checksum bytes are zero.
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.
func parseICMPMessage(b []byte) (*icmpMessage, error) {
msglen := len(b)
if msglen < 4 {
return nil, errors.New("message too short")
}
m := &icmpMessage{Type: ipv6.ICMPType(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
if msglen > 4 {
var err error
switch m.Type {
case ipv6.ICMPTypeEchoRequest, ipv6.ICMPTypeEchoReply:
m.Body, err = parseICMPEcho(b[4:])
if err != nil {
return nil, err
}
}
}
return m, nil
}
// imcpEcho represenets an ICMP echo request or reply message body.
type icmpEcho struct {
ID int // identifier
Seq int // sequence number
Data []byte // data
}
func (p *icmpEcho) Len() int {
if p == nil {
return 0
}
return 4 + len(p.Data)
}
// Marshal returns the binary enconding of the ICMP echo request or
// reply message body p.
func (p *icmpEcho) Marshal() ([]byte, error) {
b := make([]byte, 4+len(p.Data))
b[0], b[1] = byte(p.ID>>8), byte(p.ID)
b[2], b[3] = byte(p.Seq>>8), byte(p.Seq)
copy(b[4:], p.Data)
return b, nil
}
// parseICMPEcho parses b as an ICMP echo request or reply message
// body.
func parseICMPEcho(b []byte) (*icmpEcho, error) {
bodylen := len(b)
p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
if bodylen > 4 {
p.Data = make([]byte, bodylen-4)
copy(p.Data, b[4:])
}
return p, nil
}

View File

@ -1,88 +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_test
import (
"net"
"testing"
)
func isLinkLocalUnicast(ip net.IP) bool {
return ip.To4() == nil && ip.To16() != nil && ip.IsLinkLocalUnicast()
}
func loopbackInterface() *net.Interface {
ift, err := net.Interfaces()
if err != nil {
return nil
}
for _, ifi := range ift {
if ifi.Flags&net.FlagLoopback == 0 || ifi.Flags&net.FlagUp == 0 {
continue
}
ifat, err := ifi.Addrs()
if err != nil {
continue
}
for _, ifa := range ifat {
switch ifa := ifa.(type) {
case *net.IPAddr:
if isLinkLocalUnicast(ifa.IP) {
return &ifi
}
case *net.IPNet:
if isLinkLocalUnicast(ifa.IP) {
return &ifi
}
}
}
}
return nil
}
func isMulticastAvailable(ifi *net.Interface) (net.IP, bool) {
if ifi == nil || ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 {
return nil, false
}
ifat, err := ifi.Addrs()
if err != nil {
return nil, false
}
for _, ifa := range ifat {
switch ifa := ifa.(type) {
case *net.IPAddr:
if isLinkLocalUnicast(ifa.IP) {
return ifa.IP, true
}
case *net.IPNet:
if isLinkLocalUnicast(ifa.IP) {
return ifa.IP, true
}
}
}
return nil, false
}
func connector(t *testing.T, network, addr string, done chan<- bool) {
defer func() { done <- true }()
c, err := net.Dial(network, addr)
if err != nil {
t.Errorf("net.Dial failed: %v", err)
return
}
c.Close()
}
func acceptor(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
}
c.Close()
}

View File

@ -1,205 +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_test
import (
"bytes"
"code.google.com/p/go.net/ipv6"
"net"
"os"
"runtime"
"testing"
"time"
)
func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
switch runtime.GOOS {
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", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
t.Skip("ipv6 is not supported")
}
ifi := loopbackInterface()
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
c, err := net.ListenPacket("udp6", "[ff02::114]:0") // see RFC 4727
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
_, port, err := net.SplitHostPort(c.LocalAddr().String())
if err != nil {
t.Fatalf("net.SplitHostPort failed: %v", err)
}
dst, err := net.ResolveUDPAddr("udp6", "[ff02::114]:"+port) // see RFC 4727
if err != nil {
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
}
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.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)
}
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatalf("ipv6.PacketConn.SetDeadline failed: %v", err)
}
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)
}
}
}
func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
switch runtime.GOOS {
case "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")
}
ifi := loopbackInterface()
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
c, err := net.ListenPacket("ip6:ipv6-icmp", "::")
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
dst, err := net.ResolveIPAddr("ip6", "ff02::114") // see RFC 4727
if err != nil {
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.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
var f ipv6.ICMPFilter
f.SetAll(true)
f.Set(ipv6.ICMPTypeEchoReply, false)
if err := p.SetICMPFilter(&f); err != nil {
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(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)
}
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatalf("ipv6.PacketConn.SetDeadline failed: %v", err)
}
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(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

@ -1,76 +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_test
import (
"code.google.com/p/go.net/ipv6"
"net"
"os"
"runtime"
"testing"
)
var packetConnMulticastSocketOptionTests = []struct {
net, proto, addr string
gaddr net.Addr
}{
{"udp6", "", "[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}}, // see RFC 4727
{"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff02::114")}}, // see RFC 4727
}
func TestPacketConnMulticastSocketOptions(t *testing.T) {
switch runtime.GOOS {
case "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
}
if !supportsIPv6 {
t.Skip("ipv6 is not supported")
}
ifi := loopbackInterface()
if ifi == nil {
t.Skipf("not available on %q", runtime.GOOS)
}
for _, tt := range packetConnMulticastSocketOptionTests {
if tt.net == "ip6" && os.Getuid() != 0 {
t.Skip("must be root")
}
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
p := ipv6.NewPacketConn(c)
hoplim := 255
if err := p.SetMulticastHopLimit(hoplim); err != nil {
t.Fatalf("ipv6.PacketConn.SetMulticastHopLimit failed: %v", err)
}
if v, err := p.MulticastHopLimit(); err != nil {
t.Fatalf("ipv6.PacketConn.MulticastHopLimit failed: %v", err)
} else if v != hoplim {
t.Fatalf("got unexpected multicast hop limit %v; expected %v", v, hoplim)
}
for _, toggle := range []bool{true, false} {
if err := p.SetMulticastLoopback(toggle); err != nil {
t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err)
}
if v, err := p.MulticastLoopback(); err != nil {
t.Fatalf("ipv6.PacketConn.MulticastLoopback failed: %v", err)
} else if v != toggle {
t.Fatalf("got unexpected multicast loopback %v; expected %v", v, toggle)
}
}
if err := p.JoinGroup(ifi, tt.gaddr); err != nil {
t.Fatalf("ipv6.PacketConn.JoinGroup(%v, %v) failed: %v", ifi, tt.gaddr, err)
}
if err := p.LeaveGroup(ifi, tt.gaddr); err != nil {
t.Fatalf("ipv6.PacketConn.LeaveGroup(%v, %v) failed: %v", ifi, tt.gaddr, err)
}
}
}

View File

@ -1,70 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin
package ipv6
import (
"os"
"syscall"
"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) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockopt2292HopLimit)
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, sysSockopt2292HopLimit, boolint(v)))
}
func ipv6ReceivePacketInfo(fd int) (bool, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockopt2292PacketInfo)
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, sysSockopt2292PacketInfo, boolint(v)))
}
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, 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, unsafe.Pointer(&f.sysICMPFilter), sysSizeofICMPFilter))
}

View File

@ -1,19 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd netbsd openbsd
package ipv6
import (
"os"
"syscall"
)
func setIPv6Checksum(fd int, on bool, offset int) error {
if !on {
offset = -1
}
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, sysSockoptChecksum, offset))
}

View File

@ -1,17 +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 setIPv6Checksum(fd int, on bool, offset int) error {
if !on {
offset = -1
}
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolReserved, sysSockoptChecksum, offset))
}

View File

@ -1,115 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd
package ipv6
import (
"net"
"os"
"syscall"
"unsafe"
)
func ipv6TrafficClass(fd int) (int, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptTrafficClass)
if err != nil {
return 0, os.NewSyscallError("getsockopt", err)
}
return v, nil
}
func setIPv6TrafficClass(fd, v int) error {
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, sysSockoptTrafficClass, v))
}
func ipv6HopLimit(fd int) (int, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit)
if err != nil {
return 0, os.NewSyscallError("getsockopt", err)
}
return v, nil
}
func setIPv6HopLimit(fd, v int) error {
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, v))
}
func ipv6Checksum(fd int) (bool, int, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptChecksum)
if err != nil {
return false, 0, os.NewSyscallError("getsockopt", err)
}
on := true
if v == -1 {
on = false
}
return on, v, nil
}
func ipv6MulticastHopLimit(fd int) (int, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit)
if err != nil {
return 0, os.NewSyscallError("getsockopt", err)
}
return v, nil
}
func setIPv6MulticastHopLimit(fd, v int) error {
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, v))
}
func ipv6MulticastInterface(fd int) (*net.Interface, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface)
if err != nil {
return nil, os.NewSyscallError("getsockopt", err)
}
if v == 0 {
return nil, nil
}
ifi, err := net.InterfaceByIndex(v)
if err != nil {
return nil, err
}
return ifi, nil
}
func setIPv6MulticastInterface(fd int, ifi *net.Interface) error {
var v int
if ifi != nil {
v = ifi.Index
}
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface, v))
}
func ipv6MulticastLoopback(fd int) (bool, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback)
if 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, sysSockoptMulticastLoopback, boolint(v)))
}
func joinIPv6Group(fd int, ifi *net.Interface, grp net.IP) error {
mreq := sysMulticastReq{}
copy(mreq.IP[:], grp)
if ifi != nil {
mreq.IfIndex = uint32(ifi.Index)
}
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptJoinGroup, unsafe.Pointer(&mreq), sysSizeofMulticastReq))
}
func leaveIPv6Group(fd int, ifi *net.Interface, grp net.IP) error {
mreq := sysMulticastReq{}
copy(mreq.IP[:], grp)
if ifi != nil {
mreq.IfIndex = uint32(ifi.Index)
}
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptLeaveGroup, unsafe.Pointer(&mreq), sysSizeofMulticastReq))
}

View File

@ -1,116 +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"
)
func ipv6TrafficClass(fd syscall.Handle) (int, error) {
// TODO(mikio): Implement this
return 0, syscall.EWINDOWS
}
func setIPv6TrafficClass(fd syscall.Handle, v int) error {
// TODO(mikio): Implement this
return syscall.EWINDOWS
}
func ipv6HopLimit(fd syscall.Handle) (int, error) {
var v int32
l := int32(4)
if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
return 0, os.NewSyscallError("getsockopt", err)
}
return int(v), nil
}
func setIPv6HopLimit(fd syscall.Handle, v int) error {
vv := int32(v)
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, (*byte)(unsafe.Pointer(&vv)), 4))
}
func ipv6Checksum(fd syscall.Handle) (bool, int, error) {
// TODO(mikio): Implement this
return false, 0, syscall.EWINDOWS
}
func ipv6MulticastHopLimit(fd syscall.Handle) (int, error) {
var v int32
l := int32(4)
if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
return 0, os.NewSyscallError("getsockopt", err)
}
return int(v), nil
}
func setIPv6MulticastHopLimit(fd syscall.Handle, v int) error {
vv := int32(v)
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, sysSockoptMulticastInterface, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
return nil, os.NewSyscallError("getsockopt", err)
}
if v == 0 {
return nil, nil
}
ifi, err := net.InterfaceByIndex(int(v))
if err != nil {
return nil, err
}
return ifi, nil
}
func setIPv6MulticastInterface(fd syscall.Handle, ifi *net.Interface) error {
var v int32
if ifi != nil {
v = int32(ifi.Index)
}
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, sysSockoptMulticastLoopback, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
return false, os.NewSyscallError("getsockopt", err)
}
return v == 1, nil
}
func setIPv6MulticastLoopback(fd syscall.Handle, v bool) error {
vv := int32(boolint(v))
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 := sysMulticastReq{}
copy(mreq.IP[:], grp)
if ifi != nil {
mreq.IfIndex = uint32(ifi.Index)
}
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 := sysMulticastReq{}
copy(mreq.IP[:], grp)
if ifi != nil {
mreq.IfIndex = uint32(ifi.Index)
}
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 {
// TODO(mikio): Implement this
return syscall.EWINDOWS
}

View File

@ -1,83 +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 dragonfly freebsd linux netbsd openbsd
package ipv6
import (
"os"
"syscall"
"unsafe"
)
func ipv6ReceiveTrafficClass(fd int) (bool, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptReceiveTrafficClass)
if 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, sysSockoptReceiveTrafficClass, boolint(v)))
}
func ipv6ReceiveHopLimit(fd int) (bool, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptReceiveHopLimit)
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, sysSockoptReceiveHopLimit, boolint(v)))
}
func ipv6ReceivePacketInfo(fd int) (bool, error) {
v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptReceivePacketInfo)
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, sysSockoptReceivePacketInfo, boolint(v)))
}
func ipv6PathMTU(fd int) (int, error) {
var v sysMTUInfo
l := sysSockoptLen(sysSizeofMTUInfo)
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptPathMTU, unsafe.Pointer(&v), &l); 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, sysSockoptReceivePathMTU)
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, sysSockoptReceivePathMTU, boolint(v)))
}
func ipv6ICMPFilter(fd int) (*ICMPFilter, error) {
var v ICMPFilter
l := sysSockoptLen(sysSizeofICMPFilter)
if err := getsockopt(fd, ianaProtocolIPv6ICMP, sysSockoptICMPFilter, 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, unsafe.Pointer(&f.sysICMPFilter), sysSizeofICMPFilter))
}

View File

@ -1,62 +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 "syscall"
func ipv6ReceiveTrafficClass(fd syscall.Handle) (bool, error) {
// TODO(mikio): Implement this
return false, syscall.EWINDOWS
}
func setIPv6ReceiveTrafficClass(fd syscall.Handle, v bool) error {
// TODO(mikio): Implement this
return syscall.EWINDOWS
}
func ipv6ReceiveHopLimit(fd syscall.Handle) (bool, error) {
// TODO(mikio): Implement this
return false, syscall.EWINDOWS
}
func setIPv6ReceiveHopLimit(fd syscall.Handle, v bool) error {
// TODO(mikio): Implement this
return syscall.EWINDOWS
}
func ipv6ReceivePacketInfo(fd syscall.Handle) (bool, error) {
// TODO(mikio): Implement this
return false, syscall.EWINDOWS
}
func setIPv6ReceivePacketInfo(fd syscall.Handle, v bool) error {
// TODO(mikio): Implement this
return syscall.EWINDOWS
}
func ipv6PathMTU(fd syscall.Handle) (int, error) {
// TODO(mikio): Implement this
return 0, syscall.EWINDOWS
}
func ipv6ReceivePathMTU(fd syscall.Handle) (bool, error) {
// TODO(mikio): Implement this
return false, syscall.EWINDOWS
}
func setIPv6ReceivePathMTU(fd syscall.Handle, v bool) error {
// TODO(mikio): Implement this
return syscall.EWINDOWS
}
func ipv6ICMPFilter(fd syscall.Handle) (*ICMPFilter, error) {
// TODO(mikio): Implement this
return nil, syscall.EWINDOWS
}
func setIPv6ICMPFilter(fd syscall.Handle, f *ICMPFilter) error {
// TODO(mikio): Implement this
return syscall.EWINDOWS
}

View File

@ -1,23 +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
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

@ -1,37 +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 dragonfly freebsd netbsd openbsd
package ipv6
import (
"net"
"syscall"
)
// RFC 3542 options
const (
// See /usr/include/netinet6/in6.h.
sysSockoptReceiveTrafficClass = syscall.IPV6_RECVTCLASS
sysSockoptTrafficClass = syscall.IPV6_TCLASS
sysSockoptReceiveHopLimit = syscall.IPV6_RECVHOPLIMIT
sysSockoptHopLimit = syscall.IPV6_HOPLIMIT
sysSockoptReceivePacketInfo = syscall.IPV6_RECVPKTINFO
sysSockoptPacketInfo = syscall.IPV6_PKTINFO
sysSockoptReceivePathMTU = syscall.IPV6_RECVPATHMTU
sysSockoptPathMTU = syscall.IPV6_PATHMTU
sysSockoptNextHop = syscall.IPV6_NEXTHOP
sysSockoptChecksum = syscall.IPV6_CHECKSUM
// See /usr/include/netinet6/in6.h.
sysSockoptICMPFilter = 0x12 // syscall.ICMP6_FILTER
)
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

@ -1,43 +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"
"syscall"
)
// RFC 2292 options
const (
// See /usr/include/netinet6/in6.h.
sysSockopt2292HopLimit = syscall.IPV6_2292HOPLIMIT
sysSockopt2292PacketInfo = syscall.IPV6_2292PKTINFO
sysSockopt2292NextHop = syscall.IPV6_2292NEXTHOP
)
// RFC 3542 options
const (
// See /usr/include/netinet6/in6.h.
sysSockoptReceiveTrafficClass = 0x23 // IPV6_RECVTCLASS
sysSockoptTrafficClass = 0x24 // IPV6_TCLASS
sysSockoptReceiveHopLimit = 0x25 // IPV6_RECVHOPLIMIT
sysSockoptHopLimit = 0x2f // IPV6_HOPLIMIT
sysSockoptReceivePacketInfo = 0x3d // IPV6_RECVPKTINFO
sysSockoptPacketInfo = 0x2e // IPV6_PKTINFO
sysSockoptReceivePathMTU = 0x2b // IPV6_RECVPATHMTU
sysSockoptPathMTU = 0x2c // IPV6_PATHMTU
sysSockoptNextHop = 0x30 // IPV6_NEXTHOP
sysSockoptChecksum = 0x1a // IPV6_CHECKSUM
// See /usr/include/netinet6/in6.h.
sysSockoptICMPFilter = 0x12 // ICMP6_FILTER
)
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

@ -1,34 +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"
"syscall"
)
// RFC 3542 options
const (
// See /usr/include/linux/ipv6.h,in6.h.
sysSockoptReceiveTrafficClass = syscall.IPV6_RECVTCLASS
sysSockoptTrafficClass = syscall.IPV6_TCLASS
sysSockoptReceiveHopLimit = syscall.IPV6_RECVHOPLIMIT
sysSockoptHopLimit = syscall.IPV6_HOPLIMIT
sysSockoptReceivePacketInfo = syscall.IPV6_RECVPKTINFO
sysSockoptPacketInfo = syscall.IPV6_PKTINFO
sysSockoptReceivePathMTU = 0x3c // IPV6_RECVPATHMTU
sysSockoptPathMTU = 0x3d // IPV6_PATHMTU
sysSockoptNextHop = syscall.IPV6_NEXTHOP
sysSockoptChecksum = syscall.IPV6_CHECKSUM
// See /usr/include/linux/icmpv6.h.
sysSockoptICMPFilter = 0x1 // syscall.ICMPV6_FILTER
)
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

@ -1,26 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd
package ipv6
import "syscall"
// RFC 3493 options
const (
sysSockoptUnicastHopLimit = syscall.IPV6_UNICAST_HOPS
sysSockoptMulticastHopLimit = syscall.IPV6_MULTICAST_HOPS
sysSockoptMulticastInterface = syscall.IPV6_MULTICAST_IF
sysSockoptMulticastLoopback = syscall.IPV6_MULTICAST_LOOP
sysSockoptJoinGroup = syscall.IPV6_JOIN_GROUP
sysSockoptLeaveGroup = syscall.IPV6_LEAVE_GROUP
)
const sysSizeofMTUInfo = 0x20
type sysMTUInfo struct {
Addr syscall.RawSockaddrInet6
MTU uint32
}

View File

@ -1,33 +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"
"syscall"
)
// RFC 3493 options
const (
// See ws2tcpip.h.
sysSockoptUnicastHopLimit = syscall.IPV6_UNICAST_HOPS
sysSockoptMulticastHopLimit = syscall.IPV6_MULTICAST_HOPS
sysSockoptMulticastInterface = syscall.IPV6_MULTICAST_IF
sysSockoptMulticastLoopback = syscall.IPV6_MULTICAST_LOOP
sysSockoptJoinGroup = syscall.IPV6_JOIN_GROUP
sysSockoptLeaveGroup = syscall.IPV6_LEAVE_GROUP
)
// RFC 3542 options
const (
// See ws2tcpip.h.
sysSockoptPacketInfo = 0x13 // IPV6_PKTINFO
)
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

@ -38,7 +38,7 @@ const (
CongestionExperienced = 0x3 // CE (Congestion Experienced)
)
// Protocol Numbers, Updated: 2014-08-12
// Protocol Numbers, Updated: 2015-01-06
const (
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
@ -94,7 +94,6 @@ const (
ProtocolESP = 50 // Encap Security Payload
ProtocolAH = 51 // Authentication Header
ProtocolINLSP = 52 // Integrated Net Layer Security TUBA
ProtocolSWIPE = 53 // IP with Encryption
ProtocolNARP = 54 // NBMA Address Resolution Protocol
ProtocolMOBILE = 55 // IP Mobility
ProtocolTLSP = 56 // Transport Layer Security Protocol using Kryptonet key management
@ -134,7 +133,6 @@ const (
ProtocolMTP = 92 // Multicast Transport Protocol
ProtocolAX25 = 93 // AX.25 Frames
ProtocolIPIP = 94 // IP-within-IP Encapsulation Protocol
ProtocolMICP = 95 // Mobile Internetworking Control Pro.
ProtocolSCCSP = 96 // Semaphore Communications Sec. Pro.
ProtocolETHERIP = 97 // Ethernet-within-IP Encapsulation
ProtocolENCAP = 98 // Encapsulation Header

View File

@ -46,7 +46,7 @@ func main() {
fmt.Fprintf(&bb, "// go generate gen.go\n")
fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
fmt.Fprintf(&bb, "package iana\n\n")
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
for _, r := range registries {
resp, err := http.Get(r.url)
if err != nil {
@ -264,6 +264,10 @@ func (pn *protocolNumbers) escape() []canonProtocolRecord {
" ", "",
)
for i, pr := range pn.Records {
if strings.Contains(pr.Name, "Deprecated") ||
strings.Contains(pr.Name, "deprecated") {
continue
}
prs[i].OrigName = pr.Name
s := strings.TrimSpace(pr.Name)
switch pr.Name {

View File

@ -11,7 +11,7 @@ import (
"syscall"
"unsafe"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
)
func marshalDst(b []byte, cm *ControlMessage) []byte {

View File

@ -10,7 +10,7 @@ import (
"syscall"
"unsafe"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
)
func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {
@ -23,7 +23,7 @@ func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {
if ip := cm.Src.To4(); ip != nil {
copy(pi.Spec_dst[:], ip)
}
if cm.IfIndex != 0 {
if cm.IfIndex > 0 {
pi.setIfindex(cm.IfIndex)
}
}

View File

@ -7,21 +7,17 @@
package ipv4
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
// TODO(mikio): Implement this
return errOpNoSupport
}
func newControlMessage(opt *rawOpt) []byte {
// TODO(mikio): Implement this
return nil
}
func parseControlMessage(b []byte) (*ControlMessage, error) {
// TODO(mikio): Implement this
return nil, errOpNoSupport
}
func marshalControlMessage(cm *ControlMessage) []byte {
// TODO(mikio): Implement this
return nil
}

View File

@ -11,13 +11,13 @@ import (
"syscall"
"unsafe"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
)
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
opt.Lock()
defer opt.Unlock()
if cf&FlagTTL != 0 {
if cf&FlagTTL != 0 && sockOpts[ssoReceiveTTL].name > 0 {
if err := setInt(fd, &sockOpts[ssoReceiveTTL], boolint(on)); err != nil {
return err
}
@ -39,7 +39,7 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
}
}
} else {
if cf&FlagDst != 0 {
if cf&FlagDst != 0 && sockOpts[ssoReceiveDst].name > 0 {
if err := setInt(fd, &sockOpts[ssoReceiveDst], boolint(on)); err != nil {
return err
}
@ -49,7 +49,7 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
opt.clear(FlagDst)
}
}
if cf&FlagInterface != 0 {
if cf&FlagInterface != 0 && sockOpts[ssoReceiveInterface].name > 0 {
if err := setInt(fd, &sockOpts[ssoReceiveInterface], boolint(on)); err != nil {
return err
}
@ -66,7 +66,7 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
func newControlMessage(opt *rawOpt) (oob []byte) {
opt.RLock()
var l int
if opt.isset(FlagTTL) {
if opt.isset(FlagTTL) && ctlOpts[ctlTTL].name > 0 {
l += syscall.CmsgSpace(ctlOpts[ctlTTL].length)
}
if ctlOpts[ctlPacketInfo].name > 0 {
@ -74,17 +74,17 @@ func newControlMessage(opt *rawOpt) (oob []byte) {
l += syscall.CmsgSpace(ctlOpts[ctlPacketInfo].length)
}
} else {
if opt.isset(FlagDst) {
if opt.isset(FlagDst) && ctlOpts[ctlDst].name > 0 {
l += syscall.CmsgSpace(ctlOpts[ctlDst].length)
}
if opt.isset(FlagInterface) {
if opt.isset(FlagInterface) && ctlOpts[ctlInterface].name > 0 {
l += syscall.CmsgSpace(ctlOpts[ctlInterface].length)
}
}
if l > 0 {
oob = make([]byte, l)
b := oob
if opt.isset(FlagTTL) {
if opt.isset(FlagTTL) && ctlOpts[ctlTTL].name > 0 {
b = ctlOpts[ctlTTL].marshal(b, nil)
}
if ctlOpts[ctlPacketInfo].name > 0 {
@ -92,10 +92,10 @@ func newControlMessage(opt *rawOpt) (oob []byte) {
b = ctlOpts[ctlPacketInfo].marshal(b, nil)
}
} else {
if opt.isset(FlagDst) {
if opt.isset(FlagDst) && ctlOpts[ctlDst].name > 0 {
b = ctlOpts[ctlDst].marshal(b, nil)
}
if opt.isset(FlagInterface) {
if opt.isset(FlagInterface) && ctlOpts[ctlInterface].name > 0 {
b = ctlOpts[ctlInterface].marshal(b, nil)
}
}
@ -136,18 +136,16 @@ func marshalControlMessage(cm *ControlMessage) (oob []byte) {
return nil
}
var l int
if ctlOpts[ctlPacketInfo].name > 0 {
if cm.Src.To4() != nil || cm.IfIndex != 0 {
l += syscall.CmsgSpace(ctlOpts[ctlPacketInfo].length)
}
pktinfo := false
if ctlOpts[ctlPacketInfo].name > 0 && (cm.Src.To4() != nil || cm.IfIndex > 0) {
pktinfo = true
l += syscall.CmsgSpace(ctlOpts[ctlPacketInfo].length)
}
if l > 0 {
oob = make([]byte, l)
b := oob
if ctlOpts[ctlPacketInfo].name > 0 {
if cm.Src.To4() != nil || cm.IfIndex != 0 {
b = ctlOpts[ctlPacketInfo].marshal(b, cm)
}
if pktinfo {
b = ctlOpts[ctlPacketInfo].marshal(b, cm)
}
}
return

View File

@ -7,21 +7,21 @@ package ipv4
import "syscall"
func setControlMessage(fd syscall.Handle, opt *rawOpt, cf ControlFlags, on bool) error {
// TODO(mikio): Implement this
// TODO(mikio): implement this
return syscall.EWINDOWS
}
func newControlMessage(opt *rawOpt) []byte {
// TODO(mikio): Implement this
// TODO(mikio): implement this
return nil
}
func parseControlMessage(b []byte) (*ControlMessage, error) {
// TODO(mikio): Implement this
// TODO(mikio): implement this
return nil, syscall.EWINDOWS
}
func marshalControlMessage(cm *ControlMessage) []byte {
// TODO(mikio): Implement this
// TODO(mikio): implement this
return nil
}

View File

@ -9,6 +9,8 @@
package ipv4
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
@ -40,14 +42,28 @@ const (
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
sysSizeofInetPktinfo = C.sizeof_struct_in_pktinfo
sysSizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
sysSizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sysSizeofInetPktinfo = C.sizeof_struct_in_pktinfo
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
sysSizeofIPMreqn = C.sizeof_struct_ip_mreqn
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
sysSizeofIPMreqn = C.sizeof_struct_ip_mreqn
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
sysSizeofGroupReq = C.sizeof_struct_group_req
sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
)
type sysSockaddrStorage C.struct_sockaddr_storage
type sysSockaddrInet C.struct_sockaddr_in
type sysInetPktinfo C.struct_in_pktinfo
type sysIPMreq C.struct_ip_mreq
@ -55,3 +71,7 @@ type sysIPMreq C.struct_ip_mreq
type sysIPMreqn C.struct_ip_mreqn
type sysIPMreqSource C.struct_ip_mreq_source
type sysGroupReq C.struct_group_req
type sysGroupSourceReq C.struct_group_source_req

View File

@ -9,6 +9,8 @@
package ipv4
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
@ -41,14 +43,33 @@ const (
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
sysSizeofIPMreqn = C.sizeof_struct_ip_mreqn
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
sysSizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
sysSizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
sysSizeofIPMreqn = C.sizeof_struct_ip_mreqn
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
sysSizeofGroupReq = C.sizeof_struct_group_req
sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
)
type sysSockaddrStorage C.struct_sockaddr_storage
type sysSockaddrInet C.struct_sockaddr_in
type sysIPMreq C.struct_ip_mreq
type sysIPMreqn C.struct_ip_mreqn
type sysIPMreqSource C.struct_ip_mreq_source
type sysGroupReq C.struct_group_req
type sysGroupSourceReq C.struct_group_source_req

View File

@ -9,7 +9,10 @@
package ipv4
/*
#include <time.h>
#include <linux/errqueue.h>
#include <linux/icmp.h>
#include <linux/in.h>
*/
import "C"
@ -47,14 +50,24 @@ const (
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
sysIP_MSFILTER = C.IP_MSFILTER
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
sysMCAST_MSFILTER = C.MCAST_MSFILTER
sysIP_MULTICAST_ALL = C.IP_MULTICAST_ALL
sysIP_PMTUDISC_DONT = C.IP_PMTUDISC_DONT
sysIP_PMTUDISC_WANT = C.IP_PMTUDISC_WANT
sysIP_PMTUDISC_DO = C.IP_PMTUDISC_DO
sysIP_PMTUDISC_PROBE = C.IP_PMTUDISC_PROBE
sysIP_PMTUDISC_INTERFACE = C.IP_PMTUDISC_INTERFACE
sysIP_PMTUDISC_OMIT = C.IP_PMTUDISC_OMIT
//sysIP_PMTUDISC_DONT = C.IP_PMTUDISC_DONT
//sysIP_PMTUDISC_WANT = C.IP_PMTUDISC_WANT
//sysIP_PMTUDISC_DO = C.IP_PMTUDISC_DO
//sysIP_PMTUDISC_PROBE = C.IP_PMTUDISC_PROBE
//sysIP_PMTUDISC_INTERFACE = C.IP_PMTUDISC_INTERFACE
//sysIP_PMTUDISC_OMIT = C.IP_PMTUDISC_OMIT
sysICMP_FILTER = C.ICMP_FILTER
sysSO_EE_ORIGIN_NONE = C.SO_EE_ORIGIN_NONE
sysSO_EE_ORIGIN_LOCAL = C.SO_EE_ORIGIN_LOCAL
@ -63,14 +76,24 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = C.SO_EE_ORIGIN_TXSTATUS
sysSO_EE_ORIGIN_TIMESTAMPING = C.SO_EE_ORIGIN_TIMESTAMPING
sysSizeofInetPktinfo = C.sizeof_struct_in_pktinfo
sysSizeofSockExtendedErr = C.sizeof_struct_sock_extended_err
sysSizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
sysSizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sysSizeofInetPktinfo = C.sizeof_struct_in_pktinfo
sysSizeofSockExtendedErr = C.sizeof_struct_sock_extended_err
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
sysSizeofIPMreqn = C.sizeof_struct_ip_mreqn
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
sysSizeofIPMreqn = C.sizeof_struct_ip_mreqn
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
sysSizeofGroupReq = C.sizeof_struct_group_req
sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
sysSizeofICMPFilter = C.sizeof_struct_icmp_filter
)
type sysKernelSockaddrStorage C.struct___kernel_sockaddr_storage
type sysSockaddrInet C.struct_sockaddr_in
type sysInetPktinfo C.struct_in_pktinfo
type sysSockExtendedErr C.struct_sock_extended_err
@ -80,3 +103,9 @@ type sysIPMreq C.struct_ip_mreq
type sysIPMreqn C.struct_ip_mreqn
type sysIPMreqSource C.struct_ip_mreq_source
type sysGroupReq C.struct_group_req
type sysGroupSourceReq C.struct_group_source_req
type sysICMPFilter C.struct_icmp_filter

View File

@ -0,0 +1,251 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd windows
package ipv4
import (
"net"
"syscall"
)
// MulticastTTL returns the time-to-live field value for outgoing
// multicast packets.
func (c *dgramOpt) MulticastTTL() (int, error) {
if !c.ok() {
return 0, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return 0, err
}
return getInt(fd, &sockOpts[ssoMulticastTTL])
}
// SetMulticastTTL sets the time-to-live field value for future
// outgoing multicast packets.
func (c *dgramOpt) SetMulticastTTL(ttl int) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setInt(fd, &sockOpts[ssoMulticastTTL], ttl)
}
// MulticastInterface returns the default interface for multicast
// packet transmissions.
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
if !c.ok() {
return nil, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return nil, err
}
return getInterface(fd, &sockOpts[ssoMulticastInterface])
}
// SetMulticastInterface sets the default interface for future
// multicast packet transmissions.
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setInterface(fd, &sockOpts[ssoMulticastInterface], ifi)
}
// MulticastLoopback reports whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) MulticastLoopback() (bool, error) {
if !c.ok() {
return false, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return false, err
}
on, err := getInt(fd, &sockOpts[ssoMulticastLoopback])
if err != nil {
return false, err
}
return on == 1, nil
}
// SetMulticastLoopback sets whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setInt(fd, &sockOpts[ssoMulticastLoopback], boolint(on))
}
// JoinGroup joins the group address group on the interface ifi.
// By default all sources that can cast data to group are accepted.
// It's possible to mute and unmute data transmission from a specific
// source by using ExcludeSourceSpecificGroup and
// IncludeSourceSpecificGroup.
// JoinGroup uses the system assigned multicast interface when ifi is
// nil, although this is not recommended because the assignment
// depends on platforms and sometimes it might require routing
// configuration.
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP4(group)
if grp == nil {
return errMissingAddress
}
return setGroup(fd, &sockOpts[ssoJoinGroup], ifi, grp)
}
// LeaveGroup leaves the group address group on the interface ifi
// regardless of whether the group is any-source group or
// source-specific group.
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP4(group)
if grp == nil {
return errMissingAddress
}
return setGroup(fd, &sockOpts[ssoLeaveGroup], ifi, grp)
}
// JoinSourceSpecificGroup joins the source-specific group comprising
// group and source on the interface ifi.
// JoinSourceSpecificGroup uses the system assigned multicast
// interface when ifi is nil, although this is not recommended because
// the assignment depends on platforms and sometimes it might require
// routing configuration.
func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP4(group)
if grp == nil {
return errMissingAddress
}
src := netAddrToIP4(source)
if src == nil {
return errMissingAddress
}
return setSourceGroup(fd, &sockOpts[ssoJoinSourceGroup], ifi, grp, src)
}
// LeaveSourceSpecificGroup leaves the source-specific group on the
// interface ifi.
func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP4(group)
if grp == nil {
return errMissingAddress
}
src := netAddrToIP4(source)
if src == nil {
return errMissingAddress
}
return setSourceGroup(fd, &sockOpts[ssoLeaveSourceGroup], ifi, grp, src)
}
// ExcludeSourceSpecificGroup excludes the source-specific group from
// the already joined any-source groups by JoinGroup on the interface
// ifi.
func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP4(group)
if grp == nil {
return errMissingAddress
}
src := netAddrToIP4(source)
if src == nil {
return errMissingAddress
}
return setSourceGroup(fd, &sockOpts[ssoBlockSourceGroup], ifi, grp, src)
}
// IncludeSourceSpecificGroup includes the excluded source-specific
// group by ExcludeSourceSpecificGroup again on the interface ifi.
func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
grp := netAddrToIP4(group)
if grp == nil {
return errMissingAddress
}
src := netAddrToIP4(source)
if src == nil {
return errMissingAddress
}
return setSourceGroup(fd, &sockOpts[ssoUnblockSourceGroup], ifi, grp, src)
}
// ICMPFilter returns an ICMP filter.
// Currently only Linux supports this.
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
if !c.ok() {
return nil, syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return nil, err
}
return getICMPFilter(fd, &sockOpts[ssoICMPFilter])
}
// SetICMPFilter deploys the ICMP filter.
// Currently only Linux supports this.
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
if !c.ok() {
return syscall.EINVAL
}
fd, err := c.sysfd()
if err != nil {
return err
}
return setICMPFilter(fd, &sockOpts[ssoICMPFilter], f)
}

View File

@ -0,0 +1,106 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build nacl plan9 solaris
package ipv4
import "net"
// MulticastTTL returns the time-to-live field value for outgoing
// multicast packets.
func (c *dgramOpt) MulticastTTL() (int, error) {
return 0, errOpNoSupport
}
// SetMulticastTTL sets the time-to-live field value for future
// outgoing multicast packets.
func (c *dgramOpt) SetMulticastTTL(ttl int) error {
return errOpNoSupport
}
// MulticastInterface returns the default interface for multicast
// packet transmissions.
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
return nil, errOpNoSupport
}
// SetMulticastInterface sets the default interface for future
// multicast packet transmissions.
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
return errOpNoSupport
}
// MulticastLoopback reports whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) MulticastLoopback() (bool, error) {
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 {
return errOpNoSupport
}
// JoinGroup joins the group address group on the interface ifi.
// By default all sources that can cast data to group are accepted.
// It's possible to mute and unmute data transmission from a specific
// source by using ExcludeSourceSpecificGroup and
// IncludeSourceSpecificGroup.
// JoinGroup uses the system assigned multicast interface when ifi is
// nil, although this is not recommended because the assignment
// depends on platforms and sometimes it might require routing
// configuration.
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
return errOpNoSupport
}
// LeaveGroup leaves the group address group on the interface ifi
// regardless of whether the group is any-source group or
// source-specific group.
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
return errOpNoSupport
}
// JoinSourceSpecificGroup joins the source-specific group comprising
// group and source on the interface ifi.
// JoinSourceSpecificGroup uses the system assigned multicast
// interface when ifi is nil, although this is not recommended because
// the assignment depends on platforms and sometimes it might require
// routing configuration.
func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
return errOpNoSupport
}
// LeaveSourceSpecificGroup leaves the source-specific group on the
// interface ifi.
func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
return errOpNoSupport
}
// ExcludeSourceSpecificGroup excludes the source-specific group from
// the already joined any-source groups by JoinGroup on the interface
// ifi.
func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
return errOpNoSupport
}
// IncludeSourceSpecificGroup includes the excluded source-specific
// group by ExcludeSourceSpecificGroup again on the interface ifi.
func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
return errOpNoSupport
}
// ICMPFilter returns an ICMP filter.
// Currently only Linux supports this.
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
return nil, errOpNoSupport
}
// SetICMPFilter deploys the ICMP filter.
// Currently only Linux supports this.
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
return errOpNoSupport
}

View File

@ -6,9 +6,15 @@
// Protocol version 4.
//
// The package provides IP-level socket options that allow
// manipulation of IPv4 facilities. The IPv4 and basic host
// requirements for IPv4 are defined in RFC 791, RFC 1112 and RFC
// 1122.
// manipulation of IPv4 facilities.
//
// The IPv4 protocol and basic host requirements for IPv4 are defined
// in RFC 791 and RFC 1122.
// Host extensions for multicasting and socket interface extensions
// for multicast source filters are defined in RFC 1112 and RFC 3678.
// IGMPv1, IGMPv2 and IGMPv3 are defined in RFC 1112, RFC 2236 and RFC
// 3376.
// Source-specific multicast is defined in RFC 4607.
//
//
// Unicasting
@ -34,7 +40,7 @@
// defer c.Close()
//
// The outgoing packets will be labeled DiffServ assured forwarding
// class 1 low drop precedence, as known as AF11 packets.
// class 1 low drop precedence, known as AF11 packets.
//
// if err := ipv4.NewConn(c).SetTOS(DiffServAF11); err != nil {
// // error handling
@ -193,4 +199,44 @@
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 250)}); err != nil {
// // error handling
// }
//
//
// Source-specific multicasting
//
// An application that uses PacketConn or RawConn on IGMPv3 supported
// platform is able to join source-specific multicast groups.
// The application may use JoinSourceSpecificGroup and
// LeaveSourceSpecificGroup for the operation known as "include" mode,
//
// ssmgroup := net.UDPAddr{IP: net.IPv4(232, 7, 8, 9)}
// ssmsource := net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)})
// if err := p.JoinSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
// // error handling
// }
// if err := p.LeaveSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
// // error handling
// }
//
// or JoinGroup, ExcludeSourceSpecificGroup,
// IncludeSourceSpecificGroup and LeaveGroup for the operation known
// as "exclude" mode.
//
// exclsource := net.UDPAddr{IP: net.IPv4(192, 168, 0, 254)}
// if err := p.JoinGroup(en0, &ssmgroup); err != nil {
// // error handling
// }
// if err := p.ExcludeSourceSpecificGroup(en0, &ssmgroup, &exclsource); err != nil {
// // error handling
// }
// if err := p.LeaveGroup(en0, &ssmgroup); err != nil {
// // error handling
// }
//
// Note that it depends on each platform implementation what happens
// when an application which runs on IGMPv3 unsupported platform uses
// JoinSourceSpecificGroup and LeaveSourceSpecificGroup.
// In general the platform tries to fall back to conversations using
// IGMPv1 or IGMPv2 and starts to listen to multicast traffic.
// In the fallback case, ExcludeSourceSpecificGroup and
// IncludeSourceSpecificGroup may return an error.
package ipv4

View File

@ -97,11 +97,17 @@ func (c *PacketConn) Close() error {
// NewPacketConn returns a new PacketConn using c as its underlying
// transport.
func NewPacketConn(c net.PacketConn) *PacketConn {
return &PacketConn{
p := &PacketConn{
genericOpt: genericOpt{Conn: c.(net.Conn)},
dgramOpt: dgramOpt{PacketConn: c},
payloadHandler: payloadHandler{PacketConn: c},
}
if _, ok := c.(*net.IPConn); ok && sockOpts[ssoStripHeader].name > 0 {
if fd, err := p.payloadHandler.sysfd(); err == nil {
setInt(fd, &sockOpts[ssoStripHeader], boolint(true))
}
}
return p
}
// A RawConn represents a packet network endpoint that uses the IPv4

View File

@ -0,0 +1,223 @@
// Copyright 2012 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 ipv4_test
import (
"fmt"
"log"
"net"
"os"
"runtime"
"time"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/ipv4"
"golang.org/x/net/icmp"
)
func ExampleConn_markingTCP() {
ln, err := net.Listen("tcp4", "0.0.0.0:1024")
if err != nil {
log.Fatal(err)
}
defer ln.Close()
for {
c, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
go func(c net.Conn) {
defer c.Close()
p := ipv4.NewConn(c)
if err := p.SetTOS(iana.DiffServAF11); err != nil {
log.Fatal(err)
}
if err := p.SetTTL(128); err != nil {
log.Fatal(err)
}
if _, err := c.Write([]byte("HELLO-R-U-THERE-ACK")); err != nil {
log.Fatal(err)
}
}(c)
}
}
func ExamplePacketConn_servingOneShotMulticastDNS() {
c, err := net.ListenPacket("udp4", "0.0.0.0:5353") // mDNS over UDP
if err != nil {
log.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
en0, err := net.InterfaceByName("en0")
if err != nil {
log.Fatal(err)
}
mDNSLinkLocal := net.UDPAddr{IP: net.IPv4(224, 0, 0, 251)}
if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil {
log.Fatal(err)
}
defer p.LeaveGroup(en0, &mDNSLinkLocal)
if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
log.Fatal(err)
}
b := make([]byte, 1500)
for {
_, cm, peer, err := p.ReadFrom(b)
if err != nil {
log.Fatal(err)
}
if !cm.Dst.IsMulticast() || !cm.Dst.Equal(mDNSLinkLocal.IP) {
continue
}
answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this
if _, err := p.WriteTo(answers, nil, peer); err != nil {
log.Fatal(err)
}
}
}
func ExamplePacketConn_tracingIPPacketRoute() {
// Tracing an IP packet route to www.google.com.
const host = "www.google.com"
ips, err := net.LookupIP(host)
if err != nil {
log.Fatal(err)
}
var dst net.IPAddr
for _, ip := range ips {
if ip.To4() != nil {
dst.IP = ip
fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host)
break
}
}
if dst.IP == nil {
log.Fatal("no A record found")
}
c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolICMP), "0.0.0.0") // ICMP for IPv4
if err != nil {
log.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil {
log.Fatal(err)
}
wm := icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff,
Data: []byte("HELLO-R-U-THERE"),
},
}
rb := make([]byte, 1500)
for i := 1; i <= 64; i++ { // up to 64 hops
wm.Body.(*icmp.Echo).Seq = i
wb, err := wm.Marshal(nil)
if err != nil {
log.Fatal(err)
}
if err := p.SetTTL(i); err != nil {
log.Fatal(err)
}
// In the real world usually there are several
// multiple traffic-engineered paths for each hop.
// You may need to probe a few times to each hop.
begin := time.Now()
if _, err := p.WriteTo(wb, nil, &dst); err != nil {
log.Fatal(err)
}
if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
log.Fatal(err)
}
n, cm, peer, err := p.ReadFrom(rb)
if err != nil {
if err, ok := err.(net.Error); ok && err.Timeout() {
fmt.Printf("%v\t*\n", i)
continue
}
log.Fatal(err)
}
rm, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
if err != nil {
log.Fatal(err)
}
rtt := time.Since(begin)
// In the real world you need to determine whether the
// received message is yours using ControlMessage.Src,
// ControlMessage.Dst, icmp.Echo.ID and icmp.Echo.Seq.
switch rm.Type {
case ipv4.ICMPTypeTimeExceeded:
names, _ := net.LookupAddr(peer.String())
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
case ipv4.ICMPTypeEchoReply:
names, _ := net.LookupAddr(peer.String())
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
return
default:
log.Printf("unknown ICMP message: %+v\n", rm)
}
}
}
func ExampleRawConn_advertisingOSPFHello() {
c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolOSPFIGP), "0.0.0.0") // OSPF for IPv4
if err != nil {
log.Fatal(err)
}
defer c.Close()
r, err := ipv4.NewRawConn(c)
if err != nil {
log.Fatal(err)
}
en0, err := net.InterfaceByName("en0")
if err != nil {
log.Fatal(err)
}
allSPFRouters := net.IPAddr{IP: net.IPv4(224, 0, 0, 5)}
if err := r.JoinGroup(en0, &allSPFRouters); err != nil {
log.Fatal(err)
}
defer r.LeaveGroup(en0, &allSPFRouters)
hello := make([]byte, 24) // fake hello data, you need to implement this
ospf := make([]byte, 24) // fake ospf header, you need to implement this
ospf[0] = 2 // version 2
ospf[1] = 1 // hello packet
ospf = append(ospf, hello...)
iph := &ipv4.Header{
Version: ipv4.Version,
Len: ipv4.HeaderLen,
TOS: iana.DiffServCS6,
TotalLen: ipv4.HeaderLen + len(ospf),
TTL: 1,
Protocol: iana.ProtocolOSPFIGP,
Dst: allSPFRouters.IP.To4(),
}
var cm *ipv4.ControlMessage
switch runtime.GOOS {
case "darwin", "linux":
cm = &ipv4.ControlMessage{IfIndex: en0.Index}
default:
if err := r.SetMulticastInterface(en0); err != nil {
log.Fatal(err)
}
}
if err := r.WriteTo(iph, ospf, cm); err != nil {
log.Fatal(err)
}
}

View File

@ -52,18 +52,25 @@ func genzsys() error {
if err != nil {
return err
}
switch runtime.GOOS {
case "dragonfly", "solaris":
// The ipv4 pacakge still supports go1.2, and so we
// need to take care of additional platforms in go1.3
// and above for working with go1.2.
// The ipv4 pacakge still supports go1.2, and so we need to
// take care of additional platforms in go1.3 and above for
// working with go1.2.
switch {
case runtime.GOOS == "dragonfly" || runtime.GOOS == "solaris":
b = bytes.Replace(b, []byte("package ipv4\n"), []byte("// +build "+runtime.GOOS+"\n\npackage ipv4\n"), 1)
case runtime.GOOS == "linux" && (runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le"):
b = bytes.Replace(b, []byte("package ipv4\n"), []byte("// +build "+runtime.GOOS+","+runtime.GOARCH+"\n\npackage ipv4\n"), 1)
}
b, err = format.Source(b)
if err != nil {
return err
}
if err := ioutil.WriteFile("zsys_"+runtime.GOOS+".go", b, 0644); err != nil {
zsys := "zsys_" + runtime.GOOS + ".go"
switch runtime.GOOS {
case "freebsd", "linux":
zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
}
if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
return err
}
return nil

View File

@ -6,22 +6,24 @@
package ipv4
// TOS returns the type-of-service field value for outgoing packets.
func (c *genericOpt) TOS() (int, error) {
// TODO(mikio): Implement this
return 0, errOpNoSupport
}
// SetTOS sets the type-of-service field value for future outgoing
// packets.
func (c *genericOpt) SetTOS(tos int) error {
// TODO(mikio): Implement this
return errOpNoSupport
}
// TTL returns the time-to-live field value for outgoing packets.
func (c *genericOpt) TTL() (int, error) {
// TODO(mikio): Implement this
return 0, errOpNoSupport
}
// SetTTL sets the time-to-live field value for future outgoing
// packets.
func (c *genericOpt) SetTTL(ttl int) error {
// TODO(mikio): Implement this
return errOpNoSupport
}

View File

@ -21,33 +21,12 @@ var (
errInvalidConnType = errors.New("invalid conn type")
)
// References:
//
// RFC 791 Internet Protocol
// http://tools.ietf.org/html/rfc791
// RFC 1112 Host Extensions for IP Multicasting
// http://tools.ietf.org/html/rfc1112
// RFC 1122 Requirements for Internet Hosts
// http://tools.ietf.org/html/rfc1122
const (
Version = 4 // protocol version
HeaderLen = 20 // header length without extension headers
maxHeaderLen = 60 // sensible default, revisit if later RFCs define new usage of version and header length fields
)
const (
posTOS = 1 // type-of-service
posTotalLen = 2 // packet total length
posID = 4 // identification
posFragOff = 6 // fragment offset
posTTL = 8 // time-to-live
posProtocol = 9 // next protocol
posChecksum = 10 // checksum
posSrc = 12 // source address
posDst = 16 // destination address
)
type HeaderFlags int
const (
@ -79,10 +58,6 @@ func (h *Header) String() string {
return fmt.Sprintf("ver: %v, hdrlen: %v, tos: %#x, totallen: %v, id: %#x, flags: %#x, fragoff: %#x, ttl: %v, proto: %v, cksum: %#x, src: %v, dst: %v", h.Version, h.Len, h.TOS, h.TotalLen, h.ID, h.Flags, h.FragOff, h.TTL, h.Protocol, h.Checksum, h.Src, h.Dst)
}
// Please refer to the online manual; IP(4) on Darwin, FreeBSD and
// OpenBSD. IP(7) on Linux.
const supportsNewIPInput = runtime.GOOS == "linux" || runtime.GOOS == "openbsd"
// Marshal returns the binary encoding of the IPv4 header h.
func (h *Header) Marshal() ([]byte, error) {
if h == nil {
@ -94,24 +69,26 @@ func (h *Header) Marshal() ([]byte, error) {
hdrlen := HeaderLen + len(h.Options)
b := make([]byte, hdrlen)
b[0] = byte(Version<<4 | (hdrlen >> 2 & 0x0f))
b[posTOS] = byte(h.TOS)
b[1] = byte(h.TOS)
flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13)
if supportsNewIPInput {
b[posTotalLen], b[posTotalLen+1] = byte(h.TotalLen>>8), byte(h.TotalLen)
b[posFragOff], b[posFragOff+1] = byte(flagsAndFragOff>>8), byte(flagsAndFragOff)
} else {
*(*uint16)(unsafe.Pointer(&b[posTotalLen : posTotalLen+1][0])) = uint16(h.TotalLen)
*(*uint16)(unsafe.Pointer(&b[posFragOff : posFragOff+1][0])) = uint16(flagsAndFragOff)
switch runtime.GOOS {
case "darwin", "dragonfly", "freebsd", "netbsd":
// TODO(mikio): fix potential misaligned memory access
*(*uint16)(unsafe.Pointer(&b[2:3][0])) = uint16(h.TotalLen)
*(*uint16)(unsafe.Pointer(&b[6:7][0])) = uint16(flagsAndFragOff)
default:
b[2], b[3] = byte(h.TotalLen>>8), byte(h.TotalLen)
b[6], b[7] = byte(flagsAndFragOff>>8), byte(flagsAndFragOff)
}
b[posID], b[posID+1] = byte(h.ID>>8), byte(h.ID)
b[posTTL] = byte(h.TTL)
b[posProtocol] = byte(h.Protocol)
b[posChecksum], b[posChecksum+1] = byte(h.Checksum>>8), byte(h.Checksum)
b[4], b[5] = byte(h.ID>>8), byte(h.ID)
b[8] = byte(h.TTL)
b[9] = byte(h.Protocol)
b[10], b[11] = byte(h.Checksum>>8), byte(h.Checksum)
if ip := h.Src.To4(); ip != nil {
copy(b[posSrc:posSrc+net.IPv4len], ip[:net.IPv4len])
copy(b[12:16], ip[:net.IPv4len])
}
if ip := h.Dst.To4(); ip != nil {
copy(b[posDst:posDst+net.IPv4len], ip[:net.IPv4len])
copy(b[16:20], ip[:net.IPv4len])
} else {
return nil, errMissingAddress
}
@ -133,28 +110,37 @@ func ParseHeader(b []byte) (*Header, error) {
if hdrlen > len(b) {
return nil, errBufferTooShort
}
h := &Header{}
h.Version = int(b[0] >> 4)
h.Len = hdrlen
h.TOS = int(b[posTOS])
if supportsNewIPInput {
h.TotalLen = int(b[posTotalLen])<<8 | int(b[posTotalLen+1])
h.FragOff = int(b[posFragOff])<<8 | int(b[posFragOff+1])
} else {
h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[posTotalLen : posTotalLen+1][0])))
if runtime.GOOS != "freebsd" || freebsdVersion < 1000000 {
h := &Header{
Version: int(b[0] >> 4),
Len: hdrlen,
TOS: int(b[1]),
ID: int(b[4])<<8 | int(b[5]),
TTL: int(b[8]),
Protocol: int(b[9]),
Checksum: int(b[10])<<8 | int(b[11]),
Src: net.IPv4(b[12], b[13], b[14], b[15]),
Dst: net.IPv4(b[16], b[17], b[18], b[19]),
}
switch runtime.GOOS {
case "darwin", "dragonfly", "netbsd":
// TODO(mikio): fix potential misaligned memory access
h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0]))) + hdrlen
// TODO(mikio): fix potential misaligned memory access
h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[6:7][0])))
case "freebsd":
// TODO(mikio): fix potential misaligned memory access
h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0])))
if freebsdVersion < 1000000 {
h.TotalLen += hdrlen
}
h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[posFragOff : posFragOff+1][0])))
// TODO(mikio): fix potential misaligned memory access
h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[6:7][0])))
default:
h.TotalLen = int(b[2])<<8 | int(b[3])
h.FragOff = int(b[6])<<8 | int(b[7])
}
h.Flags = HeaderFlags(h.FragOff&0xe000) >> 13
h.FragOff = h.FragOff & 0x1fff
h.ID = int(b[posID])<<8 | int(b[posID+1])
h.TTL = int(b[posTTL])
h.Protocol = int(b[posProtocol])
h.Checksum = int(b[posChecksum])<<8 | int(b[posChecksum+1])
h.Src = net.IPv4(b[posSrc], b[posSrc+1], b[posSrc+2], b[posSrc+3])
h.Dst = net.IPv4(b[posDst], b[posDst+1], b[posDst+2], b[posDst+3])
if hdrlen-HeaderLen > 0 {
h.Options = make([]byte, hdrlen-HeaderLen)
copy(h.Options, b[HeaderLen:])

View File

@ -70,35 +70,45 @@ var (
func TestMarshalHeader(t *testing.T) {
b, err := testHeader.Marshal()
if err != nil {
t.Fatalf("ipv4.Header.Marshal failed: %v", err)
t.Fatal(err)
}
var wh []byte
if supportsNewIPInput {
wh = wireHeaderToKernel[:]
} else {
switch runtime.GOOS {
case "darwin", "dragonfly", "netbsd":
wh = wireHeaderToTradBSDKernel[:]
case "freebsd":
if freebsdVersion < 1000000 {
wh = wireHeaderToTradBSDKernel[:]
} else {
wh = wireHeaderFromFreeBSD10Kernel[:]
}
default:
wh = wireHeaderToKernel[:]
}
if !bytes.Equal(b, wh) {
t.Fatalf("ipv4.Header.Marshal failed: %#v not equal %#v", b, wh)
t.Fatalf("got %#v; want %#v", b, wh)
}
}
func TestParseHeader(t *testing.T) {
var wh []byte
if supportsNewIPInput {
wh = wireHeaderFromKernel[:]
} else {
if runtime.GOOS == "freebsd" && freebsdVersion >= 1000000 {
wh = wireHeaderFromFreeBSD10Kernel[:]
} else {
switch runtime.GOOS {
case "darwin", "dragonfly", "netbsd":
wh = wireHeaderFromTradBSDKernel[:]
case "freebsd":
if freebsdVersion < 1000000 {
wh = wireHeaderFromTradBSDKernel[:]
} else {
wh = wireHeaderFromFreeBSD10Kernel[:]
}
default:
wh = wireHeaderFromKernel[:]
}
h, err := ParseHeader(wh)
if err != nil {
t.Fatalf("ipv4.ParseHeader failed: %v", err)
t.Fatal(err)
}
if !reflect.DeepEqual(h, testHeader) {
t.Fatalf("ipv4.ParseHeader failed: %#v not equal %#v", h, testHeader)
t.Fatalf("got %#v; want %#v", h, testHeader)
}
}

View File

@ -7,21 +7,17 @@
package ipv4
func (c *genericOpt) sysfd() (int, error) {
// TODO(mikio): Implement this
return 0, errOpNoSupport
}
func (c *dgramOpt) sysfd() (int, error) {
// TODO(mikio): Implement this
return 0, errOpNoSupport
}
func (c *payloadHandler) sysfd() (int, error) {
// TODO(mikio): Implement this
return 0, errOpNoSupport
}
func (c *packetHandler) sysfd() (int, error) {
// TODO(mikio): Implement this
return 0, errOpNoSupport
}

57
Godeps/_workspace/src/golang.org/x/net/ipv4/icmp.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
// 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 ipv4
import "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
// An ICMPType represents a type of ICMP message.
type ICMPType int
func (typ ICMPType) String() string {
s, ok := icmpTypes[typ]
if !ok {
return "<nil>"
}
return s
}
// Protocol returns the ICMPv4 protocol number.
func (typ ICMPType) Protocol() int {
return iana.ProtocolICMP
}
// An ICMPFilter represents an ICMP message filter for incoming
// packets. The filter belongs to a packet delivery path on a host and
// it cannot interact with forwarding packets or tunnel-outer packets.
//
// Note: RFC 2460 defines a reasonable role model and it works not
// only for IPv6 but IPv4. A node means a device that implements IP.
// A router means a node that forwards IP packets not explicitly
// addressed to itself, and a host means a node that is not a router.
type ICMPFilter struct {
sysICMPFilter
}
// Accept accepts incoming ICMP packets including the type field value
// typ.
func (f *ICMPFilter) Accept(typ ICMPType) {
f.accept(typ)
}
// Block blocks incoming ICMP packets including the type field value
// typ.
func (f *ICMPFilter) Block(typ ICMPType) {
f.block(typ)
}
// SetAll sets the filter action to the filter.
func (f *ICMPFilter) SetAll(block bool) {
f.setAll(block)
}
// WillBlock reports whether the ICMP type will be blocked.
func (f *ICMPFilter) WillBlock(typ ICMPType) bool {
return f.willBlock(typ)
}

View File

@ -0,0 +1,25 @@
// Copyright 2014 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 ipv4
func (f *sysICMPFilter) accept(typ ICMPType) {
f.Data &^= 1 << (uint32(typ) & 31)
}
func (f *sysICMPFilter) block(typ ICMPType) {
f.Data |= 1 << (uint32(typ) & 31)
}
func (f *sysICMPFilter) setAll(block bool) {
if block {
f.Data = 1<<32 - 1
} else {
f.Data = 0
}
}
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
return f.Data&(1<<(uint32(typ)&31)) != 0
}

View File

@ -1,22 +1,25 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Copyright 2014 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
// +build !linux
package ipv4
const sysSizeofICMPFilter = 0x0
type sysICMPFilter struct {
// TODO(mikio): Implement this
}
func (f *sysICMPFilter) set(typ ICMPType, block bool) {
// TODO(mikio): Implement this
func (f *sysICMPFilter) accept(typ ICMPType) {
}
func (f *sysICMPFilter) block(typ ICMPType) {
}
func (f *sysICMPFilter) setAll(block bool) {
// TODO(mikio): Implement this
}
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
// TODO(mikio): Implement this
return false
}

View File

@ -0,0 +1,95 @@
// Copyright 2014 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 ipv4_test
import (
"net"
"reflect"
"runtime"
"testing"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/ipv4"
"golang.org/x/net/internal/nettest"
)
var icmpStringTests = []struct {
in ipv4.ICMPType
out string
}{
{ipv4.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; want %s", s, tt.out)
}
}
}
func TestICMPFilter(t *testing.T) {
switch runtime.GOOS {
case "linux":
default:
t.Skipf("not supported on %s", runtime.GOOS)
}
var f ipv4.ICMPFilter
for _, toggle := range []bool{false, true} {
f.SetAll(toggle)
for _, typ := range []ipv4.ICMPType{
ipv4.ICMPTypeDestinationUnreachable,
ipv4.ICMPTypeEchoReply,
ipv4.ICMPTypeTimeExceeded,
ipv4.ICMPTypeParameterProblem,
} {
f.Accept(typ)
if f.WillBlock(typ) {
t.Errorf("ipv4.ICMPFilter.Set(%v, false) failed", typ)
}
f.Block(typ)
if !f.WillBlock(typ) {
t.Errorf("ipv4.ICMPFilter.Set(%v, true) failed", typ)
}
}
}
}
func TestSetICMPFilter(t *testing.T) {
switch runtime.GOOS {
case "linux":
default:
t.Skipf("not supported on %s", runtime.GOOS)
}
if m, ok := nettest.SupportsRawIPSocket(); !ok {
t.Skip(m)
}
c, err := net.ListenPacket("ip4:icmp", "127.0.0.1")
if err != nil {
t.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
var f ipv4.ICMPFilter
f.SetAll(true)
f.Accept(ipv4.ICMPTypeEcho)
f.Accept(ipv4.ICMPTypeEchoReply)
if err := p.SetICMPFilter(&f); err != nil {
t.Fatal(err)
}
kf, err := p.ICMPFilter()
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(kf, &f) {
t.Fatalf("got %#v; want %#v", kf, f)
}
}

View File

@ -14,7 +14,7 @@ func acceptor(t *testing.T, ln net.Listener, done chan<- bool) {
c, err := ln.Accept()
if err != nil {
t.Errorf("net.Listener.Accept failed: %v", err)
t.Error(err)
return
}
c.Close()

View File

@ -0,0 +1,334 @@
// Copyright 2012 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 ipv4_test
import (
"bytes"
"net"
"os"
"runtime"
"testing"
"time"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/ipv4"
"golang.org/x/net/icmp"
"golang.org/x/net/internal/nettest"
)
var packetConnReadWriteMulticastUDPTests = []struct {
addr string
grp, src *net.UDPAddr
}{
{"224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
{"232.0.1.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
}
func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %s", runtime.GOOS)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %s", runtime.GOOS)
}
for _, tt := range packetConnReadWriteMulticastUDPTests {
c, err := net.ListenPacket("udp4", tt.addr)
if err != nil {
t.Fatal(err)
}
defer c.Close()
grp := *tt.grp
grp.Port = c.LocalAddr().(*net.UDPAddr).Port
p := ipv4.NewPacketConn(c)
defer p.Close()
if tt.src == nil {
if err := p.JoinGroup(ifi, &grp); err != nil {
t.Fatal(err)
}
defer p.LeaveGroup(ifi, &grp)
} else {
if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil {
switch runtime.GOOS {
case "freebsd", "linux":
default: // platforms that don't support IGMPv2/3 fail here
t.Logf("not supported on %s", runtime.GOOS)
continue
}
t.Fatal(err)
}
defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src)
}
if err := p.SetMulticastInterface(ifi); err != nil {
t.Fatal(err)
}
if _, err := p.MulticastInterface(); err != nil {
t.Fatal(err)
}
if err := p.SetMulticastLoopback(true); err != nil {
t.Fatal(err)
}
if _, err := p.MulticastLoopback(); err != nil {
t.Fatal(err)
}
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
wb := []byte("HELLO-R-U-THERE")
for i, toggle := range []bool{true, false, true} {
if err := p.SetControlMessage(cf, toggle); err != nil {
if nettest.ProtocolNotSupported(err) {
t.Logf("not supported on %s", runtime.GOOS)
continue
}
t.Fatal(err)
}
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatal(err)
}
p.SetMulticastTTL(i + 1)
if n, err := p.WriteTo(wb, nil, &grp); err != nil {
t.Fatal(err)
} else if n != len(wb) {
t.Fatalf("got %v; want %v", n, len(wb))
}
rb := make([]byte, 128)
if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatal(err)
} else if !bytes.Equal(rb[:n], wb) {
t.Fatalf("got %v; want %v", rb[:n], wb)
} else {
t.Logf("rcvd cmsg: %v", cm)
}
}
}
}
var packetConnReadWriteMulticastICMPTests = []struct {
grp, src *net.IPAddr
}{
{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
}
func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %s", runtime.GOOS)
}
if m, ok := nettest.SupportsRawIPSocket(); !ok {
t.Skip(m)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %s", runtime.GOOS)
}
for _, tt := range packetConnReadWriteMulticastICMPTests {
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
t.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
defer p.Close()
if tt.src == nil {
if err := p.JoinGroup(ifi, tt.grp); err != nil {
t.Fatal(err)
}
defer p.LeaveGroup(ifi, tt.grp)
} else {
if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
switch runtime.GOOS {
case "freebsd", "linux":
default: // platforms that don't support IGMPv2/3 fail here
t.Logf("not supported on %s", runtime.GOOS)
continue
}
t.Fatal(err)
}
defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
}
if err := p.SetMulticastInterface(ifi); err != nil {
t.Fatal(err)
}
if _, err := p.MulticastInterface(); err != nil {
t.Fatal(err)
}
if err := p.SetMulticastLoopback(true); err != nil {
t.Fatal(err)
}
if _, err := p.MulticastLoopback(); err != nil {
t.Fatal(err)
}
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
for i, toggle := range []bool{true, false, true} {
wb, err := (&icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff, Seq: i + 1,
Data: []byte("HELLO-R-U-THERE"),
},
}).Marshal(nil)
if err != nil {
t.Fatal(err)
}
if err := p.SetControlMessage(cf, toggle); err != nil {
if nettest.ProtocolNotSupported(err) {
t.Logf("not supported on %s", runtime.GOOS)
continue
}
t.Fatal(err)
}
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatal(err)
}
p.SetMulticastTTL(i + 1)
if n, err := p.WriteTo(wb, nil, tt.grp); err != nil {
t.Fatal(err)
} else if n != len(wb) {
t.Fatalf("got %v; want %v", n, len(wb))
}
rb := make([]byte, 128)
if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatal(err)
} else {
t.Logf("rcvd cmsg: %v", cm)
m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
if err != nil {
t.Fatal(err)
}
switch {
case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
default:
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
}
}
}
}
}
var rawConnReadWriteMulticastICMPTests = []struct {
grp, src *net.IPAddr
}{
{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
}
func TestRawConnReadWriteMulticastICMP(t *testing.T) {
if testing.Short() {
t.Skip("to avoid external network")
}
if m, ok := nettest.SupportsRawIPSocket(); !ok {
t.Skip(m)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %s", runtime.GOOS)
}
for _, tt := range rawConnReadWriteMulticastICMPTests {
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
t.Fatal(err)
}
defer c.Close()
r, err := ipv4.NewRawConn(c)
if err != nil {
t.Fatal(err)
}
defer r.Close()
if tt.src == nil {
if err := r.JoinGroup(ifi, tt.grp); err != nil {
t.Fatal(err)
}
defer r.LeaveGroup(ifi, tt.grp)
} else {
if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
switch runtime.GOOS {
case "freebsd", "linux":
default: // platforms that don't support IGMPv2/3 fail here
t.Logf("not supported on %s", runtime.GOOS)
continue
}
t.Fatal(err)
}
defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
}
if err := r.SetMulticastInterface(ifi); err != nil {
t.Fatal(err)
}
if _, err := r.MulticastInterface(); err != nil {
t.Fatal(err)
}
if err := r.SetMulticastLoopback(true); err != nil {
t.Fatal(err)
}
if _, err := r.MulticastLoopback(); err != nil {
t.Fatal(err)
}
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
for i, toggle := range []bool{true, false, true} {
wb, err := (&icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff, Seq: i + 1,
Data: []byte("HELLO-R-U-THERE"),
},
}).Marshal(nil)
if err != nil {
t.Fatal(err)
}
wh := &ipv4.Header{
Version: ipv4.Version,
Len: ipv4.HeaderLen,
TOS: i + 1,
TotalLen: ipv4.HeaderLen + len(wb),
Protocol: 1,
Dst: tt.grp.IP,
}
if err := r.SetControlMessage(cf, toggle); err != nil {
if nettest.ProtocolNotSupported(err) {
t.Logf("not supported on %s", runtime.GOOS)
continue
}
t.Fatal(err)
}
if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatal(err)
}
r.SetMulticastTTL(i + 1)
if err := r.WriteTo(wh, wb, nil); err != nil {
t.Fatal(err)
}
rb := make([]byte, ipv4.HeaderLen+128)
if rh, b, cm, err := r.ReadFrom(rb); err != nil {
t.Fatal(err)
} else {
t.Logf("rcvd cmsg: %v", cm)
m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
if err != nil {
t.Fatal(err)
}
switch {
case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
default:
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
}
}
}
}
}

View File

@ -6,12 +6,11 @@ package ipv4_test
import (
"net"
"os"
"runtime"
"testing"
"code.google.com/p/go.net/internal/nettest"
"code.google.com/p/go.net/ipv4"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/ipv4"
"golang.org/x/net/internal/nettest"
)
var udpMultipleGroupListenerTests = []net.Addr{
@ -23,7 +22,7 @@ var udpMultipleGroupListenerTests = []net.Addr{
func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
t.Skipf("not supported on %s", runtime.GOOS)
}
if testing.Short() {
t.Skip("to avoid external network")
@ -32,7 +31,7 @@ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
for _, gaddr := range udpMultipleGroupListenerTests {
c, err := net.ListenPacket("udp4", "0.0.0.0:0") // wildcard address with no reusable port
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
t.Fatal(err)
}
defer c.Close()
@ -41,20 +40,20 @@ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
ift, err := net.Interfaces()
if err != nil {
t.Fatalf("net.Interfaces failed: %v", err)
t.Fatal(err)
}
for i, ifi := range ift {
if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
continue
}
if err := p.JoinGroup(&ifi, gaddr); err != nil {
t.Fatalf("ipv4.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err)
t.Fatal(err)
}
mift = append(mift, &ift[i])
}
for _, ifi := range mift {
if err := p.LeaveGroup(ifi, gaddr); err != nil {
t.Fatalf("ipv4.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err)
t.Fatal(err)
}
}
}
@ -63,7 +62,7 @@ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
t.Skipf("not supported on %s", runtime.GOOS)
}
if testing.Short() {
t.Skip("to avoid external network")
@ -72,13 +71,13 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
for _, gaddr := range udpMultipleGroupListenerTests {
c1, err := net.ListenPacket("udp4", "224.0.0.0:1024") // wildcard address with reusable port
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
t.Fatal(err)
}
defer c1.Close()
c2, err := net.ListenPacket("udp4", "224.0.0.0:1024") // wildcard address with reusable port
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
t.Fatal(err)
}
defer c2.Close()
@ -89,7 +88,7 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
ift, err := net.Interfaces()
if err != nil {
t.Fatalf("net.Interfaces failed: %v", err)
t.Fatal(err)
}
for i, ifi := range ift {
if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
@ -97,7 +96,7 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
}
for _, p := range ps {
if err := p.JoinGroup(&ifi, gaddr); err != nil {
t.Fatalf("ipv4.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err)
t.Fatal(err)
}
}
mift = append(mift, &ift[i])
@ -105,7 +104,7 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
for _, ifi := range mift {
for _, p := range ps {
if err := p.LeaveGroup(ifi, gaddr); err != nil {
t.Fatalf("ipv4.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err)
t.Fatal(err)
}
}
}
@ -115,7 +114,7 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
t.Skipf("not supported on %s", runtime.GOOS)
}
if testing.Short() {
t.Skip("to avoid external network")
@ -130,7 +129,7 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
ift, err := net.Interfaces()
if err != nil {
t.Fatalf("net.Interfaces failed: %v", err)
t.Fatal(err)
}
for i, ifi := range ift {
ip, ok := nettest.IsMulticastCapable("ip4", &ifi)
@ -139,18 +138,18 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
}
c, err := net.ListenPacket("udp4", ip.String()+":"+"1024") // unicast address with non-reusable port
if err != nil {
t.Fatalf("net.ListenPacket with %v failed: %v", ip, err)
t.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
t.Fatalf("ipv4.PacketConn.JoinGroup on %v failed: %v", ifi, err)
t.Fatal(err)
}
mlt = append(mlt, &ml{p, &ift[i]})
}
for _, m := range mlt {
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
t.Fatalf("ipv4.PacketConn.LeaveGroup on %v failed: %v", m.ifi, err)
t.Fatal(err)
}
}
}
@ -158,44 +157,44 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
t.Skipf("not supported on %s", runtime.GOOS)
}
if testing.Short() {
t.Skip("to avoid external network")
}
if os.Getuid() != 0 {
t.Skip("must be root")
if m, ok := nettest.SupportsRawIPSocket(); !ok {
t.Skip(m)
}
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") // wildcard address
if err != nil {
t.Fatalf("net.ListenPacket failed: %v", err)
t.Fatal(err)
}
defer c.Close()
r, err := ipv4.NewRawConn(c)
if err != nil {
t.Fatalf("ipv4.RawConn failed: %v", err)
t.Fatal(err)
}
gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
var mift []*net.Interface
ift, err := net.Interfaces()
if err != nil {
t.Fatalf("net.Interfaces failed: %v", err)
t.Fatal(err)
}
for i, ifi := range ift {
if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
continue
}
if err := r.JoinGroup(&ifi, &gaddr); err != nil {
t.Fatalf("ipv4.RawConn.JoinGroup on %v failed: %v", ifi, err)
t.Fatal(err)
}
mift = append(mift, &ift[i])
}
for _, ifi := range mift {
if err := r.LeaveGroup(ifi, &gaddr); err != nil {
t.Fatalf("ipv4.RawConn.LeaveGroup on %v failed: %v", ifi, err)
t.Fatal(err)
}
}
}
@ -203,13 +202,13 @@ func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) {
func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %q", runtime.GOOS)
t.Skipf("not supported on %s", runtime.GOOS)
}
if testing.Short() {
t.Skip("to avoid external network")
}
if os.Getuid() != 0 {
t.Skip("must be root")
if m, ok := nettest.SupportsRawIPSocket(); !ok {
t.Skip(m)
}
gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
@ -221,7 +220,7 @@ func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) {
ift, err := net.Interfaces()
if err != nil {
t.Fatalf("net.Interfaces failed: %v", err)
t.Fatal(err)
}
for i, ifi := range ift {
ip, ok := nettest.IsMulticastCapable("ip4", &ifi)
@ -230,21 +229,21 @@ func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) {
}
c, err := net.ListenPacket("ip4:253", ip.String()) // unicast address
if err != nil {
t.Fatalf("net.ListenPacket with %v failed: %v", ip, err)
t.Fatal(err)
}
defer c.Close()
r, err := ipv4.NewRawConn(c)
if err != nil {
t.Fatalf("ipv4.NewRawConn failed: %v", err)
t.Fatal(err)
}
if err := r.JoinGroup(&ifi, &gaddr); err != nil {
t.Fatalf("ipv4.RawConn.JoinGroup on %v failed: %v", ifi, err)
t.Fatal(err)
}
mlt = append(mlt, &ml{r, &ift[i]})
}
for _, m := range mlt {
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
t.Fatalf("ipv4.RawConn.LeaveGroup on %v failed: %v", m.ifi, err)
t.Fatal(err)
}
}
}

View File

@ -0,0 +1,195 @@
// Copyright 2012 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 ipv4_test
import (
"net"
"runtime"
"testing"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/ipv4"
"golang.org/x/net/internal/nettest"
)
var packetConnMulticastSocketOptionTests = []struct {
net, proto, addr string
grp, src net.Addr
}{
{"udp4", "", "224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, nil}, // see RFC 4727
{"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
{"udp4", "", "232.0.0.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 249)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
{"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
}
func TestPacketConnMulticastSocketOptions(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris":
t.Skipf("not supported on %s", runtime.GOOS)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %s", runtime.GOOS)
}
m, ok := nettest.SupportsRawIPSocket()
for _, tt := range packetConnMulticastSocketOptionTests {
if tt.net == "ip4" && !ok {
t.Log(m)
continue
}
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
if err != nil {
t.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
defer p.Close()
if tt.src == nil {
testMulticastSocketOptions(t, p, ifi, tt.grp)
} else {
testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
}
}
}
var rawConnMulticastSocketOptionTests = []struct {
grp, src net.Addr
}{
{&net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
{&net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
}
func TestRawConnMulticastSocketOptions(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris":
t.Skipf("not supported on %s", runtime.GOOS)
}
if m, ok := nettest.SupportsRawIPSocket(); !ok {
t.Skip(m)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
if ifi == nil {
t.Skipf("not available on %s", runtime.GOOS)
}
for _, tt := range rawConnMulticastSocketOptionTests {
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
t.Fatal(err)
}
defer c.Close()
r, err := ipv4.NewRawConn(c)
if err != nil {
t.Fatal(err)
}
defer r.Close()
if tt.src == nil {
testMulticastSocketOptions(t, r, ifi, tt.grp)
} else {
testSourceSpecificMulticastSocketOptions(t, r, ifi, tt.grp, tt.src)
}
}
}
type testIPv4MulticastConn interface {
MulticastTTL() (int, error)
SetMulticastTTL(ttl int) error
MulticastLoopback() (bool, error)
SetMulticastLoopback(bool) error
JoinGroup(*net.Interface, net.Addr) error
LeaveGroup(*net.Interface, net.Addr) error
JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
}
func testMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp net.Addr) {
const ttl = 255
if err := c.SetMulticastTTL(ttl); err != nil {
t.Error(err)
return
}
if v, err := c.MulticastTTL(); err != nil {
t.Error(err)
return
} else if v != ttl {
t.Errorf("got %v; want %v", v, ttl)
return
}
for _, toggle := range []bool{true, false} {
if err := c.SetMulticastLoopback(toggle); err != nil {
t.Error(err)
return
}
if v, err := c.MulticastLoopback(); err != nil {
t.Error(err)
return
} else if v != toggle {
t.Errorf("got %v; want %v", v, toggle)
return
}
}
if err := c.JoinGroup(ifi, grp); err != nil {
t.Error(err)
return
}
if err := c.LeaveGroup(ifi, grp); err != nil {
t.Error(err)
return
}
}
func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp, src net.Addr) {
// MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP
if err := c.JoinGroup(ifi, grp); err != nil {
t.Error(err)
return
}
if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil {
switch runtime.GOOS {
case "freebsd", "linux":
default: // platforms that don't support IGMPv2/3 fail here
t.Logf("not supported on %s", runtime.GOOS)
return
}
t.Error(err)
return
}
if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil {
t.Error(err)
return
}
if err := c.LeaveGroup(ifi, grp); err != nil {
t.Error(err)
return
}
// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP
if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
t.Error(err)
return
}
if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil {
t.Error(err)
return
}
// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP
if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
t.Error(err)
return
}
if err := c.LeaveGroup(ifi, grp); err != nil {
t.Error(err)
return
}
}

View File

@ -27,13 +27,19 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.
return 0, nil, nil, err
}
case *net.IPConn:
nb := make([]byte, maxHeaderLen+len(b))
if n, oobn, _, src, err = c.ReadMsgIP(nb, oob); err != nil {
return 0, nil, nil, err
if sockOpts[ssoStripHeader].name > 0 {
if n, oobn, _, src, err = c.ReadMsgIP(b, oob); err != nil {
return 0, nil, nil, err
}
} else {
nb := make([]byte, maxHeaderLen+len(b))
if n, oobn, _, src, err = c.ReadMsgIP(nb, oob); err != nil {
return 0, nil, nil, err
}
hdrlen := int(nb[0]&0x0f) << 2
copy(b, nb[hdrlen:])
n -= hdrlen
}
hdrlen := int(nb[0]&0x0f) << 2
copy(b, nb[hdrlen:])
n -= hdrlen
default:
return 0, nil, nil, errInvalidConnType
}
@ -50,7 +56,7 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.
// address dst through the endpoint c, copying the payload from b. It
// returns the number of bytes written. The control message cm allows
// the datagram path and the outgoing interface to be specified.
// Currently only Darwin and Darwin support this. The cm may be nil if
// Currently only Darwin and Linux support this. The cm may be nil if
// control of the outgoing datagram is not required.
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
if !c.ok() {

View File

@ -0,0 +1,170 @@
// Copyright 2012 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 ipv4_test
import (
"bytes"
"net"
"runtime"
"sync"
"testing"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/ipv4"
"golang.org/x/net/internal/nettest"
)
func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
c, err := net.ListenPacket("udp4", "127.0.0.1:0")
if err != nil {
return nil, nil, err
}
dst, err := net.ResolveUDPAddr("udp4", 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.Fatal(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.Fatal(err)
}
if _, _, err := c.ReadFrom(rb); err != nil {
b.Fatal(err)
}
}
func BenchmarkReadWriteIPv4UDP(b *testing.B) {
c, dst, err := benchmarkUDPListener()
if err != nil {
b.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
defer p.Close()
cf := ipv4.FlagTTL | ipv4.FlagInterface
if err := p.SetControlMessage(cf, true); err != nil {
b.Fatal(err)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
b.ResetTimer()
for i := 0; i < b.N; i++ {
benchmarkReadWriteIPv4UDP(b, p, wb, rb, dst, ifi)
}
}
func benchmarkReadWriteIPv4UDP(b *testing.B, p *ipv4.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
cm := ipv4.ControlMessage{TTL: 1}
if ifi != nil {
cm.IfIndex = ifi.Index
}
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
b.Fatal(err)
} else if n != len(wb) {
b.Fatalf("got %v; want %v", n, len(wb))
}
if _, _, _, err := p.ReadFrom(rb); err != nil {
b.Fatal(err)
}
}
func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
switch runtime.GOOS {
case "nacl", "plan9", "solaris", "windows":
t.Skipf("not supported on %s", runtime.GOOS)
}
c, err := net.ListenPacket("udp4", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
defer p.Close()
dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
if err != nil {
t.Fatal(err)
}
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
wb := []byte("HELLO-R-U-THERE")
if err := p.SetControlMessage(cf, true); err != nil { // probe before test
if nettest.ProtocolNotSupported(err) {
t.Skipf("not supported on %s", runtime.GOOS)
}
t.Fatal(err)
}
var wg sync.WaitGroup
reader := func() {
defer wg.Done()
rb := make([]byte, 128)
if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Error(err)
return
} else if !bytes.Equal(rb[:n], wb) {
t.Errorf("got %v; want %v", rb[:n], wb)
return
} else {
t.Logf("rcvd cmsg: %v", cm)
}
}
writer := func(toggle bool) {
defer wg.Done()
cm := ipv4.ControlMessage{
Src: net.IPv4(127, 0, 0, 1),
}
if ifi != nil {
cm.IfIndex = ifi.Index
}
if err := p.SetControlMessage(cf, toggle); err != nil {
t.Error(err)
return
}
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Error(err)
return
} else if n != len(wb) {
t.Errorf("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

@ -15,9 +15,15 @@ const (
ssoReceiveDst // header field on received packet
ssoReceiveInterface // inbound interface on received packet
ssoPacketInfo // incbound or outbound packet path
ssoHeaderPrepend // ipv4 header
ssoHeaderPrepend // ipv4 header prepend
ssoStripHeader // strip ipv4 header
ssoICMPFilter // icmp filter
ssoJoinGroup // any-source multicast
ssoLeaveGroup // any-source multicast
ssoJoinSourceGroup // source-specific multicast
ssoLeaveSourceGroup // source-specific multicast
ssoBlockSourceGroup // any-source or source-specific multicast
ssoUnblockSourceGroup // any-source or source-specific multicast
ssoMax
)
@ -26,8 +32,11 @@ const (
ssoTypeByte = iota + 1
ssoTypeInt
ssoTypeInterface
ssoTypeICMPFilter
ssoTypeIPMreq
ssoTypeIPMreqn
ssoTypeGroupReq
ssoTypeGroupSourceReq
)
// A sockOpt represents a binding for sticky socket option.

View File

@ -11,7 +11,7 @@ import (
"os"
"unsafe"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
)
func setsockoptIPMreq(fd, name int, ifi *net.Interface, grp net.IP) error {

View File

@ -10,7 +10,7 @@ import (
"syscall"
"unsafe"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
)
func setsockoptIPMreq(fd syscall.Handle, name int, ifi *net.Interface, grp net.IP) error {

View File

@ -11,7 +11,7 @@ import (
"os"
"unsafe"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
)
func getsockoptIPMreqn(fd, name int) (*net.Interface, error) {

View File

@ -0,0 +1,17 @@
// Copyright 2014 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
package ipv4
import "net"
func setsockoptGroupReq(fd, name int, ifi *net.Interface, grp net.IP) error {
return errOpNoSupport
}
func setsockoptGroupSourceReq(fd, name int, ifi *net.Interface, grp, src net.IP) error {
return errOpNoSupport
}

View File

@ -0,0 +1,33 @@
// Copyright 2014 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
package ipv4
import (
"net"
"os"
"unsafe"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
)
func setsockoptGroupReq(fd, name int, ifi *net.Interface, grp net.IP) error {
var gr sysGroupReq
if ifi != nil {
gr.Interface = uint32(ifi.Index)
}
gr.setGroup(grp)
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, name, unsafe.Pointer(&gr), sysSizeofGroupReq))
}
func setsockoptGroupSourceReq(fd, name int, ifi *net.Interface, grp, src net.IP) error {
var gsr sysGroupSourceReq
if ifi != nil {
gsr.Interface = uint32(ifi.Index)
}
gsr.setSourceGroup(grp, src)
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, name, unsafe.Pointer(&gsr), sysSizeofGroupSourceReq))
}

View File

@ -0,0 +1,11 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build nacl plan9 solaris
package ipv4
func setInt(fd int, opt *sockOpt, v int) error {
return errOpNoSupport
}

View File

@ -11,7 +11,7 @@ import (
"os"
"unsafe"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
)
func getInt(fd int, opt *sockOpt) (int, error) {
@ -79,6 +79,25 @@ func setInterface(fd int, opt *sockOpt, ifi *net.Interface) error {
}
}
func getICMPFilter(fd int, opt *sockOpt) (*ICMPFilter, error) {
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
return nil, errOpNoSupport
}
var f ICMPFilter
l := sysSockoptLen(sysSizeofICMPFilter)
if err := getsockopt(fd, iana.ProtocolReserved, opt.name, unsafe.Pointer(&f.sysICMPFilter), &l); err != nil {
return nil, os.NewSyscallError("getsockopt", err)
}
return &f, nil
}
func setICMPFilter(fd int, opt *sockOpt, f *ICMPFilter) error {
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
return errOpNoSupport
}
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolReserved, opt.name, unsafe.Pointer(&f.sysICMPFilter), sysSizeofICMPFilter))
}
func setGroup(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
if opt.name < 1 {
return errOpNoSupport
@ -88,7 +107,16 @@ func setGroup(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
return setsockoptIPMreq(fd, opt.name, ifi, grp)
case ssoTypeIPMreqn:
return setsockoptIPMreqn(fd, opt.name, ifi, grp)
case ssoTypeGroupReq:
return setsockoptGroupReq(fd, opt.name, ifi, grp)
default:
return errOpNoSupport
}
}
func setSourceGroup(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
if opt.name < 1 || opt.typ != ssoTypeGroupSourceReq {
return errOpNoSupport
}
return setsockoptGroupSourceReq(fd, opt.name, ifi, grp, src)
}

View File

@ -10,7 +10,7 @@ import (
"syscall"
"unsafe"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/internal/iana"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/internal/iana"
)
func getInt(fd syscall.Handle, opt *sockOpt) (int, error) {
@ -47,9 +47,22 @@ func setInterface(fd syscall.Handle, opt *sockOpt, ifi *net.Interface) error {
return setsockoptInterface(fd, opt.name, ifi)
}
func getICMPFilter(fd syscall.Handle, opt *sockOpt) (*ICMPFilter, error) {
return nil, errOpNoSupport
}
func setICMPFilter(fd syscall.Handle, opt *sockOpt, f *ICMPFilter) error {
return errOpNoSupport
}
func setGroup(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
if opt.name < 1 || opt.typ != ssoTypeIPMreq {
return errOpNoSupport
}
return setsockoptIPMreq(fd, opt.name, ifi, grp)
}
func setSourceGroup(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
// TODO(mikio): implement this
return errOpNoSupport
}

Some files were not shown because too many files have changed in this diff Show More