Compare commits
126
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e3b3dc4e7 | ||
|
|
8d421a62d2 | ||
|
|
185b0690c8 | ||
|
|
bd0e97023e | ||
|
|
34ff0706a3 | ||
|
|
acba61babb | ||
|
|
24d2a93c0d | ||
|
|
de43080228 | ||
|
|
b0cd7be39b | ||
|
|
a7169a6348 | ||
|
|
1d710bdcd9 | ||
|
|
5feffba1ff | ||
|
|
6c56586a6b | ||
|
|
a32b66c7c3 | ||
|
|
7e3c06191e | ||
|
|
3d09090c4e | ||
|
|
596a49c112 | ||
|
|
95fc253d6b | ||
|
|
e6d5372029 | ||
|
|
8e5c692244 | ||
|
|
e694c664e5 | ||
|
|
8779f93746 | ||
|
|
1f0f5c1e23 | ||
|
|
aaf6bf3cd2 | ||
|
|
fa95c82daf | ||
|
|
0da7142a59 | ||
|
|
446a938b06 | ||
|
|
21c3994650 | ||
|
|
f90f3a5ca6 | ||
|
|
a34d2b72c0 | ||
|
|
9d617dcfec | ||
|
|
55506a0fc3 | ||
|
|
19c03f504f | ||
|
|
985a3436e2 | ||
|
|
9dae87c80c | ||
|
|
46364a38c6 | ||
|
|
148b2b9d02 | ||
|
|
64354b51c9 | ||
|
|
f2db1c8ab2 | ||
|
|
36b8a75ede | ||
|
|
0a42b85c06 | ||
|
|
baf231e3b6 | ||
|
|
e26e85b6d6 | ||
|
|
b2193b23e5 | ||
|
|
2af3a92833 | ||
|
|
d2af6dcf38 | ||
|
|
dd6b66167e | ||
|
|
51a4a88a81 | ||
|
|
516efb21cf | ||
|
|
2d4397af53 | ||
|
|
06f319a380 | ||
|
|
37ed5a01e0 | ||
|
|
4a9997e449 | ||
|
|
54269553c8 | ||
|
|
3d6ea23511 | ||
|
|
61130ea191 | ||
|
|
2581e56503 | ||
|
|
fea0ae7f2f | ||
|
|
3299438cbd | ||
|
|
5c160048df | ||
|
|
e3e1036dda | ||
|
|
876d7ac85e | ||
|
|
70b37dc469 | ||
|
|
6393f69138 | ||
|
|
0ca39f6c65 | ||
|
|
02493251d5 | ||
|
|
ff04648112 | ||
|
|
55002d7adf | ||
|
|
0664c6b5b0 | ||
|
|
a4ebac147b | ||
|
|
cf802dc67e | ||
|
|
37fb6473b3 | ||
|
|
ba676f2810 | ||
|
|
b3d7c622c3 | ||
|
|
bc016e360e | ||
|
|
594918dd3c | ||
|
|
ec5feb41e8 | ||
|
|
94c52e3a77 | ||
|
|
875de4f637 | ||
|
|
72fa5a69f1 | ||
|
|
d63e54237b | ||
|
|
e256d93b43 | ||
|
|
4d12df5424 | ||
|
|
cae120fd4d | ||
|
|
be332a6223 | ||
|
|
bda0bb6f13 | ||
|
|
9bdcadf634 | ||
|
|
037be433f8 | ||
|
|
2bed62dd9e | ||
|
|
a27bc4ebea | ||
|
|
d6e34761dc | ||
|
|
98effcd8e3 | ||
|
|
baa87bc823 | ||
|
|
944d9c84a0 | ||
|
|
1e447741ee | ||
|
|
4405ac7386 | ||
|
|
e1190f0f0f | ||
|
|
a7f2416c0c | ||
|
|
40d0100132 | ||
|
|
37f7c48cfc | ||
|
|
21adf752c8 | ||
|
|
aec143b882 | ||
|
|
f691040936 | ||
|
|
42acf0ed60 | ||
|
|
ca4a3589e5 | ||
|
|
2eead17224 | ||
|
|
626b26a227 | ||
|
|
c46db0761e | ||
|
|
cfed06697d | ||
|
|
a0d9183b14 | ||
|
|
d3eb674b30 | ||
|
|
7d444021bb | ||
|
|
a03dd1bd41 | ||
|
|
4b366f2857 | ||
|
|
c87faace6b | ||
|
|
1e8b185377 | ||
|
|
031804827f | ||
|
|
6cccd9b6fc | ||
|
|
687fbb0a7e | ||
|
|
8f2db99c86 | ||
|
|
2c0f8dc546 | ||
|
|
a388fb0bb7 | ||
|
|
27465353c1 | ||
|
|
c2ccab4361 | ||
|
|
bb876eac82 | ||
|
|
34c04babbe |
+4
-4
@@ -1,4 +1,6 @@
|
|||||||
./syncthing
|
syncthing
|
||||||
|
!gui/syncthing
|
||||||
|
!Godeps/_workspace/src/github.com/syncthing
|
||||||
syncthing.exe
|
syncthing.exe
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.zip
|
*.zip
|
||||||
@@ -9,8 +11,6 @@ files/pidx
|
|||||||
bin
|
bin
|
||||||
perfstats*.csv
|
perfstats*.csv
|
||||||
coverage.xml
|
coverage.xml
|
||||||
!gui/scripts/syncthing
|
syncthing.sig
|
||||||
syncthing.md5
|
|
||||||
syncthing.exe.md5
|
|
||||||
RELEASE
|
RELEASE
|
||||||
deb
|
deb
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ Phill Luby <phill.luby@newredo.com>
|
|||||||
Piotr Bejda <piotrb10@gmail.com>
|
Piotr Bejda <piotrb10@gmail.com>
|
||||||
Ryan Sullivan <kayoticsully@gmail.com>
|
Ryan Sullivan <kayoticsully@gmail.com>
|
||||||
Sergey Mishin <ralder@yandex.ru>
|
Sergey Mishin <ralder@yandex.ru>
|
||||||
Stefan Tatschner <stefan@sevenbyte.org>
|
Stefan Tatschner <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org>
|
||||||
Tim Abell <tim@timwise.co.uk>
|
Tim Abell <tim@timwise.co.uk>
|
||||||
Tobias Nygren <tnn@nygren.pp.se>
|
Tobias Nygren <tnn@nygren.pp.se>
|
||||||
Tomas Cerveny <kozec@kozec.com>
|
Tomas Cerveny <kozec@kozec.com>
|
||||||
|
|||||||
Generated
+23
-7
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"ImportPath": "github.com/syncthing/syncthing",
|
"ImportPath": "github.com/syncthing/syncthing",
|
||||||
"GoVersion": "go1.5rc1",
|
"GoVersion": "go1.5.1",
|
||||||
"Packages": [
|
"Packages": [
|
||||||
"./cmd/..."
|
"./cmd/..."
|
||||||
],
|
],
|
||||||
"Deps": [
|
"Deps": [
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/bkaradzic/go-lz4",
|
"ImportPath": "github.com/bkaradzic/go-lz4",
|
||||||
"Rev": "d47913b1412890a261b9fefae99d72d2bf5aebd8"
|
"Rev": "74ddf82598bc4745b965729e9c6a463bedd33049"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/calmh/du",
|
"ImportPath": "github.com/calmh/du",
|
||||||
@@ -39,15 +39,23 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/syncthing/protocol",
|
"ImportPath": "github.com/syncthing/protocol",
|
||||||
"Rev": "ebcdea63c07327a342f65415bbadc497462b8f1f"
|
"Rev": "f91191218b192ace841c878f161832d19c09145a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/syncthing/relaysrv/client",
|
||||||
|
"Rev": "6e126fb97e2ff566d35f8d8824e86793d22b2147"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/syncthing/relaysrv/protocol",
|
||||||
|
"Rev": "6e126fb97e2ff566d35f8d8824e86793d22b2147"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/syndtr/goleveldb/leveldb",
|
"ImportPath": "github.com/syndtr/goleveldb/leveldb",
|
||||||
"Rev": "b743d92d3215f11c9b5ce8830fafe1f16786adf4"
|
"Rev": "1a9d62f03ea92815b46fcaab357cfd4df264b1a0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/thejerf/suture",
|
"ImportPath": "github.com/thejerf/suture",
|
||||||
"Rev": "fc7aaeabdc43fe41c5328efa1479ffea0b820978"
|
"Rev": "860b44045335c64a6d54ac7eed22a3aedfc687c9"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/vitrun/qart/coding",
|
"ImportPath": "github.com/vitrun/qart/coding",
|
||||||
@@ -63,11 +71,19 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/bcrypt",
|
"ImportPath": "golang.org/x/crypto/bcrypt",
|
||||||
"Rev": "c16968172724c0b5e8bdc6ad33f5a79443a44cd7"
|
"Rev": "81bf7719a6b7ce9b665598222362b50122dfc13b"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/blowfish",
|
"ImportPath": "golang.org/x/crypto/blowfish",
|
||||||
"Rev": "c16968172724c0b5e8bdc6ad33f5a79443a44cd7"
|
"Rev": "81bf7719a6b7ce9b665598222362b50122dfc13b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/internal/iana",
|
||||||
|
"Rev": "66f0418ca41253f8d1a024eb9754e9441a8e79b9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/ipv6",
|
||||||
|
"Rev": "66f0418ca41253f8d1a024eb9754e9441a8e79b9"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/text/transform",
|
"ImportPath": "golang.org/x/text/transform",
|
||||||
|
|||||||
+2
-1
@@ -4,5 +4,6 @@ go:
|
|||||||
- 1.1
|
- 1.1
|
||||||
- 1.2
|
- 1.2
|
||||||
- 1.3
|
- 1.3
|
||||||
- 1.4
|
- 1.4
|
||||||
|
- 1.5
|
||||||
- tip
|
- tip
|
||||||
|
|||||||
+2
-2
@@ -31,11 +31,11 @@ func (t *TestModel) Index(deviceID DeviceID, folder string, files []FileInfo, fl
|
|||||||
func (t *TestModel) IndexUpdate(deviceID DeviceID, folder string, files []FileInfo, flags uint32, options []Option) {
|
func (t *TestModel) IndexUpdate(deviceID DeviceID, folder string, files []FileInfo, flags uint32, options []Option) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestModel) Request(deviceID DeviceID, folder, name string, offset int64, size int, hash []byte, flags uint32, options []Option, buf []byte) error {
|
func (t *TestModel) Request(deviceID DeviceID, folder, name string, offset int64, hash []byte, flags uint32, options []Option, buf []byte) error {
|
||||||
t.folder = folder
|
t.folder = folder
|
||||||
t.name = name
|
t.name = name
|
||||||
t.offset = offset
|
t.offset = offset
|
||||||
t.size = size
|
t.size = len(buf)
|
||||||
t.hash = hash
|
t.hash = hash
|
||||||
t.flags = flags
|
t.flags = flags
|
||||||
t.options = options
|
t.options = options
|
||||||
|
|||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
// Copyright (C) 2015 The Protocol Authors.
|
||||||
|
|
||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Fuzz(data []byte) int {
|
||||||
|
// Regenerate the length, or we'll most commonly exit quickly due to an
|
||||||
|
// unexpected eof which is unintestering.
|
||||||
|
if len(data) > 8 {
|
||||||
|
binary.BigEndian.PutUint32(data[4:], uint32(len(data))-8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup a rawConnection we'll use to parse the message.
|
||||||
|
c := rawConnection{
|
||||||
|
cr: &countingReader{Reader: bytes.NewReader(data)},
|
||||||
|
closed: make(chan struct{}),
|
||||||
|
pool: sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return make([]byte, BlockSize)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to parse the message.
|
||||||
|
hdr, msg, err := c.readMessage()
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// If parsing worked, attempt to encode it again.
|
||||||
|
newBs, err := msg.AppendXDR(nil)
|
||||||
|
if err != nil {
|
||||||
|
panic("not encodable")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an appriate header for the re-encoding.
|
||||||
|
newMsg := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint32(newMsg, encodeHeader(hdr))
|
||||||
|
binary.BigEndian.PutUint32(newMsg[4:], uint32(len(newBs)))
|
||||||
|
newMsg = append(newMsg, newBs...)
|
||||||
|
|
||||||
|
// Use the rawConnection to parse the re-encoding.
|
||||||
|
c.cr = &countingReader{Reader: bytes.NewReader(newMsg)}
|
||||||
|
hdr2, msg2, err := c.readMessage()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Initial:\n" + hex.Dump(data))
|
||||||
|
fmt.Println("New:\n" + hex.Dump(newMsg))
|
||||||
|
panic("not parseable after re-encode: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the data is the same as it was before.
|
||||||
|
if hdr != hdr2 {
|
||||||
|
panic("headers differ")
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(msg, msg2) {
|
||||||
|
panic("contents differ")
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
// Copyright (C) 2015 The Protocol Authors.
|
||||||
|
|
||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"testing/quick"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This can be used to generate a corpus of valid messages as a starting point
|
||||||
|
// for the fuzzer.
|
||||||
|
func TestGenerateCorpus(t *testing.T) {
|
||||||
|
t.Skip("Use to generate initial corpus only")
|
||||||
|
|
||||||
|
n := 0
|
||||||
|
check := func(idx IndexMessage) bool {
|
||||||
|
for i := range idx.Options {
|
||||||
|
if len(idx.Options[i].Key) > 64 {
|
||||||
|
idx.Options[i].Key = idx.Options[i].Key[:64]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hdr := header{
|
||||||
|
version: 0,
|
||||||
|
msgID: 42,
|
||||||
|
msgType: messageTypeIndex,
|
||||||
|
compression: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
msgBs := idx.MustMarshalXDR()
|
||||||
|
|
||||||
|
buf := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint32(buf, encodeHeader(hdr))
|
||||||
|
binary.BigEndian.PutUint32(buf[4:], uint32(len(msgBs)))
|
||||||
|
buf = append(buf, msgBs...)
|
||||||
|
|
||||||
|
ioutil.WriteFile(fmt.Sprintf("testdata/corpus/test-%03d.xdr", n), buf, 0644)
|
||||||
|
n++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := quick.Check(check, &quick.Config{MaxCount: 1000}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests any crashers found by the fuzzer, for closer investigation.
|
||||||
|
func TestCrashers(t *testing.T) {
|
||||||
|
testFiles(t, "testdata/crashers")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests the entire corpus, which should PASS before the fuzzer starts
|
||||||
|
// fuzzing.
|
||||||
|
func TestCorpus(t *testing.T) {
|
||||||
|
testFiles(t, "testdata/corpus")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFiles(t *testing.T, dir string) {
|
||||||
|
fd, err := os.Open(dir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
crashers, err := fd.Readdirnames(-1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, name := range crashers {
|
||||||
|
if strings.HasSuffix(name, ".output") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(name, ".quoted") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(name)
|
||||||
|
crasher, err := ioutil.ReadFile(dir + "/" + name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Fuzz(crasher)
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-7
@@ -9,7 +9,7 @@ import "fmt"
|
|||||||
|
|
||||||
type IndexMessage struct {
|
type IndexMessage struct {
|
||||||
Folder string
|
Folder string
|
||||||
Files []FileInfo
|
Files []FileInfo // max:1000000
|
||||||
Flags uint32
|
Flags uint32
|
||||||
Options []Option // max:64
|
Options []Option // max:64
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,8 @@ type FileInfo struct {
|
|||||||
Modified int64
|
Modified int64
|
||||||
Version Vector
|
Version Vector
|
||||||
LocalVersion int64
|
LocalVersion int64
|
||||||
Blocks []BlockInfo
|
CachedSize int64 // noencode (cache only)
|
||||||
|
Blocks []BlockInfo // max:1000000
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) String() string {
|
func (f FileInfo) String() string {
|
||||||
@@ -109,9 +110,9 @@ type ResponseMessage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ClusterConfigMessage struct {
|
type ClusterConfigMessage struct {
|
||||||
ClientName string // max:64
|
ClientName string // max:64
|
||||||
ClientVersion string // max:64
|
ClientVersion string // max:64
|
||||||
Folders []Folder
|
Folders []Folder // max:1000000
|
||||||
Options []Option // max:64
|
Options []Option // max:64
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +126,8 @@ func (o *ClusterConfigMessage) GetOption(key string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Folder struct {
|
type Folder struct {
|
||||||
ID string // max:64
|
ID string // max:64
|
||||||
Devices []Device
|
Devices []Device // max:1000000
|
||||||
Flags uint32
|
Flags uint32
|
||||||
Options []Option // max:64
|
Options []Option // max:64
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-8
@@ -42,7 +42,7 @@ IndexMessage Structure:
|
|||||||
|
|
||||||
struct IndexMessage {
|
struct IndexMessage {
|
||||||
string Folder<>;
|
string Folder<>;
|
||||||
FileInfo Files<>;
|
FileInfo Files<1000000>;
|
||||||
unsigned int Flags;
|
unsigned int Flags;
|
||||||
Option Options<64>;
|
Option Options<64>;
|
||||||
}
|
}
|
||||||
@@ -75,6 +75,9 @@ func (o IndexMessage) AppendXDR(bs []byte) ([]byte, error) {
|
|||||||
|
|
||||||
func (o IndexMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
func (o IndexMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
xw.WriteString(o.Folder)
|
xw.WriteString(o.Folder)
|
||||||
|
if l := len(o.Files); l > 1000000 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Files", l, 1000000)
|
||||||
|
}
|
||||||
xw.WriteUint32(uint32(len(o.Files)))
|
xw.WriteUint32(uint32(len(o.Files)))
|
||||||
for i := range o.Files {
|
for i := range o.Files {
|
||||||
_, err := o.Files[i].EncodeXDRInto(xw)
|
_, err := o.Files[i].EncodeXDRInto(xw)
|
||||||
@@ -111,7 +114,10 @@ func (o *IndexMessage) DecodeXDRFrom(xr *xdr.Reader) error {
|
|||||||
o.Folder = xr.ReadString()
|
o.Folder = xr.ReadString()
|
||||||
_FilesSize := int(xr.ReadUint32())
|
_FilesSize := int(xr.ReadUint32())
|
||||||
if _FilesSize < 0 {
|
if _FilesSize < 0 {
|
||||||
return xdr.ElementSizeExceeded("Files", _FilesSize, 0)
|
return xdr.ElementSizeExceeded("Files", _FilesSize, 1000000)
|
||||||
|
}
|
||||||
|
if _FilesSize > 1000000 {
|
||||||
|
return xdr.ElementSizeExceeded("Files", _FilesSize, 1000000)
|
||||||
}
|
}
|
||||||
o.Files = make([]FileInfo, _FilesSize)
|
o.Files = make([]FileInfo, _FilesSize)
|
||||||
for i := range o.Files {
|
for i := range o.Files {
|
||||||
@@ -173,7 +179,7 @@ struct FileInfo {
|
|||||||
hyper Modified;
|
hyper Modified;
|
||||||
Vector Version;
|
Vector Version;
|
||||||
hyper LocalVersion;
|
hyper LocalVersion;
|
||||||
BlockInfo Blocks<>;
|
BlockInfo Blocks<1000000>;
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@@ -214,6 +220,9 @@ func (o FileInfo) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
|||||||
return xw.Tot(), err
|
return xw.Tot(), err
|
||||||
}
|
}
|
||||||
xw.WriteUint64(uint64(o.LocalVersion))
|
xw.WriteUint64(uint64(o.LocalVersion))
|
||||||
|
if l := len(o.Blocks); l > 1000000 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Blocks", l, 1000000)
|
||||||
|
}
|
||||||
xw.WriteUint32(uint32(len(o.Blocks)))
|
xw.WriteUint32(uint32(len(o.Blocks)))
|
||||||
for i := range o.Blocks {
|
for i := range o.Blocks {
|
||||||
_, err := o.Blocks[i].EncodeXDRInto(xw)
|
_, err := o.Blocks[i].EncodeXDRInto(xw)
|
||||||
@@ -243,7 +252,10 @@ func (o *FileInfo) DecodeXDRFrom(xr *xdr.Reader) error {
|
|||||||
o.LocalVersion = int64(xr.ReadUint64())
|
o.LocalVersion = int64(xr.ReadUint64())
|
||||||
_BlocksSize := int(xr.ReadUint32())
|
_BlocksSize := int(xr.ReadUint32())
|
||||||
if _BlocksSize < 0 {
|
if _BlocksSize < 0 {
|
||||||
return xdr.ElementSizeExceeded("Blocks", _BlocksSize, 0)
|
return xdr.ElementSizeExceeded("Blocks", _BlocksSize, 1000000)
|
||||||
|
}
|
||||||
|
if _BlocksSize > 1000000 {
|
||||||
|
return xdr.ElementSizeExceeded("Blocks", _BlocksSize, 1000000)
|
||||||
}
|
}
|
||||||
o.Blocks = make([]BlockInfo, _BlocksSize)
|
o.Blocks = make([]BlockInfo, _BlocksSize)
|
||||||
for i := range o.Blocks {
|
for i := range o.Blocks {
|
||||||
@@ -571,7 +583,7 @@ ClusterConfigMessage Structure:
|
|||||||
struct ClusterConfigMessage {
|
struct ClusterConfigMessage {
|
||||||
string ClientName<64>;
|
string ClientName<64>;
|
||||||
string ClientVersion<64>;
|
string ClientVersion<64>;
|
||||||
Folder Folders<>;
|
Folder Folders<1000000>;
|
||||||
Option Options<64>;
|
Option Options<64>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,6 +622,9 @@ func (o ClusterConfigMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
|||||||
return xw.Tot(), xdr.ElementSizeExceeded("ClientVersion", l, 64)
|
return xw.Tot(), xdr.ElementSizeExceeded("ClientVersion", l, 64)
|
||||||
}
|
}
|
||||||
xw.WriteString(o.ClientVersion)
|
xw.WriteString(o.ClientVersion)
|
||||||
|
if l := len(o.Folders); l > 1000000 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Folders", l, 1000000)
|
||||||
|
}
|
||||||
xw.WriteUint32(uint32(len(o.Folders)))
|
xw.WriteUint32(uint32(len(o.Folders)))
|
||||||
for i := range o.Folders {
|
for i := range o.Folders {
|
||||||
_, err := o.Folders[i].EncodeXDRInto(xw)
|
_, err := o.Folders[i].EncodeXDRInto(xw)
|
||||||
@@ -646,7 +661,10 @@ func (o *ClusterConfigMessage) DecodeXDRFrom(xr *xdr.Reader) error {
|
|||||||
o.ClientVersion = xr.ReadStringMax(64)
|
o.ClientVersion = xr.ReadStringMax(64)
|
||||||
_FoldersSize := int(xr.ReadUint32())
|
_FoldersSize := int(xr.ReadUint32())
|
||||||
if _FoldersSize < 0 {
|
if _FoldersSize < 0 {
|
||||||
return xdr.ElementSizeExceeded("Folders", _FoldersSize, 0)
|
return xdr.ElementSizeExceeded("Folders", _FoldersSize, 1000000)
|
||||||
|
}
|
||||||
|
if _FoldersSize > 1000000 {
|
||||||
|
return xdr.ElementSizeExceeded("Folders", _FoldersSize, 1000000)
|
||||||
}
|
}
|
||||||
o.Folders = make([]Folder, _FoldersSize)
|
o.Folders = make([]Folder, _FoldersSize)
|
||||||
for i := range o.Folders {
|
for i := range o.Folders {
|
||||||
@@ -697,7 +715,7 @@ Folder Structure:
|
|||||||
|
|
||||||
struct Folder {
|
struct Folder {
|
||||||
string ID<64>;
|
string ID<64>;
|
||||||
Device Devices<>;
|
Device Devices<1000000>;
|
||||||
unsigned int Flags;
|
unsigned int Flags;
|
||||||
Option Options<64>;
|
Option Options<64>;
|
||||||
}
|
}
|
||||||
@@ -733,6 +751,9 @@ func (o Folder) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
|||||||
return xw.Tot(), xdr.ElementSizeExceeded("ID", l, 64)
|
return xw.Tot(), xdr.ElementSizeExceeded("ID", l, 64)
|
||||||
}
|
}
|
||||||
xw.WriteString(o.ID)
|
xw.WriteString(o.ID)
|
||||||
|
if l := len(o.Devices); l > 1000000 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Devices", l, 1000000)
|
||||||
|
}
|
||||||
xw.WriteUint32(uint32(len(o.Devices)))
|
xw.WriteUint32(uint32(len(o.Devices)))
|
||||||
for i := range o.Devices {
|
for i := range o.Devices {
|
||||||
_, err := o.Devices[i].EncodeXDRInto(xw)
|
_, err := o.Devices[i].EncodeXDRInto(xw)
|
||||||
@@ -769,7 +790,10 @@ func (o *Folder) DecodeXDRFrom(xr *xdr.Reader) error {
|
|||||||
o.ID = xr.ReadStringMax(64)
|
o.ID = xr.ReadStringMax(64)
|
||||||
_DevicesSize := int(xr.ReadUint32())
|
_DevicesSize := int(xr.ReadUint32())
|
||||||
if _DevicesSize < 0 {
|
if _DevicesSize < 0 {
|
||||||
return xdr.ElementSizeExceeded("Devices", _DevicesSize, 0)
|
return xdr.ElementSizeExceeded("Devices", _DevicesSize, 1000000)
|
||||||
|
}
|
||||||
|
if _DevicesSize > 1000000 {
|
||||||
|
return xdr.ElementSizeExceeded("Devices", _DevicesSize, 1000000)
|
||||||
}
|
}
|
||||||
o.Devices = make([]Device, _DevicesSize)
|
o.Devices = make([]Device, _DevicesSize)
|
||||||
for i := range o.Devices {
|
for i := range o.Devices {
|
||||||
|
|||||||
+61
-58
@@ -15,7 +15,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BlockSize = 128 * 1024
|
// Data block size (128 KiB)
|
||||||
|
BlockSize = 128 << 10
|
||||||
|
|
||||||
|
// We reject messages larger than this when encountered on the wire. (64 MiB)
|
||||||
|
MaxMessageLen = 64 << 20
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -24,7 +28,6 @@ const (
|
|||||||
messageTypeRequest = 2
|
messageTypeRequest = 2
|
||||||
messageTypeResponse = 3
|
messageTypeResponse = 3
|
||||||
messageTypePing = 4
|
messageTypePing = 4
|
||||||
messageTypePong = 5
|
|
||||||
messageTypeIndexUpdate = 6
|
messageTypeIndexUpdate = 6
|
||||||
messageTypeClose = 7
|
messageTypeClose = 7
|
||||||
)
|
)
|
||||||
@@ -67,13 +70,12 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrClusterHash = fmt.Errorf("configuration error: mismatched cluster hash")
|
ErrClosed = errors.New("connection closed")
|
||||||
ErrClosed = errors.New("connection closed")
|
ErrTimeout = errors.New("read timeout")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Specific variants of empty messages...
|
// Specific variants of empty messages...
|
||||||
type pingMessage struct{ EmptyMessage }
|
type pingMessage struct{ EmptyMessage }
|
||||||
type pongMessage struct{ EmptyMessage }
|
|
||||||
|
|
||||||
type Model interface {
|
type Model interface {
|
||||||
// An index was received from the peer device
|
// An index was received from the peer device
|
||||||
@@ -142,9 +144,11 @@ type isEofer interface {
|
|||||||
IsEOF() bool
|
IsEOF() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
const (
|
||||||
PingTimeout = 30 * time.Second
|
// We make sure to send a message at least this often, by triggering pings.
|
||||||
PingIdleTime = 60 * time.Second
|
PingSendInterval = 90 * time.Second
|
||||||
|
// If we haven't received a message from the other side for this long, close the connection.
|
||||||
|
ReceiveTimeout = 300 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, receiver Model, name string, compress Compression) Connection {
|
func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, receiver Model, name string, compress Compression) Connection {
|
||||||
@@ -176,7 +180,8 @@ func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, receiv
|
|||||||
func (c *rawConnection) Start() {
|
func (c *rawConnection) Start() {
|
||||||
go c.readerLoop()
|
go c.readerLoop()
|
||||||
go c.writerLoop()
|
go c.writerLoop()
|
||||||
go c.pingerLoop()
|
go c.pingSender()
|
||||||
|
go c.pingReceiver()
|
||||||
go c.idGenerator()
|
go c.idGenerator()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,18 +279,7 @@ func (c *rawConnection) ping() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
rc := make(chan asyncResult, 1)
|
return c.send(id, messageTypePing, nil, nil)
|
||||||
c.awaitingMut.Lock()
|
|
||||||
c.awaiting[id] = rc
|
|
||||||
c.awaitingMut.Unlock()
|
|
||||||
|
|
||||||
ok := c.send(id, messageTypePing, nil, nil)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
res, ok := <-rc
|
|
||||||
return ok && res.err == nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *rawConnection) readerLoop() (err error) {
|
func (c *rawConnection) readerLoop() (err error) {
|
||||||
@@ -348,13 +342,7 @@ func (c *rawConnection) readerLoop() (err error) {
|
|||||||
if state != stateReady {
|
if state != stateReady {
|
||||||
return fmt.Errorf("protocol error: ping message in state %d", state)
|
return fmt.Errorf("protocol error: ping message in state %d", state)
|
||||||
}
|
}
|
||||||
c.send(hdr.msgID, messageTypePong, pongMessage{}, nil)
|
// Nothing
|
||||||
|
|
||||||
case pongMessage:
|
|
||||||
if state != stateReady {
|
|
||||||
return fmt.Errorf("protocol error: pong message in state %d", state)
|
|
||||||
}
|
|
||||||
c.handlePong(hdr.msgID)
|
|
||||||
|
|
||||||
case CloseMessage:
|
case CloseMessage:
|
||||||
return errors.New(msg.Reason)
|
return errors.New(msg.Reason)
|
||||||
@@ -383,6 +371,11 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) {
|
|||||||
l.Debugf("read header %v (msglen=%d)", hdr, msglen)
|
l.Debugf("read header %v (msglen=%d)", hdr, msglen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if msglen > MaxMessageLen {
|
||||||
|
err = fmt.Errorf("message length %d exceeds maximum %d", msglen, MaxMessageLen)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if hdr.version != 0 {
|
if hdr.version != 0 {
|
||||||
err = fmt.Errorf("unknown protocol version 0x%x", hdr.version)
|
err = fmt.Errorf("unknown protocol version 0x%x", hdr.version)
|
||||||
return
|
return
|
||||||
@@ -403,7 +396,7 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
msgBuf := c.rdbuf0
|
msgBuf := c.rdbuf0
|
||||||
if hdr.compression {
|
if hdr.compression && msglen > 0 {
|
||||||
c.rdbuf1 = c.rdbuf1[:cap(c.rdbuf1)]
|
c.rdbuf1 = c.rdbuf1[:cap(c.rdbuf1)]
|
||||||
c.rdbuf1, err = lz4.Decode(c.rdbuf1, c.rdbuf0)
|
c.rdbuf1, err = lz4.Decode(c.rdbuf1, c.rdbuf0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -458,9 +451,6 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) {
|
|||||||
case messageTypePing:
|
case messageTypePing:
|
||||||
msg = pingMessage{}
|
msg = pingMessage{}
|
||||||
|
|
||||||
case messageTypePong:
|
|
||||||
msg = pongMessage{}
|
|
||||||
|
|
||||||
case messageTypeClusterConfig:
|
case messageTypeClusterConfig:
|
||||||
var cc ClusterConfigMessage
|
var cc ClusterConfigMessage
|
||||||
err = cc.UnmarshalXDR(msgBuf)
|
err = cc.UnmarshalXDR(msgBuf)
|
||||||
@@ -720,42 +710,55 @@ func (c *rawConnection) idGenerator() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *rawConnection) pingerLoop() {
|
// The pingSender makes sure that we've sent a message within the last
|
||||||
var rc = make(chan bool, 1)
|
// PingSendInterval. If we already have something sent in the last
|
||||||
ticker := time.Tick(PingIdleTime / 2)
|
// PingSendInterval/2, we do nothing. Otherwise we send a ping message. This
|
||||||
|
// results in an effecting ping interval of somewhere between
|
||||||
|
// PingSendInterval/2 and PingSendInterval.
|
||||||
|
func (c *rawConnection) pingSender() {
|
||||||
|
ticker := time.Tick(PingSendInterval / 2)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker:
|
case <-ticker:
|
||||||
if d := time.Since(c.cr.Last()); d < PingIdleTime {
|
d := time.Since(c.cw.Last())
|
||||||
if debug {
|
if d < PingSendInterval/2 {
|
||||||
l.Debugln(c.id, "ping skipped after rd", d)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if d := time.Since(c.cw.Last()); d < PingIdleTime {
|
|
||||||
if debug {
|
if debug {
|
||||||
l.Debugln(c.id, "ping skipped after wr", d)
|
l.Debugln(c.id, "ping skipped after wr", d)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go func() {
|
|
||||||
|
if debug {
|
||||||
|
l.Debugln(c.id, "ping -> after", d)
|
||||||
|
}
|
||||||
|
c.ping()
|
||||||
|
|
||||||
|
case <-c.closed:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The pingReciever checks that we've received a message (any message will do,
|
||||||
|
// but we expect pings in the absence of other messages) within the last
|
||||||
|
// ReceiveTimeout. If not, we close the connection with an ErrTimeout.
|
||||||
|
func (c *rawConnection) pingReceiver() {
|
||||||
|
ticker := time.Tick(ReceiveTimeout / 2)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker:
|
||||||
|
d := time.Since(c.cr.Last())
|
||||||
|
if d > ReceiveTimeout {
|
||||||
if debug {
|
if debug {
|
||||||
l.Debugln(c.id, "ping ->")
|
l.Debugln(c.id, "ping timeout", d)
|
||||||
}
|
}
|
||||||
rc <- c.ping()
|
c.close(ErrTimeout)
|
||||||
}()
|
}
|
||||||
select {
|
|
||||||
case ok := <-rc:
|
if debug {
|
||||||
if debug {
|
l.Debugln(c.id, "last read within", d)
|
||||||
l.Debugln(c.id, "<- pong")
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
c.close(fmt.Errorf("ping failure"))
|
|
||||||
}
|
|
||||||
case <-time.After(PingTimeout):
|
|
||||||
c.close(fmt.Errorf("ping timeout"))
|
|
||||||
case <-c.closed:
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-c.closed:
|
case <-c.closed:
|
||||||
|
|||||||
+6
-94
@@ -6,7 +6,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -82,94 +81,6 @@ func TestPing(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPingErr(t *testing.T) {
|
|
||||||
e := errors.New("something broke")
|
|
||||||
|
|
||||||
for i := 0; i < 32; i++ {
|
|
||||||
for j := 0; j < 32; j++ {
|
|
||||||
m0 := newTestModel()
|
|
||||||
m1 := newTestModel()
|
|
||||||
|
|
||||||
ar, aw := io.Pipe()
|
|
||||||
br, bw := io.Pipe()
|
|
||||||
eaw := &ErrPipe{PipeWriter: *aw, max: i, err: e}
|
|
||||||
ebw := &ErrPipe{PipeWriter: *bw, max: j, err: e}
|
|
||||||
|
|
||||||
c0 := NewConnection(c0ID, ar, ebw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
|
|
||||||
c0.Start()
|
|
||||||
c1 := NewConnection(c1ID, br, eaw, m1, "name", CompressAlways)
|
|
||||||
c1.Start()
|
|
||||||
c0.ClusterConfig(ClusterConfigMessage{})
|
|
||||||
c1.ClusterConfig(ClusterConfigMessage{})
|
|
||||||
|
|
||||||
res := c0.ping()
|
|
||||||
if (i < 8 || j < 8) && res {
|
|
||||||
// This should have resulted in failure, as there is no way an empty ClusterConfig plus a Ping message fits in eight bytes.
|
|
||||||
t.Errorf("Unexpected ping success; i=%d, j=%d", i, j)
|
|
||||||
} else if (i >= 28 && j >= 28) && !res {
|
|
||||||
// This should have worked though, as 28 bytes is plenty for both.
|
|
||||||
t.Errorf("Unexpected ping fail; i=%d, j=%d", i, j)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// func TestRequestResponseErr(t *testing.T) {
|
|
||||||
// e := errors.New("something broke")
|
|
||||||
|
|
||||||
// var pass bool
|
|
||||||
// for i := 0; i < 48; i++ {
|
|
||||||
// for j := 0; j < 38; j++ {
|
|
||||||
// m0 := newTestModel()
|
|
||||||
// m0.data = []byte("response data")
|
|
||||||
// m1 := newTestModel()
|
|
||||||
|
|
||||||
// ar, aw := io.Pipe()
|
|
||||||
// br, bw := io.Pipe()
|
|
||||||
// eaw := &ErrPipe{PipeWriter: *aw, max: i, err: e}
|
|
||||||
// ebw := &ErrPipe{PipeWriter: *bw, max: j, err: e}
|
|
||||||
|
|
||||||
// NewConnection(c0ID, ar, ebw, m0, nil)
|
|
||||||
// c1 := NewConnection(c1ID, br, eaw, m1, nil).(wireFormatConnection).next.(*rawConnection)
|
|
||||||
|
|
||||||
// d, err := c1.Request("default", "tn", 1234, 5678)
|
|
||||||
// if err == e || err == ErrClosed {
|
|
||||||
// t.Logf("Error at %d+%d bytes", i, j)
|
|
||||||
// if !m1.isClosed() {
|
|
||||||
// t.Fatal("c1 not closed")
|
|
||||||
// }
|
|
||||||
// if !m0.isClosed() {
|
|
||||||
// t.Fatal("c0 not closed")
|
|
||||||
// }
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
// }
|
|
||||||
// if string(d) != "response data" {
|
|
||||||
// t.Fatalf("Incorrect response data %q", string(d))
|
|
||||||
// }
|
|
||||||
// if m0.folder != "default" {
|
|
||||||
// t.Fatalf("Incorrect folder %q", m0.folder)
|
|
||||||
// }
|
|
||||||
// if m0.name != "tn" {
|
|
||||||
// t.Fatalf("Incorrect name %q", m0.name)
|
|
||||||
// }
|
|
||||||
// if m0.offset != 1234 {
|
|
||||||
// t.Fatalf("Incorrect offset %d", m0.offset)
|
|
||||||
// }
|
|
||||||
// if m0.size != 5678 {
|
|
||||||
// t.Fatalf("Incorrect size %d", m0.size)
|
|
||||||
// }
|
|
||||||
// t.Logf("Pass at %d+%d bytes", i, j)
|
|
||||||
// pass = true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if !pass {
|
|
||||||
// t.Fatal("Never passed")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
func TestVersionErr(t *testing.T) {
|
func TestVersionErr(t *testing.T) {
|
||||||
m0 := newTestModel()
|
m0 := newTestModel()
|
||||||
m1 := newTestModel()
|
m1 := newTestModel()
|
||||||
@@ -278,11 +189,12 @@ func TestMarshalIndexMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
f := func(m1 IndexMessage) bool {
|
f := func(m1 IndexMessage) bool {
|
||||||
for _, f := range m1.Files {
|
for i, f := range m1.Files {
|
||||||
for i := range f.Blocks {
|
m1.Files[i].CachedSize = 0
|
||||||
f.Blocks[i].Offset = 0
|
for j := range f.Blocks {
|
||||||
if len(f.Blocks[i].Hash) == 0 {
|
f.Blocks[j].Offset = 0
|
||||||
f.Blocks[i].Hash = nil
|
if len(f.Blocks[j].Hash) == 0 {
|
||||||
|
f.Blocks[j].Hash = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
package protocol
|
package protocol
|
||||||
|
|
||||||
|
import "github.com/calmh/xdr"
|
||||||
|
|
||||||
// This stuff is hacked up manually because genxdr doesn't support 'type
|
// This stuff is hacked up manually because genxdr doesn't support 'type
|
||||||
// Vector []Counter' declarations and it was tricky when I tried to add it...
|
// Vector []Counter' declarations and it was tricky when I tried to add it...
|
||||||
|
|
||||||
@@ -28,6 +30,9 @@ func (v Vector) EncodeXDRInto(w xdrWriter) (int, error) {
|
|||||||
// DecodeXDRFrom decodes the XDR objects from the given reader into itself.
|
// DecodeXDRFrom decodes the XDR objects from the given reader into itself.
|
||||||
func (v *Vector) DecodeXDRFrom(r xdrReader) error {
|
func (v *Vector) DecodeXDRFrom(r xdrReader) error {
|
||||||
l := int(r.ReadUint32())
|
l := int(r.ReadUint32())
|
||||||
|
if l > 1e6 {
|
||||||
|
return xdr.ElementSizeExceeded("number of counters", l, 1e6)
|
||||||
|
}
|
||||||
n := make(Vector, l)
|
n := make(Vector, l)
|
||||||
for i := range n {
|
for i := range n {
|
||||||
n[i].ID = r.ReadUint64()
|
n[i].ID = r.ReadUint64()
|
||||||
|
|||||||
+298
@@ -0,0 +1,298 @@
|
|||||||
|
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
|
||||||
|
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
syncthingprotocol "github.com/syncthing/protocol"
|
||||||
|
"github.com/syncthing/relaysrv/protocol"
|
||||||
|
"github.com/syncthing/syncthing/lib/sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProtocolClient struct {
|
||||||
|
URI *url.URL
|
||||||
|
Invitations chan protocol.SessionInvitation
|
||||||
|
|
||||||
|
closeInvitationsOnFinish bool
|
||||||
|
|
||||||
|
config *tls.Config
|
||||||
|
|
||||||
|
timeout time.Duration
|
||||||
|
|
||||||
|
stop chan struct{}
|
||||||
|
stopped chan struct{}
|
||||||
|
|
||||||
|
conn *tls.Conn
|
||||||
|
|
||||||
|
mut sync.RWMutex
|
||||||
|
connected bool
|
||||||
|
latency time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProtocolClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation) *ProtocolClient {
|
||||||
|
closeInvitationsOnFinish := false
|
||||||
|
if invitations == nil {
|
||||||
|
closeInvitationsOnFinish = true
|
||||||
|
invitations = make(chan protocol.SessionInvitation)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ProtocolClient{
|
||||||
|
URI: uri,
|
||||||
|
Invitations: invitations,
|
||||||
|
|
||||||
|
closeInvitationsOnFinish: closeInvitationsOnFinish,
|
||||||
|
|
||||||
|
config: configForCerts(certs),
|
||||||
|
|
||||||
|
timeout: time.Minute * 2,
|
||||||
|
|
||||||
|
stop: make(chan struct{}),
|
||||||
|
stopped: make(chan struct{}),
|
||||||
|
|
||||||
|
mut: sync.NewRWMutex(),
|
||||||
|
connected: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ProtocolClient) Serve() {
|
||||||
|
c.stop = make(chan struct{})
|
||||||
|
c.stopped = make(chan struct{})
|
||||||
|
defer close(c.stopped)
|
||||||
|
|
||||||
|
if err := c.connect(); err != nil {
|
||||||
|
if debug {
|
||||||
|
l.Debugln("Relay connect:", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
l.Debugln(c, "connected", c.conn.RemoteAddr())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.join(); err != nil {
|
||||||
|
c.conn.Close()
|
||||||
|
l.Infoln("Relay join:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.conn.SetDeadline(time.Time{}); err != nil {
|
||||||
|
l.Infoln("Relay set deadline:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
l.Debugln(c, "joined", c.conn.RemoteAddr(), "via", c.conn.LocalAddr())
|
||||||
|
}
|
||||||
|
|
||||||
|
defer c.cleanup()
|
||||||
|
c.mut.Lock()
|
||||||
|
c.connected = true
|
||||||
|
c.mut.Unlock()
|
||||||
|
|
||||||
|
messages := make(chan interface{})
|
||||||
|
errors := make(chan error, 1)
|
||||||
|
|
||||||
|
go messageReader(c.conn, messages, errors)
|
||||||
|
|
||||||
|
timeout := time.NewTimer(c.timeout)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case message := <-messages:
|
||||||
|
timeout.Reset(c.timeout)
|
||||||
|
if debug {
|
||||||
|
log.Printf("%s received message %T", c, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch msg := message.(type) {
|
||||||
|
case protocol.Ping:
|
||||||
|
if err := protocol.WriteMessage(c.conn, protocol.Pong{}); err != nil {
|
||||||
|
l.Infoln("Relay write:", err)
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
l.Debugln(c, "sent pong")
|
||||||
|
}
|
||||||
|
|
||||||
|
case protocol.SessionInvitation:
|
||||||
|
ip := net.IP(msg.Address)
|
||||||
|
if len(ip) == 0 || ip.IsUnspecified() {
|
||||||
|
msg.Address = c.conn.RemoteAddr().(*net.TCPAddr).IP[:]
|
||||||
|
}
|
||||||
|
c.Invitations <- msg
|
||||||
|
|
||||||
|
default:
|
||||||
|
l.Infoln("Relay: protocol error: unexpected message %v", msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-c.stop:
|
||||||
|
if debug {
|
||||||
|
l.Debugln(c, "stopping")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
case err := <-errors:
|
||||||
|
l.Infoln("Relay received:", err)
|
||||||
|
return
|
||||||
|
|
||||||
|
case <-timeout.C:
|
||||||
|
if debug {
|
||||||
|
l.Debugln(c, "timed out")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ProtocolClient) Stop() {
|
||||||
|
if c.stop == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
close(c.stop)
|
||||||
|
<-c.stopped
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ProtocolClient) StatusOK() bool {
|
||||||
|
c.mut.RLock()
|
||||||
|
con := c.connected
|
||||||
|
c.mut.RUnlock()
|
||||||
|
return con
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ProtocolClient) Latency() time.Duration {
|
||||||
|
c.mut.RLock()
|
||||||
|
lat := c.latency
|
||||||
|
c.mut.RUnlock()
|
||||||
|
return lat
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ProtocolClient) String() string {
|
||||||
|
return fmt.Sprintf("ProtocolClient@%p", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ProtocolClient) connect() error {
|
||||||
|
if c.URI.Scheme != "relay" {
|
||||||
|
return fmt.Errorf("Unsupported relay schema:", c.URI.Scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
t0 := time.Now()
|
||||||
|
tcpConn, err := net.Dial("tcp", c.URI.Host)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.mut.Lock()
|
||||||
|
c.latency = time.Since(t0)
|
||||||
|
c.mut.Unlock()
|
||||||
|
|
||||||
|
conn := tls.Client(tcpConn, c.config)
|
||||||
|
if err = conn.Handshake(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := conn.SetDeadline(time.Now().Add(10 * time.Second)); err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := performHandshakeAndValidation(conn, c.URI); err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.conn = conn
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ProtocolClient) cleanup() {
|
||||||
|
if c.closeInvitationsOnFinish {
|
||||||
|
close(c.Invitations)
|
||||||
|
c.Invitations = make(chan protocol.SessionInvitation)
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
l.Debugln(c, "cleaning up")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.mut.Lock()
|
||||||
|
c.connected = false
|
||||||
|
c.mut.Unlock()
|
||||||
|
|
||||||
|
c.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ProtocolClient) join() error {
|
||||||
|
if err := protocol.WriteMessage(c.conn, protocol.JoinRelayRequest{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
message, err := protocol.ReadMessage(c.conn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch msg := message.(type) {
|
||||||
|
case protocol.Response:
|
||||||
|
if msg.Code != 0 {
|
||||||
|
return fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("protocol error: expecting response got %v", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func performHandshakeAndValidation(conn *tls.Conn, uri *url.URL) error {
|
||||||
|
if err := conn.Handshake(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := conn.ConnectionState()
|
||||||
|
if !cs.NegotiatedProtocolIsMutual || cs.NegotiatedProtocol != protocol.ProtocolName {
|
||||||
|
return fmt.Errorf("protocol negotiation error")
|
||||||
|
}
|
||||||
|
|
||||||
|
q := uri.Query()
|
||||||
|
relayIDs := q.Get("id")
|
||||||
|
if relayIDs != "" {
|
||||||
|
relayID, err := syncthingprotocol.DeviceIDFromString(relayIDs)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("relay address contains invalid verification id: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certs := cs.PeerCertificates
|
||||||
|
if cl := len(certs); cl != 1 {
|
||||||
|
return fmt.Errorf("unexpected certificate count: %d", cl)
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteID := syncthingprotocol.NewDeviceID(certs[0].Raw)
|
||||||
|
if remoteID != relayID {
|
||||||
|
return fmt.Errorf("relay id does not match. Expected %v got %v", relayID, remoteID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func messageReader(conn net.Conn, messages chan<- interface{}, errors chan<- error) {
|
||||||
|
for {
|
||||||
|
msg, err := protocol.ReadMessage(conn)
|
||||||
|
if err != nil {
|
||||||
|
errors <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
messages <- msg
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
|
||||||
|
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/calmh/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
debug = strings.Contains(os.Getenv("STTRACE"), "relay") || os.Getenv("STTRACE") == "all"
|
||||||
|
l = logger.DefaultLogger
|
||||||
|
)
|
||||||
+141
@@ -0,0 +1,141 @@
|
|||||||
|
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
|
||||||
|
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
syncthingprotocol "github.com/syncthing/protocol"
|
||||||
|
"github.com/syncthing/relaysrv/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetInvitationFromRelay(uri *url.URL, id syncthingprotocol.DeviceID, certs []tls.Certificate) (protocol.SessionInvitation, error) {
|
||||||
|
if uri.Scheme != "relay" {
|
||||||
|
return protocol.SessionInvitation{}, fmt.Errorf("Unsupported relay scheme:", uri.Scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := tls.Dial("tcp", uri.Host, configForCerts(certs))
|
||||||
|
if err != nil {
|
||||||
|
return protocol.SessionInvitation{}, err
|
||||||
|
}
|
||||||
|
conn.SetDeadline(time.Now().Add(10 * time.Second))
|
||||||
|
|
||||||
|
if err := performHandshakeAndValidation(conn, uri); err != nil {
|
||||||
|
return protocol.SessionInvitation{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
request := protocol.ConnectRequest{
|
||||||
|
ID: id[:],
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := protocol.WriteMessage(conn, request); err != nil {
|
||||||
|
return protocol.SessionInvitation{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
message, err := protocol.ReadMessage(conn)
|
||||||
|
if err != nil {
|
||||||
|
return protocol.SessionInvitation{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch msg := message.(type) {
|
||||||
|
case protocol.Response:
|
||||||
|
return protocol.SessionInvitation{}, fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
|
||||||
|
case protocol.SessionInvitation:
|
||||||
|
if debug {
|
||||||
|
l.Debugln("Received invitation", msg, "via", conn.LocalAddr())
|
||||||
|
}
|
||||||
|
ip := net.IP(msg.Address)
|
||||||
|
if len(ip) == 0 || ip.IsUnspecified() {
|
||||||
|
msg.Address = conn.RemoteAddr().(*net.TCPAddr).IP[:]
|
||||||
|
}
|
||||||
|
return msg, nil
|
||||||
|
default:
|
||||||
|
return protocol.SessionInvitation{}, fmt.Errorf("protocol error: unexpected message %v", msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func JoinSession(invitation protocol.SessionInvitation) (net.Conn, error) {
|
||||||
|
addr := net.JoinHostPort(net.IP(invitation.Address).String(), strconv.Itoa(int(invitation.Port)))
|
||||||
|
|
||||||
|
conn, err := net.Dial("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
request := protocol.JoinSessionRequest{
|
||||||
|
Key: invitation.Key,
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.SetDeadline(time.Now().Add(10 * time.Second))
|
||||||
|
err = protocol.WriteMessage(conn, request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
message, err := protocol.ReadMessage(conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.SetDeadline(time.Time{})
|
||||||
|
|
||||||
|
switch msg := message.(type) {
|
||||||
|
case protocol.Response:
|
||||||
|
if msg.Code != 0 {
|
||||||
|
return nil, fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("protocol error: expecting response got %v", msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRelay(uri *url.URL, certs []tls.Certificate, sleep time.Duration, times int) bool {
|
||||||
|
id := syncthingprotocol.NewDeviceID(certs[0].Certificate[0])
|
||||||
|
invs := make(chan protocol.SessionInvitation, 1)
|
||||||
|
c := NewProtocolClient(uri, certs, invs)
|
||||||
|
go c.Serve()
|
||||||
|
defer func() {
|
||||||
|
close(invs)
|
||||||
|
c.Stop()
|
||||||
|
}()
|
||||||
|
|
||||||
|
for i := 0; i < times; i++ {
|
||||||
|
_, err := GetInvitationFromRelay(uri, id, certs)
|
||||||
|
if err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "Incorrect response code") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
time.Sleep(sleep)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func configForCerts(certs []tls.Certificate) *tls.Config {
|
||||||
|
return &tls.Config{
|
||||||
|
Certificates: certs,
|
||||||
|
NextProtos: []string{protocol.ProtocolName},
|
||||||
|
ClientAuth: tls.RequestClientCert,
|
||||||
|
SessionTicketsDisabled: true,
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
CipherSuites: []uint16{
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
|
||||||
|
|
||||||
|
//go:generate -command genxdr go run ../../syncthing/Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go
|
||||||
|
//go:generate genxdr -o packets_xdr.go packets.go
|
||||||
|
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
syncthingprotocol "github.com/syncthing/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
messageTypePing int32 = iota
|
||||||
|
messageTypePong
|
||||||
|
messageTypeJoinRelayRequest
|
||||||
|
messageTypeJoinSessionRequest
|
||||||
|
messageTypeResponse
|
||||||
|
messageTypeConnectRequest
|
||||||
|
messageTypeSessionInvitation
|
||||||
|
)
|
||||||
|
|
||||||
|
type header struct {
|
||||||
|
magic uint32
|
||||||
|
messageType int32
|
||||||
|
messageLength int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ping struct{}
|
||||||
|
type Pong struct{}
|
||||||
|
type JoinRelayRequest struct{}
|
||||||
|
|
||||||
|
type JoinSessionRequest struct {
|
||||||
|
Key []byte // max:32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Code int32
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnectRequest struct {
|
||||||
|
ID []byte // max:32
|
||||||
|
}
|
||||||
|
|
||||||
|
type SessionInvitation struct {
|
||||||
|
From []byte // max:32
|
||||||
|
Key []byte // max:32
|
||||||
|
Address []byte // max:32
|
||||||
|
Port uint16
|
||||||
|
ServerSocket bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i SessionInvitation) String() string {
|
||||||
|
return fmt.Sprintf("%s@%s", syncthingprotocol.DeviceIDFromBytes(i.From), i.AddressString())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i SessionInvitation) GoString() string {
|
||||||
|
return i.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i SessionInvitation) AddressString() string {
|
||||||
|
return fmt.Sprintf("%s:%d", net.IP(i.Address), i.Port)
|
||||||
|
}
|
||||||
+567
@@ -0,0 +1,567 @@
|
|||||||
|
// ************************************************************
|
||||||
|
// This file is automatically generated by genxdr. Do not edit.
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/calmh/xdr"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
header Structure:
|
||||||
|
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| magic |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| message Type |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| message Length |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
|
||||||
|
struct header {
|
||||||
|
unsigned int magic;
|
||||||
|
int messageType;
|
||||||
|
int messageLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (o header) EncodeXDR(w io.Writer) (int, error) {
|
||||||
|
var xw = xdr.NewWriter(w)
|
||||||
|
return o.EncodeXDRInto(xw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o header) MarshalXDR() ([]byte, error) {
|
||||||
|
return o.AppendXDR(make([]byte, 0, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o header) MustMarshalXDR() []byte {
|
||||||
|
bs, err := o.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o header) AppendXDR(bs []byte) ([]byte, error) {
|
||||||
|
var aw = xdr.AppendWriter(bs)
|
||||||
|
var xw = xdr.NewWriter(&aw)
|
||||||
|
_, err := o.EncodeXDRInto(xw)
|
||||||
|
return []byte(aw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o header) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
xw.WriteUint32(o.magic)
|
||||||
|
xw.WriteUint32(uint32(o.messageType))
|
||||||
|
xw.WriteUint32(uint32(o.messageLength))
|
||||||
|
return xw.Tot(), xw.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *header) DecodeXDR(r io.Reader) error {
|
||||||
|
xr := xdr.NewReader(r)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *header) UnmarshalXDR(bs []byte) error {
|
||||||
|
var br = bytes.NewReader(bs)
|
||||||
|
var xr = xdr.NewReader(br)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *header) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
o.magic = xr.ReadUint32()
|
||||||
|
o.messageType = int32(xr.ReadUint32())
|
||||||
|
o.messageLength = int32(xr.ReadUint32())
|
||||||
|
return xr.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Ping Structure:
|
||||||
|
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
|
||||||
|
struct Ping {
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (o Ping) EncodeXDR(w io.Writer) (int, error) {
|
||||||
|
var xw = xdr.NewWriter(w)
|
||||||
|
return o.EncodeXDRInto(xw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Ping) MarshalXDR() ([]byte, error) {
|
||||||
|
return o.AppendXDR(make([]byte, 0, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Ping) MustMarshalXDR() []byte {
|
||||||
|
bs, err := o.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Ping) AppendXDR(bs []byte) ([]byte, error) {
|
||||||
|
var aw = xdr.AppendWriter(bs)
|
||||||
|
var xw = xdr.NewWriter(&aw)
|
||||||
|
_, err := o.EncodeXDRInto(xw)
|
||||||
|
return []byte(aw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Ping) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
return xw.Tot(), xw.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Ping) DecodeXDR(r io.Reader) error {
|
||||||
|
xr := xdr.NewReader(r)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Ping) UnmarshalXDR(bs []byte) error {
|
||||||
|
var br = bytes.NewReader(bs)
|
||||||
|
var xr = xdr.NewReader(br)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Ping) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
return xr.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Pong Structure:
|
||||||
|
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
|
||||||
|
struct Pong {
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (o Pong) EncodeXDR(w io.Writer) (int, error) {
|
||||||
|
var xw = xdr.NewWriter(w)
|
||||||
|
return o.EncodeXDRInto(xw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Pong) MarshalXDR() ([]byte, error) {
|
||||||
|
return o.AppendXDR(make([]byte, 0, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Pong) MustMarshalXDR() []byte {
|
||||||
|
bs, err := o.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Pong) AppendXDR(bs []byte) ([]byte, error) {
|
||||||
|
var aw = xdr.AppendWriter(bs)
|
||||||
|
var xw = xdr.NewWriter(&aw)
|
||||||
|
_, err := o.EncodeXDRInto(xw)
|
||||||
|
return []byte(aw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Pong) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
return xw.Tot(), xw.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Pong) DecodeXDR(r io.Reader) error {
|
||||||
|
xr := xdr.NewReader(r)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Pong) UnmarshalXDR(bs []byte) error {
|
||||||
|
var br = bytes.NewReader(bs)
|
||||||
|
var xr = xdr.NewReader(br)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Pong) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
return xr.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
JoinRelayRequest Structure:
|
||||||
|
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
|
||||||
|
struct JoinRelayRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (o JoinRelayRequest) EncodeXDR(w io.Writer) (int, error) {
|
||||||
|
var xw = xdr.NewWriter(w)
|
||||||
|
return o.EncodeXDRInto(xw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o JoinRelayRequest) MarshalXDR() ([]byte, error) {
|
||||||
|
return o.AppendXDR(make([]byte, 0, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o JoinRelayRequest) MustMarshalXDR() []byte {
|
||||||
|
bs, err := o.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o JoinRelayRequest) AppendXDR(bs []byte) ([]byte, error) {
|
||||||
|
var aw = xdr.AppendWriter(bs)
|
||||||
|
var xw = xdr.NewWriter(&aw)
|
||||||
|
_, err := o.EncodeXDRInto(xw)
|
||||||
|
return []byte(aw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o JoinRelayRequest) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
return xw.Tot(), xw.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *JoinRelayRequest) DecodeXDR(r io.Reader) error {
|
||||||
|
xr := xdr.NewReader(r)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *JoinRelayRequest) UnmarshalXDR(bs []byte) error {
|
||||||
|
var br = bytes.NewReader(bs)
|
||||||
|
var xr = xdr.NewReader(br)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *JoinRelayRequest) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
return xr.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
JoinSessionRequest Structure:
|
||||||
|
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of Key |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ Key (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
|
||||||
|
struct JoinSessionRequest {
|
||||||
|
opaque Key<32>;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (o JoinSessionRequest) EncodeXDR(w io.Writer) (int, error) {
|
||||||
|
var xw = xdr.NewWriter(w)
|
||||||
|
return o.EncodeXDRInto(xw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o JoinSessionRequest) MarshalXDR() ([]byte, error) {
|
||||||
|
return o.AppendXDR(make([]byte, 0, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o JoinSessionRequest) MustMarshalXDR() []byte {
|
||||||
|
bs, err := o.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o JoinSessionRequest) AppendXDR(bs []byte) ([]byte, error) {
|
||||||
|
var aw = xdr.AppendWriter(bs)
|
||||||
|
var xw = xdr.NewWriter(&aw)
|
||||||
|
_, err := o.EncodeXDRInto(xw)
|
||||||
|
return []byte(aw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o JoinSessionRequest) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
if l := len(o.Key); l > 32 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Key", l, 32)
|
||||||
|
}
|
||||||
|
xw.WriteBytes(o.Key)
|
||||||
|
return xw.Tot(), xw.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *JoinSessionRequest) DecodeXDR(r io.Reader) error {
|
||||||
|
xr := xdr.NewReader(r)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *JoinSessionRequest) UnmarshalXDR(bs []byte) error {
|
||||||
|
var br = bytes.NewReader(bs)
|
||||||
|
var xr = xdr.NewReader(br)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *JoinSessionRequest) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
o.Key = xr.ReadBytesMax(32)
|
||||||
|
return xr.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Response Structure:
|
||||||
|
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Code |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of Message |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ Message (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
|
||||||
|
struct Response {
|
||||||
|
int Code;
|
||||||
|
string Message<>;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (o Response) EncodeXDR(w io.Writer) (int, error) {
|
||||||
|
var xw = xdr.NewWriter(w)
|
||||||
|
return o.EncodeXDRInto(xw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Response) MarshalXDR() ([]byte, error) {
|
||||||
|
return o.AppendXDR(make([]byte, 0, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Response) MustMarshalXDR() []byte {
|
||||||
|
bs, err := o.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Response) AppendXDR(bs []byte) ([]byte, error) {
|
||||||
|
var aw = xdr.AppendWriter(bs)
|
||||||
|
var xw = xdr.NewWriter(&aw)
|
||||||
|
_, err := o.EncodeXDRInto(xw)
|
||||||
|
return []byte(aw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Response) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
xw.WriteUint32(uint32(o.Code))
|
||||||
|
xw.WriteString(o.Message)
|
||||||
|
return xw.Tot(), xw.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Response) DecodeXDR(r io.Reader) error {
|
||||||
|
xr := xdr.NewReader(r)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Response) UnmarshalXDR(bs []byte) error {
|
||||||
|
var br = bytes.NewReader(bs)
|
||||||
|
var xr = xdr.NewReader(br)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Response) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
o.Code = int32(xr.ReadUint32())
|
||||||
|
o.Message = xr.ReadString()
|
||||||
|
return xr.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
ConnectRequest Structure:
|
||||||
|
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of ID |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ ID (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
|
||||||
|
struct ConnectRequest {
|
||||||
|
opaque ID<32>;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (o ConnectRequest) EncodeXDR(w io.Writer) (int, error) {
|
||||||
|
var xw = xdr.NewWriter(w)
|
||||||
|
return o.EncodeXDRInto(xw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ConnectRequest) MarshalXDR() ([]byte, error) {
|
||||||
|
return o.AppendXDR(make([]byte, 0, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ConnectRequest) MustMarshalXDR() []byte {
|
||||||
|
bs, err := o.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ConnectRequest) AppendXDR(bs []byte) ([]byte, error) {
|
||||||
|
var aw = xdr.AppendWriter(bs)
|
||||||
|
var xw = xdr.NewWriter(&aw)
|
||||||
|
_, err := o.EncodeXDRInto(xw)
|
||||||
|
return []byte(aw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ConnectRequest) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
if l := len(o.ID); l > 32 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("ID", l, 32)
|
||||||
|
}
|
||||||
|
xw.WriteBytes(o.ID)
|
||||||
|
return xw.Tot(), xw.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ConnectRequest) DecodeXDR(r io.Reader) error {
|
||||||
|
xr := xdr.NewReader(r)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ConnectRequest) UnmarshalXDR(bs []byte) error {
|
||||||
|
var br = bytes.NewReader(bs)
|
||||||
|
var xr = xdr.NewReader(br)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ConnectRequest) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
o.ID = xr.ReadBytesMax(32)
|
||||||
|
return xr.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
SessionInvitation Structure:
|
||||||
|
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of From |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ From (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of Key |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ Key (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of Address |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ Address (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| 0x0000 | Port |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Server Socket (V=0 or 1) |V|
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
|
||||||
|
struct SessionInvitation {
|
||||||
|
opaque From<32>;
|
||||||
|
opaque Key<32>;
|
||||||
|
opaque Address<32>;
|
||||||
|
unsigned int Port;
|
||||||
|
bool ServerSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (o SessionInvitation) EncodeXDR(w io.Writer) (int, error) {
|
||||||
|
var xw = xdr.NewWriter(w)
|
||||||
|
return o.EncodeXDRInto(xw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o SessionInvitation) MarshalXDR() ([]byte, error) {
|
||||||
|
return o.AppendXDR(make([]byte, 0, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o SessionInvitation) MustMarshalXDR() []byte {
|
||||||
|
bs, err := o.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o SessionInvitation) AppendXDR(bs []byte) ([]byte, error) {
|
||||||
|
var aw = xdr.AppendWriter(bs)
|
||||||
|
var xw = xdr.NewWriter(&aw)
|
||||||
|
_, err := o.EncodeXDRInto(xw)
|
||||||
|
return []byte(aw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o SessionInvitation) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
if l := len(o.From); l > 32 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("From", l, 32)
|
||||||
|
}
|
||||||
|
xw.WriteBytes(o.From)
|
||||||
|
if l := len(o.Key); l > 32 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Key", l, 32)
|
||||||
|
}
|
||||||
|
xw.WriteBytes(o.Key)
|
||||||
|
if l := len(o.Address); l > 32 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Address", l, 32)
|
||||||
|
}
|
||||||
|
xw.WriteBytes(o.Address)
|
||||||
|
xw.WriteUint16(o.Port)
|
||||||
|
xw.WriteBool(o.ServerSocket)
|
||||||
|
return xw.Tot(), xw.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *SessionInvitation) DecodeXDR(r io.Reader) error {
|
||||||
|
xr := xdr.NewReader(r)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *SessionInvitation) UnmarshalXDR(bs []byte) error {
|
||||||
|
var br = bytes.NewReader(bs)
|
||||||
|
var xr = xdr.NewReader(br)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *SessionInvitation) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
o.From = xr.ReadBytesMax(32)
|
||||||
|
o.Key = xr.ReadBytesMax(32)
|
||||||
|
o.Address = xr.ReadBytesMax(32)
|
||||||
|
o.Port = xr.ReadUint16()
|
||||||
|
o.ServerSocket = xr.ReadBool()
|
||||||
|
return xr.Error()
|
||||||
|
}
|
||||||
+114
@@ -0,0 +1,114 @@
|
|||||||
|
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
|
||||||
|
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
magic = 0x9E79BC40
|
||||||
|
ProtocolName = "bep-relay"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ResponseSuccess = Response{0, "success"}
|
||||||
|
ResponseNotFound = Response{1, "not found"}
|
||||||
|
ResponseAlreadyConnected = Response{2, "already connected"}
|
||||||
|
ResponseInternalError = Response{99, "internal error"}
|
||||||
|
ResponseUnexpectedMessage = Response{100, "unexpected message"}
|
||||||
|
)
|
||||||
|
|
||||||
|
func WriteMessage(w io.Writer, message interface{}) error {
|
||||||
|
header := header{
|
||||||
|
magic: magic,
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload []byte
|
||||||
|
var err error
|
||||||
|
|
||||||
|
switch msg := message.(type) {
|
||||||
|
case Ping:
|
||||||
|
payload, err = msg.MarshalXDR()
|
||||||
|
header.messageType = messageTypePing
|
||||||
|
case Pong:
|
||||||
|
payload, err = msg.MarshalXDR()
|
||||||
|
header.messageType = messageTypePong
|
||||||
|
case JoinRelayRequest:
|
||||||
|
payload, err = msg.MarshalXDR()
|
||||||
|
header.messageType = messageTypeJoinRelayRequest
|
||||||
|
case JoinSessionRequest:
|
||||||
|
payload, err = msg.MarshalXDR()
|
||||||
|
header.messageType = messageTypeJoinSessionRequest
|
||||||
|
case Response:
|
||||||
|
payload, err = msg.MarshalXDR()
|
||||||
|
header.messageType = messageTypeResponse
|
||||||
|
case ConnectRequest:
|
||||||
|
payload, err = msg.MarshalXDR()
|
||||||
|
header.messageType = messageTypeConnectRequest
|
||||||
|
case SessionInvitation:
|
||||||
|
payload, err = msg.MarshalXDR()
|
||||||
|
header.messageType = messageTypeSessionInvitation
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("Unknown message type")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
header.messageLength = int32(len(payload))
|
||||||
|
|
||||||
|
headerpayload, err := header.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(append(headerpayload, payload...))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadMessage(r io.Reader) (interface{}, error) {
|
||||||
|
var header header
|
||||||
|
if err := header.DecodeXDR(r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.magic != magic {
|
||||||
|
return nil, fmt.Errorf("magic mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch header.messageType {
|
||||||
|
case messageTypePing:
|
||||||
|
var msg Ping
|
||||||
|
err := msg.DecodeXDR(r)
|
||||||
|
return msg, err
|
||||||
|
case messageTypePong:
|
||||||
|
var msg Pong
|
||||||
|
err := msg.DecodeXDR(r)
|
||||||
|
return msg, err
|
||||||
|
case messageTypeJoinRelayRequest:
|
||||||
|
var msg JoinRelayRequest
|
||||||
|
err := msg.DecodeXDR(r)
|
||||||
|
return msg, err
|
||||||
|
case messageTypeJoinSessionRequest:
|
||||||
|
var msg JoinSessionRequest
|
||||||
|
err := msg.DecodeXDR(r)
|
||||||
|
return msg, err
|
||||||
|
case messageTypeResponse:
|
||||||
|
var msg Response
|
||||||
|
err := msg.DecodeXDR(r)
|
||||||
|
return msg, err
|
||||||
|
case messageTypeConnectRequest:
|
||||||
|
var msg ConnectRequest
|
||||||
|
err := msg.DecodeXDR(r)
|
||||||
|
return msg, err
|
||||||
|
case messageTypeSessionInvitation:
|
||||||
|
var msg SessionInvitation
|
||||||
|
err := msg.DecodeXDR(r)
|
||||||
|
return msg, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("Unknown message type")
|
||||||
|
}
|
||||||
+1
@@ -201,6 +201,7 @@ func (p *BufferPool) String() string {
|
|||||||
|
|
||||||
func (p *BufferPool) drain() {
|
func (p *BufferPool) drain() {
|
||||||
ticker := time.NewTicker(2 * time.Second)
|
ticker := time.NewTicker(2 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
|
|||||||
+2
-8
@@ -6,10 +6,8 @@ Suture
|
|||||||
Suture provides Erlang-ish supervisor trees for Go. "Supervisor trees" ->
|
Suture provides Erlang-ish supervisor trees for Go. "Supervisor trees" ->
|
||||||
"sutree" -> "suture" -> holds your code together when it's trying to die.
|
"sutree" -> "suture" -> holds your code together when it's trying to die.
|
||||||
|
|
||||||
This is intended to be a production-quality library going into code that I
|
This library has hit maturity, and isn't expected to be changed
|
||||||
will be very early on the phone tree to support when it goes down. However,
|
radically. This can also be imported via gopkg.in/thejerf/suture.v1 .
|
||||||
it has not been deployed into something quite that serious yet. (I will
|
|
||||||
update this statement when that changes.)
|
|
||||||
|
|
||||||
It is intended to deal gracefully with the real failure cases that can
|
It is intended to deal gracefully with the real failure cases that can
|
||||||
occur with supervision trees (such as burning all your CPU time endlessly
|
occur with supervision trees (such as burning all your CPU time endlessly
|
||||||
@@ -24,10 +22,6 @@ This module is fully covered with [godoc](http://godoc.org/github.com/thejerf/su
|
|||||||
including an example, usage, and everything else you might expect from a
|
including an example, usage, and everything else you might expect from a
|
||||||
README.md on GitHub. (DRY.)
|
README.md on GitHub. (DRY.)
|
||||||
|
|
||||||
This is not currently tagged with particular git tags for Go as this is
|
|
||||||
currently considered to be alpha code. As I move this into production and
|
|
||||||
feel more confident about it, I'll give it relevant tags.
|
|
||||||
|
|
||||||
Code Signing
|
Code Signing
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|||||||
+181
@@ -0,0 +1,181 @@
|
|||||||
|
// go generate gen.go
|
||||||
|
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
|
||||||
|
package iana
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Protocol Numbers, Updated: 2015-06-23
|
||||||
|
const (
|
||||||
|
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
|
||||||
|
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
|
||||||
|
ProtocolICMP = 1 // Internet Control Message
|
||||||
|
ProtocolIGMP = 2 // Internet Group Management
|
||||||
|
ProtocolGGP = 3 // Gateway-to-Gateway
|
||||||
|
ProtocolIPv4 = 4 // IPv4 encapsulation
|
||||||
|
ProtocolST = 5 // Stream
|
||||||
|
ProtocolTCP = 6 // Transmission Control
|
||||||
|
ProtocolCBT = 7 // CBT
|
||||||
|
ProtocolEGP = 8 // Exterior Gateway Protocol
|
||||||
|
ProtocolIGP = 9 // any private interior gateway (used by Cisco for their IGRP)
|
||||||
|
ProtocolBBNRCCMON = 10 // BBN RCC Monitoring
|
||||||
|
ProtocolNVPII = 11 // Network Voice Protocol
|
||||||
|
ProtocolPUP = 12 // PUP
|
||||||
|
ProtocolARGUS = 13 // ARGUS
|
||||||
|
ProtocolEMCON = 14 // EMCON
|
||||||
|
ProtocolXNET = 15 // Cross Net Debugger
|
||||||
|
ProtocolCHAOS = 16 // Chaos
|
||||||
|
ProtocolUDP = 17 // User Datagram
|
||||||
|
ProtocolMUX = 18 // Multiplexing
|
||||||
|
ProtocolDCNMEAS = 19 // DCN Measurement Subsystems
|
||||||
|
ProtocolHMP = 20 // Host Monitoring
|
||||||
|
ProtocolPRM = 21 // Packet Radio Measurement
|
||||||
|
ProtocolXNSIDP = 22 // XEROX NS IDP
|
||||||
|
ProtocolTRUNK1 = 23 // Trunk-1
|
||||||
|
ProtocolTRUNK2 = 24 // Trunk-2
|
||||||
|
ProtocolLEAF1 = 25 // Leaf-1
|
||||||
|
ProtocolLEAF2 = 26 // Leaf-2
|
||||||
|
ProtocolRDP = 27 // Reliable Data Protocol
|
||||||
|
ProtocolIRTP = 28 // Internet Reliable Transaction
|
||||||
|
ProtocolISOTP4 = 29 // ISO Transport Protocol Class 4
|
||||||
|
ProtocolNETBLT = 30 // Bulk Data Transfer Protocol
|
||||||
|
ProtocolMFENSP = 31 // MFE Network Services Protocol
|
||||||
|
ProtocolMERITINP = 32 // MERIT Internodal Protocol
|
||||||
|
ProtocolDCCP = 33 // Datagram Congestion Control Protocol
|
||||||
|
Protocol3PC = 34 // Third Party Connect Protocol
|
||||||
|
ProtocolIDPR = 35 // Inter-Domain Policy Routing Protocol
|
||||||
|
ProtocolXTP = 36 // XTP
|
||||||
|
ProtocolDDP = 37 // Datagram Delivery Protocol
|
||||||
|
ProtocolIDPRCMTP = 38 // IDPR Control Message Transport Proto
|
||||||
|
ProtocolTPPP = 39 // TP++ Transport Protocol
|
||||||
|
ProtocolIL = 40 // IL Transport Protocol
|
||||||
|
ProtocolIPv6 = 41 // IPv6 encapsulation
|
||||||
|
ProtocolSDRP = 42 // Source Demand Routing Protocol
|
||||||
|
ProtocolIPv6Route = 43 // Routing Header for IPv6
|
||||||
|
ProtocolIPv6Frag = 44 // Fragment Header for IPv6
|
||||||
|
ProtocolIDRP = 45 // Inter-Domain Routing Protocol
|
||||||
|
ProtocolRSVP = 46 // Reservation Protocol
|
||||||
|
ProtocolGRE = 47 // Generic Routing Encapsulation
|
||||||
|
ProtocolDSR = 48 // Dynamic Source Routing Protocol
|
||||||
|
ProtocolBNA = 49 // BNA
|
||||||
|
ProtocolESP = 50 // Encap Security Payload
|
||||||
|
ProtocolAH = 51 // Authentication Header
|
||||||
|
ProtocolINLSP = 52 // Integrated Net Layer Security TUBA
|
||||||
|
ProtocolNARP = 54 // NBMA Address Resolution Protocol
|
||||||
|
ProtocolMOBILE = 55 // IP Mobility
|
||||||
|
ProtocolTLSP = 56 // Transport Layer Security Protocol using Kryptonet key management
|
||||||
|
ProtocolSKIP = 57 // SKIP
|
||||||
|
ProtocolIPv6ICMP = 58 // ICMP for IPv6
|
||||||
|
ProtocolIPv6NoNxt = 59 // No Next Header for IPv6
|
||||||
|
ProtocolIPv6Opts = 60 // Destination Options for IPv6
|
||||||
|
ProtocolCFTP = 62 // CFTP
|
||||||
|
ProtocolSATEXPAK = 64 // SATNET and Backroom EXPAK
|
||||||
|
ProtocolKRYPTOLAN = 65 // Kryptolan
|
||||||
|
ProtocolRVD = 66 // MIT Remote Virtual Disk Protocol
|
||||||
|
ProtocolIPPC = 67 // Internet Pluribus Packet Core
|
||||||
|
ProtocolSATMON = 69 // SATNET Monitoring
|
||||||
|
ProtocolVISA = 70 // VISA Protocol
|
||||||
|
ProtocolIPCV = 71 // Internet Packet Core Utility
|
||||||
|
ProtocolCPNX = 72 // Computer Protocol Network Executive
|
||||||
|
ProtocolCPHB = 73 // Computer Protocol Heart Beat
|
||||||
|
ProtocolWSN = 74 // Wang Span Network
|
||||||
|
ProtocolPVP = 75 // Packet Video Protocol
|
||||||
|
ProtocolBRSATMON = 76 // Backroom SATNET Monitoring
|
||||||
|
ProtocolSUNND = 77 // SUN ND PROTOCOL-Temporary
|
||||||
|
ProtocolWBMON = 78 // WIDEBAND Monitoring
|
||||||
|
ProtocolWBEXPAK = 79 // WIDEBAND EXPAK
|
||||||
|
ProtocolISOIP = 80 // ISO Internet Protocol
|
||||||
|
ProtocolVMTP = 81 // VMTP
|
||||||
|
ProtocolSECUREVMTP = 82 // SECURE-VMTP
|
||||||
|
ProtocolVINES = 83 // VINES
|
||||||
|
ProtocolTTP = 84 // Transaction Transport Protocol
|
||||||
|
ProtocolIPTM = 84 // Internet Protocol Traffic Manager
|
||||||
|
ProtocolNSFNETIGP = 85 // NSFNET-IGP
|
||||||
|
ProtocolDGP = 86 // Dissimilar Gateway Protocol
|
||||||
|
ProtocolTCF = 87 // TCF
|
||||||
|
ProtocolEIGRP = 88 // EIGRP
|
||||||
|
ProtocolOSPFIGP = 89 // OSPFIGP
|
||||||
|
ProtocolSpriteRPC = 90 // Sprite RPC Protocol
|
||||||
|
ProtocolLARP = 91 // Locus Address Resolution Protocol
|
||||||
|
ProtocolMTP = 92 // Multicast Transport Protocol
|
||||||
|
ProtocolAX25 = 93 // AX.25 Frames
|
||||||
|
ProtocolIPIP = 94 // IP-within-IP Encapsulation Protocol
|
||||||
|
ProtocolSCCSP = 96 // Semaphore Communications Sec. Pro.
|
||||||
|
ProtocolETHERIP = 97 // Ethernet-within-IP Encapsulation
|
||||||
|
ProtocolENCAP = 98 // Encapsulation Header
|
||||||
|
ProtocolGMTP = 100 // GMTP
|
||||||
|
ProtocolIFMP = 101 // Ipsilon Flow Management Protocol
|
||||||
|
ProtocolPNNI = 102 // PNNI over IP
|
||||||
|
ProtocolPIM = 103 // Protocol Independent Multicast
|
||||||
|
ProtocolARIS = 104 // ARIS
|
||||||
|
ProtocolSCPS = 105 // SCPS
|
||||||
|
ProtocolQNX = 106 // QNX
|
||||||
|
ProtocolAN = 107 // Active Networks
|
||||||
|
ProtocolIPComp = 108 // IP Payload Compression Protocol
|
||||||
|
ProtocolSNP = 109 // Sitara Networks Protocol
|
||||||
|
ProtocolCompaqPeer = 110 // Compaq Peer Protocol
|
||||||
|
ProtocolIPXinIP = 111 // IPX in IP
|
||||||
|
ProtocolVRRP = 112 // Virtual Router Redundancy Protocol
|
||||||
|
ProtocolPGM = 113 // PGM Reliable Transport Protocol
|
||||||
|
ProtocolL2TP = 115 // Layer Two Tunneling Protocol
|
||||||
|
ProtocolDDX = 116 // D-II Data Exchange (DDX)
|
||||||
|
ProtocolIATP = 117 // Interactive Agent Transfer Protocol
|
||||||
|
ProtocolSTP = 118 // Schedule Transfer Protocol
|
||||||
|
ProtocolSRP = 119 // SpectraLink Radio Protocol
|
||||||
|
ProtocolUTI = 120 // UTI
|
||||||
|
ProtocolSMP = 121 // Simple Message Protocol
|
||||||
|
ProtocolPTP = 123 // Performance Transparency Protocol
|
||||||
|
ProtocolISIS = 124 // ISIS over IPv4
|
||||||
|
ProtocolFIRE = 125 // FIRE
|
||||||
|
ProtocolCRTP = 126 // Combat Radio Transport Protocol
|
||||||
|
ProtocolCRUDP = 127 // Combat Radio User Datagram
|
||||||
|
ProtocolSSCOPMCE = 128 // SSCOPMCE
|
||||||
|
ProtocolIPLT = 129 // IPLT
|
||||||
|
ProtocolSPS = 130 // Secure Packet Shield
|
||||||
|
ProtocolPIPE = 131 // Private IP Encapsulation within IP
|
||||||
|
ProtocolSCTP = 132 // Stream Control Transmission Protocol
|
||||||
|
ProtocolFC = 133 // Fibre Channel
|
||||||
|
ProtocolRSVPE2EIGNORE = 134 // RSVP-E2E-IGNORE
|
||||||
|
ProtocolMobilityHeader = 135 // Mobility Header
|
||||||
|
ProtocolUDPLite = 136 // UDPLite
|
||||||
|
ProtocolMPLSinIP = 137 // MPLS-in-IP
|
||||||
|
ProtocolMANET = 138 // MANET Protocols
|
||||||
|
ProtocolHIP = 139 // Host Identity Protocol
|
||||||
|
ProtocolShim6 = 140 // Shim6 Protocol
|
||||||
|
ProtocolWESP = 141 // Wrapped Encapsulating Security Payload
|
||||||
|
ProtocolROHC = 142 // Robust Header Compression
|
||||||
|
ProtocolReserved = 255 // Reserved
|
||||||
|
)
|
||||||
+293
@@ -0,0 +1,293 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
//go:generate go run gen.go
|
||||||
|
|
||||||
|
// This program generates internet protocol constants and tables by
|
||||||
|
// reading IANA protocol registries.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
|
||||||
|
parseProtocolNumbers,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var bb bytes.Buffer
|
||||||
|
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 // import "golang.org/x/net/internal/iana"`+"\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)
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var pn protocolNumbers
|
||||||
|
if err := dec.Decode(&pn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prs := pn.escape()
|
||||||
|
prs = append([]canonProtocolRecord{{
|
||||||
|
Name: "IP",
|
||||||
|
Descr: "IPv4 encapsulation, pseudo protocol number",
|
||||||
|
Value: 0,
|
||||||
|
}}, prs...)
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, pr := range prs {
|
||||||
|
if pr.Name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
|
||||||
|
s := pr.Descr
|
||||||
|
if s == "" {
|
||||||
|
s = pr.OrigName
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "// %s\n", s)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type protocolNumbers struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
RegTitle string `xml:"registry>title"`
|
||||||
|
Note string `xml:"registry>note"`
|
||||||
|
Records []struct {
|
||||||
|
Value string `xml:"value"`
|
||||||
|
Name string `xml:"name"`
|
||||||
|
Descr string `xml:"description"`
|
||||||
|
} `xml:"registry>record"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonProtocolRecord struct {
|
||||||
|
OrigName string
|
||||||
|
Name string
|
||||||
|
Descr string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pn *protocolNumbers) escape() []canonProtocolRecord {
|
||||||
|
prs := make([]canonProtocolRecord, len(pn.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"-in-", "in",
|
||||||
|
"-within-", "within",
|
||||||
|
"-over-", "over",
|
||||||
|
"+", "P",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
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 {
|
||||||
|
case "ISIS over IPv4":
|
||||||
|
prs[i].Name = "ISIS"
|
||||||
|
case "manet":
|
||||||
|
prs[i].Name = "MANET"
|
||||||
|
default:
|
||||||
|
prs[i].Name = sr.Replace(s)
|
||||||
|
}
|
||||||
|
ss := strings.Split(pr.Descr, "\n")
|
||||||
|
for i := range ss {
|
||||||
|
ss[i] = strings.TrimSpace(ss[i])
|
||||||
|
}
|
||||||
|
if len(ss) > 1 {
|
||||||
|
prs[i].Descr = strings.Join(ss, " ")
|
||||||
|
} else {
|
||||||
|
prs[i].Descr = ss[0]
|
||||||
|
}
|
||||||
|
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||||
|
}
|
||||||
|
return prs
|
||||||
|
}
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
// 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 (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errMissingAddress = errors.New("missing address")
|
||||||
|
errInvalidConnType = errors.New("invalid conn type")
|
||||||
|
errNoSuchInterface = errors.New("no such interface")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Note that RFC 3542 obsoletes RFC 2292 but OS X Snow Leopard and the
|
||||||
|
// former still support RFC 2292 only. Please be aware that almost
|
||||||
|
// all protocol implementations prohibit using a combination of RFC
|
||||||
|
// 2292 and RFC 3542 for some practical reasons.
|
||||||
|
|
||||||
|
type rawOpt struct {
|
||||||
|
sync.RWMutex
|
||||||
|
cflags ControlFlags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rawOpt) set(f ControlFlags) { c.cflags |= f }
|
||||||
|
func (c *rawOpt) clear(f ControlFlags) { c.cflags &^= f }
|
||||||
|
func (c *rawOpt) isset(f ControlFlags) bool { return c.cflags&f != 0 }
|
||||||
|
|
||||||
|
// A ControlFlags represents per packet basis IP-level socket option
|
||||||
|
// control flags.
|
||||||
|
type ControlFlags uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
FlagTrafficClass ControlFlags = 1 << iota // pass the traffic class on the received packet
|
||||||
|
FlagHopLimit // pass the hop limit on the received packet
|
||||||
|
FlagSrc // pass the source address on the received packet
|
||||||
|
FlagDst // pass the destination address on the received packet
|
||||||
|
FlagInterface // pass the interface index on the received packet
|
||||||
|
FlagPathMTU // pass the path MTU on the received packet path
|
||||||
|
)
|
||||||
|
|
||||||
|
const flagPacketInfo = FlagDst | FlagInterface
|
||||||
|
|
||||||
|
// A ControlMessage represents per packet basis IP-level socket
|
||||||
|
// options.
|
||||||
|
type ControlMessage struct {
|
||||||
|
// Receiving socket options: SetControlMessage allows to
|
||||||
|
// receive the options from the protocol stack using ReadFrom
|
||||||
|
// method of PacketConn.
|
||||||
|
//
|
||||||
|
// Specifying socket options: ControlMessage for WriteTo
|
||||||
|
// method of PacketConn allows to send the options to the
|
||||||
|
// protocol stack.
|
||||||
|
//
|
||||||
|
TrafficClass int // traffic class, must be 1 <= value <= 255 when specifying
|
||||||
|
HopLimit int // hop limit, must be 1 <= value <= 255 when specifying
|
||||||
|
Src net.IP // source address, specifying only
|
||||||
|
Dst net.IP // destination address, receiving only
|
||||||
|
IfIndex int // interface index, must be 1 <= value when specifying
|
||||||
|
NextHop net.IP // next hop address, specifying only
|
||||||
|
MTU int // path MTU, receiving only
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cm *ControlMessage) String() string {
|
||||||
|
if cm == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("tclass: %#x, hoplim: %v, src: %v, dst: %v, ifindex: %v, nexthop: %v, mtu: %v", cm.TrafficClass, cm.HopLimit, cm.Src, cm.Dst, cm.IfIndex, cm.NextHop, cm.MTU)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ancillary data socket options
|
||||||
|
const (
|
||||||
|
ctlTrafficClass = iota // header field
|
||||||
|
ctlHopLimit // header field
|
||||||
|
ctlPacketInfo // inbound or outbound packet path
|
||||||
|
ctlNextHop // nexthop
|
||||||
|
ctlPathMTU // path mtu
|
||||||
|
ctlMax
|
||||||
|
)
|
||||||
|
|
||||||
|
// A ctlOpt represents a binding for ancillary data socket option.
|
||||||
|
type ctlOpt struct {
|
||||||
|
name int // option name, must be equal or greater than 1
|
||||||
|
length int // option length
|
||||||
|
marshal func([]byte, *ControlMessage) []byte
|
||||||
|
parse func(*ControlMessage, []byte)
|
||||||
|
}
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
// 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 (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func marshal2292HopLimit(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIPv6
|
||||||
|
m.Type = sysIPV6_2292HOPLIMIT
|
||||||
|
m.SetLen(syscall.CmsgLen(4))
|
||||||
|
if cm != nil {
|
||||||
|
data := b[syscall.CmsgLen(0):]
|
||||||
|
// TODO(mikio): fix potential misaligned memory access
|
||||||
|
*(*int32)(unsafe.Pointer(&data[:4][0])) = int32(cm.HopLimit)
|
||||||
|
}
|
||||||
|
return b[syscall.CmsgSpace(4):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshal2292PacketInfo(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIPv6
|
||||||
|
m.Type = sysIPV6_2292PKTINFO
|
||||||
|
m.SetLen(syscall.CmsgLen(sysSizeofInet6Pktinfo))
|
||||||
|
if cm != nil {
|
||||||
|
pi := (*sysInet6Pktinfo)(unsafe.Pointer(&b[syscall.CmsgLen(0)]))
|
||||||
|
if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
|
||||||
|
copy(pi.Addr[:], ip)
|
||||||
|
}
|
||||||
|
if cm.IfIndex > 0 {
|
||||||
|
pi.setIfindex(cm.IfIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b[syscall.CmsgSpace(sysSizeofInet6Pktinfo):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshal2292NextHop(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIPv6
|
||||||
|
m.Type = sysIPV6_2292NEXTHOP
|
||||||
|
m.SetLen(syscall.CmsgLen(sysSizeofSockaddrInet6))
|
||||||
|
if cm != nil {
|
||||||
|
sa := (*sysSockaddrInet6)(unsafe.Pointer(&b[syscall.CmsgLen(0)]))
|
||||||
|
sa.setSockaddr(cm.NextHop, cm.IfIndex)
|
||||||
|
}
|
||||||
|
return b[syscall.CmsgSpace(sysSizeofSockaddrInet6):]
|
||||||
|
}
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
// 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"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func marshalTrafficClass(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIPv6
|
||||||
|
m.Type = sysIPV6_TCLASS
|
||||||
|
m.SetLen(syscall.CmsgLen(4))
|
||||||
|
if cm != nil {
|
||||||
|
data := b[syscall.CmsgLen(0):]
|
||||||
|
// TODO(mikio): fix potential misaligned memory access
|
||||||
|
*(*int32)(unsafe.Pointer(&data[:4][0])) = int32(cm.TrafficClass)
|
||||||
|
}
|
||||||
|
return b[syscall.CmsgSpace(4):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTrafficClass(cm *ControlMessage, b []byte) {
|
||||||
|
// TODO(mikio): fix potential misaligned memory access
|
||||||
|
cm.TrafficClass = int(*(*int32)(unsafe.Pointer(&b[:4][0])))
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalHopLimit(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIPv6
|
||||||
|
m.Type = sysIPV6_HOPLIMIT
|
||||||
|
m.SetLen(syscall.CmsgLen(4))
|
||||||
|
if cm != nil {
|
||||||
|
data := b[syscall.CmsgLen(0):]
|
||||||
|
// TODO(mikio): fix potential misaligned memory access
|
||||||
|
*(*int32)(unsafe.Pointer(&data[:4][0])) = int32(cm.HopLimit)
|
||||||
|
}
|
||||||
|
return b[syscall.CmsgSpace(4):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseHopLimit(cm *ControlMessage, b []byte) {
|
||||||
|
// TODO(mikio): fix potential misaligned memory access
|
||||||
|
cm.HopLimit = int(*(*int32)(unsafe.Pointer(&b[:4][0])))
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIPv6
|
||||||
|
m.Type = sysIPV6_PKTINFO
|
||||||
|
m.SetLen(syscall.CmsgLen(sysSizeofInet6Pktinfo))
|
||||||
|
if cm != nil {
|
||||||
|
pi := (*sysInet6Pktinfo)(unsafe.Pointer(&b[syscall.CmsgLen(0)]))
|
||||||
|
if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
|
||||||
|
copy(pi.Addr[:], ip)
|
||||||
|
}
|
||||||
|
if cm.IfIndex > 0 {
|
||||||
|
pi.setIfindex(cm.IfIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b[syscall.CmsgSpace(sysSizeofInet6Pktinfo):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parsePacketInfo(cm *ControlMessage, b []byte) {
|
||||||
|
pi := (*sysInet6Pktinfo)(unsafe.Pointer(&b[0]))
|
||||||
|
cm.Dst = pi.Addr[:]
|
||||||
|
cm.IfIndex = int(pi.Ifindex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalNextHop(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIPv6
|
||||||
|
m.Type = sysIPV6_NEXTHOP
|
||||||
|
m.SetLen(syscall.CmsgLen(sysSizeofSockaddrInet6))
|
||||||
|
if cm != nil {
|
||||||
|
sa := (*sysSockaddrInet6)(unsafe.Pointer(&b[syscall.CmsgLen(0)]))
|
||||||
|
sa.setSockaddr(cm.NextHop, cm.IfIndex)
|
||||||
|
}
|
||||||
|
return b[syscall.CmsgSpace(sysSizeofSockaddrInet6):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseNextHop(cm *ControlMessage, b []byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalPathMTU(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIPv6
|
||||||
|
m.Type = sysIPV6_PATHMTU
|
||||||
|
m.SetLen(syscall.CmsgLen(sysSizeofIPv6Mtuinfo))
|
||||||
|
return b[syscall.CmsgSpace(sysSizeofIPv6Mtuinfo):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parsePathMTU(cm *ControlMessage, b []byte) {
|
||||||
|
mi := (*sysIPv6Mtuinfo)(unsafe.Pointer(&b[0]))
|
||||||
|
cm.Dst = mi.Addr.Addr[:]
|
||||||
|
cm.IfIndex = int(mi.Addr.Scope_id)
|
||||||
|
cm.MTU = int(mi.Mtu)
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build nacl plan9 solaris
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
// 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 (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
|
opt.Lock()
|
||||||
|
defer opt.Unlock()
|
||||||
|
if cf&FlagTrafficClass != 0 && sockOpts[ssoReceiveTrafficClass].name > 0 {
|
||||||
|
if err := setInt(fd, &sockOpts[ssoReceiveTrafficClass], boolint(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if on {
|
||||||
|
opt.set(FlagTrafficClass)
|
||||||
|
} else {
|
||||||
|
opt.clear(FlagTrafficClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cf&FlagHopLimit != 0 && sockOpts[ssoReceiveHopLimit].name > 0 {
|
||||||
|
if err := setInt(fd, &sockOpts[ssoReceiveHopLimit], boolint(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if on {
|
||||||
|
opt.set(FlagHopLimit)
|
||||||
|
} else {
|
||||||
|
opt.clear(FlagHopLimit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cf&flagPacketInfo != 0 && sockOpts[ssoReceivePacketInfo].name > 0 {
|
||||||
|
if err := setInt(fd, &sockOpts[ssoReceivePacketInfo], boolint(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if on {
|
||||||
|
opt.set(cf & flagPacketInfo)
|
||||||
|
} else {
|
||||||
|
opt.clear(cf & flagPacketInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cf&FlagPathMTU != 0 && sockOpts[ssoReceivePathMTU].name > 0 {
|
||||||
|
if err := setInt(fd, &sockOpts[ssoReceivePathMTU], boolint(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if on {
|
||||||
|
opt.set(FlagPathMTU)
|
||||||
|
} else {
|
||||||
|
opt.clear(FlagPathMTU)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||||
|
opt.RLock()
|
||||||
|
var l int
|
||||||
|
if opt.isset(FlagTrafficClass) && ctlOpts[ctlTrafficClass].name > 0 {
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlTrafficClass].length)
|
||||||
|
}
|
||||||
|
if opt.isset(FlagHopLimit) && ctlOpts[ctlHopLimit].name > 0 {
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlHopLimit].length)
|
||||||
|
}
|
||||||
|
if opt.isset(flagPacketInfo) && ctlOpts[ctlPacketInfo].name > 0 {
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlPacketInfo].length)
|
||||||
|
}
|
||||||
|
if opt.isset(FlagPathMTU) && ctlOpts[ctlPathMTU].name > 0 {
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlPathMTU].length)
|
||||||
|
}
|
||||||
|
if l > 0 {
|
||||||
|
oob = make([]byte, l)
|
||||||
|
b := oob
|
||||||
|
if opt.isset(FlagTrafficClass) && ctlOpts[ctlTrafficClass].name > 0 {
|
||||||
|
b = ctlOpts[ctlTrafficClass].marshal(b, nil)
|
||||||
|
}
|
||||||
|
if opt.isset(FlagHopLimit) && ctlOpts[ctlHopLimit].name > 0 {
|
||||||
|
b = ctlOpts[ctlHopLimit].marshal(b, nil)
|
||||||
|
}
|
||||||
|
if opt.isset(flagPacketInfo) && ctlOpts[ctlPacketInfo].name > 0 {
|
||||||
|
b = ctlOpts[ctlPacketInfo].marshal(b, nil)
|
||||||
|
}
|
||||||
|
if opt.isset(FlagPathMTU) && ctlOpts[ctlPathMTU].name > 0 {
|
||||||
|
b = ctlOpts[ctlPathMTU].marshal(b, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt.RUnlock()
|
||||||
|
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 != iana.ProtocolIPv6 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch int(m.Header.Type) {
|
||||||
|
case ctlOpts[ctlTrafficClass].name:
|
||||||
|
ctlOpts[ctlTrafficClass].parse(cm, m.Data[:])
|
||||||
|
case ctlOpts[ctlHopLimit].name:
|
||||||
|
ctlOpts[ctlHopLimit].parse(cm, m.Data[:])
|
||||||
|
case ctlOpts[ctlPacketInfo].name:
|
||||||
|
ctlOpts[ctlPacketInfo].parse(cm, m.Data[:])
|
||||||
|
case ctlOpts[ctlPathMTU].name:
|
||||||
|
ctlOpts[ctlPathMTU].parse(cm, m.Data[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||||
|
if cm == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var l int
|
||||||
|
tclass := false
|
||||||
|
if ctlOpts[ctlTrafficClass].name > 0 && cm.TrafficClass > 0 {
|
||||||
|
tclass = true
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlTrafficClass].length)
|
||||||
|
}
|
||||||
|
hoplimit := false
|
||||||
|
if ctlOpts[ctlHopLimit].name > 0 && cm.HopLimit > 0 {
|
||||||
|
hoplimit = true
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlHopLimit].length)
|
||||||
|
}
|
||||||
|
pktinfo := false
|
||||||
|
if ctlOpts[ctlPacketInfo].name > 0 && (cm.Src.To16() != nil && cm.Src.To4() == nil || cm.IfIndex > 0) {
|
||||||
|
pktinfo = true
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlPacketInfo].length)
|
||||||
|
}
|
||||||
|
nexthop := false
|
||||||
|
if ctlOpts[ctlNextHop].name > 0 && cm.NextHop.To16() != nil && cm.NextHop.To4() == nil {
|
||||||
|
nexthop = true
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlNextHop].length)
|
||||||
|
}
|
||||||
|
if l > 0 {
|
||||||
|
oob = make([]byte, l)
|
||||||
|
b := oob
|
||||||
|
if tclass {
|
||||||
|
b = ctlOpts[ctlTrafficClass].marshal(b, cm)
|
||||||
|
}
|
||||||
|
if hoplimit {
|
||||||
|
b = ctlOpts[ctlHopLimit].marshal(b, cm)
|
||||||
|
}
|
||||||
|
if pktinfo {
|
||||||
|
b = ctlOpts[ctlPacketInfo].marshal(b, cm)
|
||||||
|
}
|
||||||
|
if nexthop {
|
||||||
|
b = ctlOpts[ctlNextHop].marshal(b, cm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
// 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 setControlMessage(fd syscall.Handle, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return syscall.EWINDOWS
|
||||||
|
}
|
||||||
|
|
||||||
|
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return nil, syscall.EWINDOWS
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define __APPLE_USE_RFC_3542
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/icmp6.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||||
|
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||||
|
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||||
|
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||||
|
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||||
|
sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
|
||||||
|
sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
|
||||||
|
sysIPV6_2292NEXTHOP = C.IPV6_2292NEXTHOP
|
||||||
|
sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
|
||||||
|
sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
|
||||||
|
sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
|
||||||
|
|
||||||
|
sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||||
|
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||||
|
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||||
|
|
||||||
|
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||||
|
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||||
|
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||||
|
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||||
|
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||||
|
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||||
|
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||||
|
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||||
|
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||||
|
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
||||||
|
|
||||||
|
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||||
|
|
||||||
|
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
||||||
|
|
||||||
|
sysIPV6_MSFILTER = C.IPV6_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
|
||||||
|
|
||||||
|
sysIPV6_BOUND_IF = C.IPV6_BOUND_IF
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||||
|
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||||
|
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||||
|
sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
sysSizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||||
|
sysSizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||||
|
sysSizeofGroupReq = C.sizeof_struct_group_req
|
||||||
|
sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage C.struct_sockaddr_storage
|
||||||
|
|
||||||
|
type sysSockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
type sysInet6Pktinfo C.struct_in6_pktinfo
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo C.struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
type sysIPv6Mreq C.struct_ipv6_mreq
|
||||||
|
|
||||||
|
type sysICMPv6Filter C.struct_icmp6_filter
|
||||||
|
|
||||||
|
type sysGroupReq C.struct_group_req
|
||||||
|
|
||||||
|
type sysGroupSourceReq C.struct_group_source_req
|
||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/icmp6.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||||
|
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||||
|
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||||
|
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||||
|
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||||
|
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||||
|
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||||
|
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||||
|
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||||
|
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||||
|
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||||
|
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||||
|
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||||
|
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||||
|
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||||
|
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||||
|
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||||
|
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||||
|
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||||
|
|
||||||
|
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||||
|
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||||
|
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||||
|
|
||||||
|
sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
sysSizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||||
|
sysSizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
type sysInet6Pktinfo C.struct_in6_pktinfo
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo C.struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
type sysIPv6Mreq C.struct_ipv6_mreq
|
||||||
|
|
||||||
|
type sysICMPv6Filter C.struct_icmp6_filter
|
||||||
+105
@@ -0,0 +1,105 @@
|
|||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/icmp6.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||||
|
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||||
|
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||||
|
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||||
|
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||||
|
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||||
|
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||||
|
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||||
|
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||||
|
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||||
|
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||||
|
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||||
|
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||||
|
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||||
|
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||||
|
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||||
|
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||||
|
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||||
|
|
||||||
|
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
||||||
|
|
||||||
|
sysIPV6_BINDANY = C.IPV6_BINDANY
|
||||||
|
|
||||||
|
sysIPV6_MSFILTER = C.IPV6_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
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||||
|
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||||
|
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||||
|
sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
sysSizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||||
|
sysSizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||||
|
sysSizeofGroupReq = C.sizeof_struct_group_req
|
||||||
|
sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage C.struct_sockaddr_storage
|
||||||
|
|
||||||
|
type sysSockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
type sysInet6Pktinfo C.struct_in6_pktinfo
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo C.struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
type sysIPv6Mreq C.struct_ipv6_mreq
|
||||||
|
|
||||||
|
type sysGroupReq C.struct_group_req
|
||||||
|
|
||||||
|
type sysGroupSourceReq C.struct_group_source_req
|
||||||
|
|
||||||
|
type sysICMPv6Filter C.struct_icmp6_filter
|
||||||
+136
@@ -0,0 +1,136 @@
|
|||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/in6.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/icmpv6.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_ADDRFORM = C.IPV6_ADDRFORM
|
||||||
|
sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
|
||||||
|
sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
|
||||||
|
sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
|
||||||
|
sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
|
||||||
|
sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
|
||||||
|
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||||
|
sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
|
||||||
|
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||||
|
sysIPV6_FLOWINFO = C.IPV6_FLOWINFO
|
||||||
|
|
||||||
|
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||||
|
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||||
|
sysIPV6_ADD_MEMBERSHIP = C.IPV6_ADD_MEMBERSHIP
|
||||||
|
sysIPV6_DROP_MEMBERSHIP = C.IPV6_DROP_MEMBERSHIP
|
||||||
|
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
|
||||||
|
sysIPV6_ROUTER_ALERT = C.IPV6_ROUTER_ALERT
|
||||||
|
sysIPV6_MTU_DISCOVER = C.IPV6_MTU_DISCOVER
|
||||||
|
sysIPV6_MTU = C.IPV6_MTU
|
||||||
|
sysIPV6_RECVERR = C.IPV6_RECVERR
|
||||||
|
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||||
|
sysIPV6_JOIN_ANYCAST = C.IPV6_JOIN_ANYCAST
|
||||||
|
sysIPV6_LEAVE_ANYCAST = C.IPV6_LEAVE_ANYCAST
|
||||||
|
|
||||||
|
//sysIPV6_PMTUDISC_DONT = C.IPV6_PMTUDISC_DONT
|
||||||
|
//sysIPV6_PMTUDISC_WANT = C.IPV6_PMTUDISC_WANT
|
||||||
|
//sysIPV6_PMTUDISC_DO = C.IPV6_PMTUDISC_DO
|
||||||
|
//sysIPV6_PMTUDISC_PROBE = C.IPV6_PMTUDISC_PROBE
|
||||||
|
//sysIPV6_PMTUDISC_INTERFACE = C.IPV6_PMTUDISC_INTERFACE
|
||||||
|
//sysIPV6_PMTUDISC_OMIT = C.IPV6_PMTUDISC_OMIT
|
||||||
|
|
||||||
|
sysIPV6_FLOWLABEL_MGR = C.IPV6_FLOWLABEL_MGR
|
||||||
|
sysIPV6_FLOWINFO_SEND = C.IPV6_FLOWINFO_SEND
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||||
|
sysIPV6_XFRM_POLICY = C.IPV6_XFRM_POLICY
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||||
|
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||||
|
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||||
|
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||||
|
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||||
|
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||||
|
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||||
|
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||||
|
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||||
|
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||||
|
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||||
|
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||||
|
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||||
|
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||||
|
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||||
|
|
||||||
|
sysIPV6_ADDR_PREFERENCES = C.IPV6_ADDR_PREFERENCES
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_TMP = C.IPV6_PREFER_SRC_TMP
|
||||||
|
sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
|
||||||
|
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = C.IPV6_PREFER_SRC_PUBTMP_DEFAULT
|
||||||
|
sysIPV6_PREFER_SRC_COA = C.IPV6_PREFER_SRC_COA
|
||||||
|
sysIPV6_PREFER_SRC_HOME = C.IPV6_PREFER_SRC_HOME
|
||||||
|
sysIPV6_PREFER_SRC_CGA = C.IPV6_PREFER_SRC_CGA
|
||||||
|
sysIPV6_PREFER_SRC_NONCGA = C.IPV6_PREFER_SRC_NONCGA
|
||||||
|
|
||||||
|
sysIPV6_MINHOPCOUNT = C.IPV6_MINHOPCOUNT
|
||||||
|
|
||||||
|
sysIPV6_ORIGDSTADDR = C.IPV6_ORIGDSTADDR
|
||||||
|
sysIPV6_RECVORIGDSTADDR = C.IPV6_RECVORIGDSTADDR
|
||||||
|
sysIPV6_TRANSPARENT = C.IPV6_TRANSPARENT
|
||||||
|
sysIPV6_UNICAST_IF = C.IPV6_UNICAST_IF
|
||||||
|
|
||||||
|
sysICMPV6_FILTER = C.ICMPV6_FILTER
|
||||||
|
|
||||||
|
sysICMPV6_FILTER_BLOCK = C.ICMPV6_FILTER_BLOCK
|
||||||
|
sysICMPV6_FILTER_PASS = C.ICMPV6_FILTER_PASS
|
||||||
|
sysICMPV6_FILTER_BLOCKOTHERS = C.ICMPV6_FILTER_BLOCKOTHERS
|
||||||
|
sysICMPV6_FILTER_PASSONLY = C.ICMPV6_FILTER_PASSONLY
|
||||||
|
|
||||||
|
sysSizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
||||||
|
sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
sysSizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||||
|
sysSizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||||
|
sysSizeofIPv6FlowlabelReq = C.sizeof_struct_in6_flowlabel_req
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||||
|
sysSizeofGroupReq = C.sizeof_struct_group_req
|
||||||
|
sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysKernelSockaddrStorage C.struct___kernel_sockaddr_storage
|
||||||
|
|
||||||
|
type sysSockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
type sysInet6Pktinfo C.struct_in6_pktinfo
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo C.struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
type sysIPv6FlowlabelReq C.struct_in6_flowlabel_req
|
||||||
|
|
||||||
|
type sysIPv6Mreq C.struct_ipv6_mreq
|
||||||
|
|
||||||
|
type sysGroupReq C.struct_group_req
|
||||||
|
|
||||||
|
type sysGroupSourceReq C.struct_group_source_req
|
||||||
|
|
||||||
|
type sysICMPv6Filter C.struct_icmp6_filter
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/icmp6.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||||
|
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||||
|
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||||
|
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||||
|
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||||
|
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||||
|
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||||
|
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||||
|
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||||
|
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||||
|
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||||
|
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||||
|
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||||
|
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||||
|
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||||
|
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||||
|
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||||
|
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||||
|
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||||
|
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||||
|
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||||
|
|
||||||
|
sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
sysSizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||||
|
sysSizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
type sysInet6Pktinfo C.struct_in6_pktinfo
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo C.struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
type sysIPv6Mreq C.struct_ipv6_mreq
|
||||||
|
|
||||||
|
type sysICMPv6Filter C.struct_icmp6_filter
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/icmp6.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||||
|
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||||
|
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||||
|
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||||
|
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||||
|
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||||
|
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||||
|
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||||
|
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||||
|
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||||
|
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||||
|
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||||
|
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||||
|
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||||
|
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||||
|
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||||
|
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||||
|
|
||||||
|
sysIPV6_AUTH_LEVEL = C.IPV6_AUTH_LEVEL
|
||||||
|
sysIPV6_ESP_TRANS_LEVEL = C.IPV6_ESP_TRANS_LEVEL
|
||||||
|
sysIPV6_ESP_NETWORK_LEVEL = C.IPV6_ESP_NETWORK_LEVEL
|
||||||
|
sysIPSEC6_OUTSA = C.IPSEC6_OUTSA
|
||||||
|
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
||||||
|
sysIPV6_IPCOMP_LEVEL = C.IPV6_IPCOMP_LEVEL
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||||
|
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||||
|
sysIPV6_PIPEX = C.IPV6_PIPEX
|
||||||
|
|
||||||
|
sysIPV6_RTABLE = C.IPV6_RTABLE
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||||
|
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||||
|
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||||
|
|
||||||
|
sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
sysSizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||||
|
sysSizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
type sysInet6Pktinfo C.struct_in6_pktinfo
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo C.struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
type sysIPv6Mreq C.struct_ipv6_mreq
|
||||||
|
|
||||||
|
type sysICMPv6Filter C.struct_icmp6_filter
|
||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/icmp6.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||||
|
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||||
|
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||||
|
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||||
|
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||||
|
|
||||||
|
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||||
|
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||||
|
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||||
|
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||||
|
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||||
|
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||||
|
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||||
|
|
||||||
|
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||||
|
|
||||||
|
sysIPV6_RECVRTHDRDSTOPTS = C.IPV6_RECVRTHDRDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||||
|
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||||
|
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||||
|
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||||
|
sysIPV6_SEC_OPT = C.IPV6_SEC_OPT
|
||||||
|
sysIPV6_SRC_PREFERENCES = C.IPV6_SRC_PREFERENCES
|
||||||
|
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||||
|
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||||
|
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||||
|
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||||
|
|
||||||
|
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_HOME = C.IPV6_PREFER_SRC_HOME
|
||||||
|
sysIPV6_PREFER_SRC_COA = C.IPV6_PREFER_SRC_COA
|
||||||
|
sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
|
||||||
|
sysIPV6_PREFER_SRC_TMP = C.IPV6_PREFER_SRC_TMP
|
||||||
|
sysIPV6_PREFER_SRC_NONCGA = C.IPV6_PREFER_SRC_NONCGA
|
||||||
|
sysIPV6_PREFER_SRC_CGA = C.IPV6_PREFER_SRC_CGA
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_MIPMASK = C.IPV6_PREFER_SRC_MIPMASK
|
||||||
|
sysIPV6_PREFER_SRC_MIPDEFAULT = C.IPV6_PREFER_SRC_MIPDEFAULT
|
||||||
|
sysIPV6_PREFER_SRC_TMPMASK = C.IPV6_PREFER_SRC_TMPMASK
|
||||||
|
sysIPV6_PREFER_SRC_TMPDEFAULT = C.IPV6_PREFER_SRC_TMPDEFAULT
|
||||||
|
sysIPV6_PREFER_SRC_CGAMASK = C.IPV6_PREFER_SRC_CGAMASK
|
||||||
|
sysIPV6_PREFER_SRC_CGADEFAULT = C.IPV6_PREFER_SRC_CGADEFAULT
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_MASK = C.IPV6_PREFER_SRC_MASK
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_DEFAULT = C.IPV6_PREFER_SRC_DEFAULT
|
||||||
|
|
||||||
|
sysIPV6_BOUND_IF = C.IPV6_BOUND_IF
|
||||||
|
sysIPV6_UNSPEC_SRC = C.IPV6_UNSPEC_SRC
|
||||||
|
|
||||||
|
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||||
|
|
||||||
|
sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
sysSizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||||
|
sysSizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
type sysInet6Pktinfo C.struct_in6_pktinfo
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo C.struct_ip6_mtuinfo
|
||||||
|
|
||||||
|
type sysIPv6Mreq C.struct_ipv6_mreq
|
||||||
|
|
||||||
|
type sysICMPv6Filter C.struct_icmp6_filter
|
||||||
+288
@@ -0,0 +1,288 @@
|
|||||||
|
// 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 getInt(fd, &sockOpts[ssoMulticastHopLimit])
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 setInt(fd, &sockOpts[ssoMulticastHopLimit], 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 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 := netAddrToIP16(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 := netAddrToIP16(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 := netAddrToIP16(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
src := netAddrToIP16(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 := netAddrToIP16(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
src := netAddrToIP16(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 := netAddrToIP16(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
src := netAddrToIP16(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 := netAddrToIP16(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
src := netAddrToIP16(source)
|
||||||
|
if src == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
return setSourceGroup(fd, &sockOpts[ssoUnblockSourceGroup], ifi, grp, src)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
offset, err = getInt(fd, &sockOpts[ssoChecksum])
|
||||||
|
if err != nil {
|
||||||
|
return false, 0, err
|
||||||
|
}
|
||||||
|
if offset < 0 {
|
||||||
|
return false, 0, nil
|
||||||
|
}
|
||||||
|
return true, offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
if !on {
|
||||||
|
offset = -1
|
||||||
|
}
|
||||||
|
return setInt(fd, &sockOpts[ssoChecksum], 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 getICMPFilter(fd, &sockOpts[ssoICMPFilter])
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 setICMPFilter(fd, &sockOpts[ssoICMPFilter], f)
|
||||||
|
}
|
||||||
+119
@@ -0,0 +1,119 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
// MulticastHopLimit returns the hop limit field value for outgoing
|
||||||
|
// multicast packets.
|
||||||
|
func (c *dgramOpt) MulticastHopLimit() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMulticastHopLimit sets the hop limit field value for future
|
||||||
|
// outgoing multicast packets.
|
||||||
|
func (c *dgramOpt) SetMulticastHopLimit(hoplim 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
return false, 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// ICMPFilter returns an ICMP filter.
|
||||||
|
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetICMPFilter deploys the ICMP filter.
|
||||||
|
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
+240
@@ -0,0 +1,240 @@
|
|||||||
|
// 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 implements IP-level socket options for the Internet
|
||||||
|
// Protocol version 6.
|
||||||
|
//
|
||||||
|
// The package provides IP-level socket options that allow
|
||||||
|
// manipulation of IPv6 facilities.
|
||||||
|
//
|
||||||
|
// The IPv6 protocol is defined in RFC 2460.
|
||||||
|
// Basic and advanced socket interface extensions are defined in RFC
|
||||||
|
// 3493 and RFC 3542.
|
||||||
|
// Socket interface extensions for multicast source filters are
|
||||||
|
// defined in RFC 3678.
|
||||||
|
// MLDv1 and MLDv2 are defined in RFC 2710 and RFC 3810.
|
||||||
|
// Source-specific multicast is defined in RFC 4607.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Unicasting
|
||||||
|
//
|
||||||
|
// The options for unicasting are available for net.TCPConn,
|
||||||
|
// net.UDPConn and net.IPConn which are created as network connections
|
||||||
|
// that use the IPv6 transport. When a single TCP connection carrying
|
||||||
|
// a data flow of multiple packets needs to indicate the flow is
|
||||||
|
// important, ipv6.Conn is used to set the traffic class field on the
|
||||||
|
// IPv6 header for each packet.
|
||||||
|
//
|
||||||
|
// ln, err := net.Listen("tcp6", "[::]:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer ln.Close()
|
||||||
|
// for {
|
||||||
|
// c, err := ln.Accept()
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// go func(c net.Conn) {
|
||||||
|
// defer c.Close()
|
||||||
|
//
|
||||||
|
// The outgoing packets will be labeled DiffServ assured forwarding
|
||||||
|
// class 1 low drop precedence, known as AF11 packets.
|
||||||
|
//
|
||||||
|
// if err := ipv6.NewConn(c).SetTrafficClass(DiffServAF11); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if _, err := c.Write(data); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// }(c)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Multicasting
|
||||||
|
//
|
||||||
|
// The options for multicasting are available for net.UDPConn and
|
||||||
|
// net.IPconn which are created as network connections that use the
|
||||||
|
// IPv6 transport. A few network facilities must be prepared before
|
||||||
|
// you begin multicasting, at a minimum joining network interfaces and
|
||||||
|
// multicast groups.
|
||||||
|
//
|
||||||
|
// en0, err := net.InterfaceByName("en0")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// en1, err := net.InterfaceByIndex(911)
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// group := net.ParseIP("ff02::114")
|
||||||
|
//
|
||||||
|
// First, an application listens to an appropriate address with an
|
||||||
|
// appropriate service port.
|
||||||
|
//
|
||||||
|
// c, err := net.ListenPacket("udp6", "[::]:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer c.Close()
|
||||||
|
//
|
||||||
|
// Second, the application joins multicast groups, starts listening to
|
||||||
|
// the groups on the specified network interfaces. Note that the
|
||||||
|
// service port for transport layer protocol does not matter with this
|
||||||
|
// operation as joining groups affects only network and link layer
|
||||||
|
// protocols, such as IPv6 and Ethernet.
|
||||||
|
//
|
||||||
|
// p := ipv6.NewPacketConn(c)
|
||||||
|
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: group}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.JoinGroup(en1, &net.UDPAddr{IP: group}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The application might set per packet control message transmissions
|
||||||
|
// between the protocol stack within the kernel. When the application
|
||||||
|
// needs a destination address on an incoming packet,
|
||||||
|
// SetControlMessage of ipv6.PacketConn is used to enable control
|
||||||
|
// message transmissons.
|
||||||
|
//
|
||||||
|
// if err := p.SetControlMessage(ipv6.FlagDst, true); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The application could identify whether the received packets are
|
||||||
|
// of interest by using the control message that contains the
|
||||||
|
// destination address of the received packet.
|
||||||
|
//
|
||||||
|
// b := make([]byte, 1500)
|
||||||
|
// for {
|
||||||
|
// n, rcm, src, err := p.ReadFrom(b)
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if rcm.Dst.IsMulticast() {
|
||||||
|
// if rcm.Dst.Equal(group) {
|
||||||
|
// // joined group, do something
|
||||||
|
// } else {
|
||||||
|
// // unknown group, discard
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The application can also send both unicast and multicast packets.
|
||||||
|
//
|
||||||
|
// p.SetTrafficClass(DiffServCS0)
|
||||||
|
// p.SetHopLimit(16)
|
||||||
|
// if _, err := p.WriteTo(data[:n], nil, src); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// dst := &net.UDPAddr{IP: group, Port: 1024}
|
||||||
|
// wcm := ipv6.ControlMessage{TrafficClass: DiffServCS7, HopLimit: 1}
|
||||||
|
// for _, ifi := range []*net.Interface{en0, en1} {
|
||||||
|
// wcm.IfIndex = ifi.Index
|
||||||
|
// if _, err := p.WriteTo(data[:n], &wcm, dst); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// More multicasting
|
||||||
|
//
|
||||||
|
// An application that uses PacketConn may join multiple multicast
|
||||||
|
// groups. For example, a UDP listener with port 1024 might join two
|
||||||
|
// different groups across over two different network interfaces by
|
||||||
|
// using:
|
||||||
|
//
|
||||||
|
// c, err := net.ListenPacket("udp6", "[::]:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer c.Close()
|
||||||
|
// p := ipv6.NewPacketConn(c)
|
||||||
|
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::1:114")}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::2:114")}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.JoinGroup(en1, &net.UDPAddr{IP: net.ParseIP("ff02::2:114")}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// It is possible for multiple UDP listeners that listen on the same
|
||||||
|
// UDP port to join the same multicast group. The net package will
|
||||||
|
// provide a socket that listens to a wildcard address with reusable
|
||||||
|
// UDP port when an appropriate multicast address prefix is passed to
|
||||||
|
// the net.ListenPacket or net.ListenUDP.
|
||||||
|
//
|
||||||
|
// c1, err := net.ListenPacket("udp6", "[ff02::]:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer c1.Close()
|
||||||
|
// c2, err := net.ListenPacket("udp6", "[ff02::]:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer c2.Close()
|
||||||
|
// p1 := ipv6.NewPacketConn(c1)
|
||||||
|
// if err := p1.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// p2 := ipv6.NewPacketConn(c2)
|
||||||
|
// if err := p2.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Also it is possible for the application to leave or rejoin a
|
||||||
|
// multicast group on the network interface.
|
||||||
|
//
|
||||||
|
// if err := p.LeaveGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff01::114")}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Source-specific multicasting
|
||||||
|
//
|
||||||
|
// An application that uses PacketConn on MLDv2 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.ParseIP("ff32::8000:9")}
|
||||||
|
// ssmsource := net.UDPAddr{IP: net.ParseIP("fe80::cafe")}
|
||||||
|
// 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.ParseIP("fe80::dead")}
|
||||||
|
// 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 MLDv2 unsupported platform uses
|
||||||
|
// JoinSourceSpecificGroup and LeaveSourceSpecificGroup.
|
||||||
|
// In general the platform tries to fall back to conversations using
|
||||||
|
// MLDv1 and starts to listen to multicast traffic.
|
||||||
|
// In the fallback case, ExcludeSourceSpecificGroup and
|
||||||
|
// IncludeSourceSpecificGroup may return an error.
|
||||||
|
package ipv6
|
||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
// 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"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Conn represents a network endpoint that uses IPv6 transport.
|
||||||
|
// It allows to set basic IP-level socket options such as traffic
|
||||||
|
// class and hop limit.
|
||||||
|
type Conn struct {
|
||||||
|
genericOpt
|
||||||
|
}
|
||||||
|
|
||||||
|
type genericOpt struct {
|
||||||
|
net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *genericOpt) ok() bool { return c != nil && c.Conn != nil }
|
||||||
|
|
||||||
|
// PathMTU returns a path MTU value for the destination associated
|
||||||
|
// with the endpoint.
|
||||||
|
func (c *Conn) PathMTU() (int, error) {
|
||||||
|
if !c.genericOpt.ok() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.genericOpt.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
_, mtu, err := getMTUInfo(fd, &sockOpts[ssoPathMTU])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return mtu, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConn returns a new Conn.
|
||||||
|
func NewConn(c net.Conn) *Conn {
|
||||||
|
return &Conn{
|
||||||
|
genericOpt: genericOpt{Conn: c},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A PacketConn represents a packet network endpoint that uses IPv6
|
||||||
|
// transport. It is used to control several IP-level socket options
|
||||||
|
// including IPv6 header manipulation. It also provides datagram
|
||||||
|
// based network I/O methods specific to the IPv6 and higher layer
|
||||||
|
// protocols such as OSPF, GRE, and UDP.
|
||||||
|
type PacketConn struct {
|
||||||
|
genericOpt
|
||||||
|
dgramOpt
|
||||||
|
payloadHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
type dgramOpt struct {
|
||||||
|
net.PacketConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dgramOpt) ok() bool { return c != nil && c.PacketConn != nil }
|
||||||
|
|
||||||
|
// SetControlMessage allows to receive the per packet basis IP-level
|
||||||
|
// socket options.
|
||||||
|
func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.payloadHandler.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setControlMessage(fd, &c.payloadHandler.rawOpt, cf, on)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDeadline sets the read and write deadlines associated with the
|
||||||
|
// endpoint.
|
||||||
|
func (c *PacketConn) SetDeadline(t time.Time) error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.payloadHandler.SetDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReadDeadline sets the read deadline associated with the
|
||||||
|
// endpoint.
|
||||||
|
func (c *PacketConn) SetReadDeadline(t time.Time) error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.payloadHandler.SetReadDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWriteDeadline sets the write deadline associated with the
|
||||||
|
// endpoint.
|
||||||
|
func (c *PacketConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.payloadHandler.SetWriteDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the endpoint.
|
||||||
|
func (c *PacketConn) Close() error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.payloadHandler.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPacketConn returns a new PacketConn using c as its underlying
|
||||||
|
// transport.
|
||||||
|
func NewPacketConn(c net.PacketConn) *PacketConn {
|
||||||
|
return &PacketConn{
|
||||||
|
genericOpt: genericOpt{Conn: c.(net.Conn)},
|
||||||
|
dgramOpt: dgramOpt{PacketConn: c},
|
||||||
|
payloadHandler: payloadHandler{PacketConn: c},
|
||||||
|
}
|
||||||
|
}
|
||||||
+214
@@ -0,0 +1,214 @@
|
|||||||
|
// 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_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleConn_markingTCP() {
|
||||||
|
ln, err := net.Listen("tcp6", "[::]: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 := ipv6.NewConn(c)
|
||||||
|
if err := p.SetTrafficClass(0x28); err != nil { // DSCP AF11
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetHopLimit(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("udp6", "[::]:5353") // mDNS over UDP
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
|
||||||
|
en0, err := net.InterfaceByName("en0")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
mDNSLinkLocal := net.UDPAddr{IP: net.ParseIP("ff02::fb")}
|
||||||
|
if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer p.LeaveGroup(en0, &mDNSLinkLocal)
|
||||||
|
if err := p.SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wcm ipv6.ControlMessage
|
||||||
|
b := make([]byte, 1500)
|
||||||
|
for {
|
||||||
|
_, rcm, peer, err := p.ReadFrom(b)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if !rcm.Dst.IsMulticast() || !rcm.Dst.Equal(mDNSLinkLocal.IP) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wcm.IfIndex = rcm.IfIndex
|
||||||
|
answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this
|
||||||
|
if _, err := p.WriteTo(answers, &wcm, 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.To16() != nil && 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 AAAA record found")
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip6:58", "::") // ICMP for IPv6
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
|
||||||
|
if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
wm := icmp.Message{
|
||||||
|
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: os.Getpid() & 0xffff,
|
||||||
|
Data: []byte("HELLO-R-U-THERE"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var f ipv6.ICMPFilter
|
||||||
|
f.SetAll(true)
|
||||||
|
f.Accept(ipv6.ICMPTypeTimeExceeded)
|
||||||
|
f.Accept(ipv6.ICMPTypeEchoReply)
|
||||||
|
if err := p.SetICMPFilter(&f); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wcm ipv6.ControlMessage
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
wcm.HopLimit = i
|
||||||
|
if _, err := p.WriteTo(wb, &wcm, &dst); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
n, rcm, 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(58, 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,
|
||||||
|
// ControlMesage.Dst, icmp.Echo.ID and icmp.Echo.Seq.
|
||||||
|
switch rm.Type {
|
||||||
|
case ipv6.ICMPTypeTimeExceeded:
|
||||||
|
names, _ := net.LookupAddr(peer.String())
|
||||||
|
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm)
|
||||||
|
case ipv6.ICMPTypeEchoReply:
|
||||||
|
names, _ := net.LookupAddr(peer.String())
|
||||||
|
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExamplePacketConn_advertisingOSPFHello() {
|
||||||
|
c, err := net.ListenPacket("ip6:89", "::") // OSPF for IPv6
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
|
||||||
|
en0, err := net.InterfaceByName("en0")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
allSPFRouters := net.IPAddr{IP: net.ParseIP("ff02::5")}
|
||||||
|
if err := p.JoinGroup(en0, &allSPFRouters); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer p.LeaveGroup(en0, &allSPFRouters)
|
||||||
|
|
||||||
|
hello := make([]byte, 24) // fake hello data, you need to implement this
|
||||||
|
ospf := make([]byte, 16) // fake ospf header, you need to implement this
|
||||||
|
ospf[0] = 3 // version 3
|
||||||
|
ospf[1] = 1 // hello packet
|
||||||
|
ospf = append(ospf, hello...)
|
||||||
|
if err := p.SetChecksum(true, 12); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cm := ipv6.ControlMessage{
|
||||||
|
TrafficClass: 0xc0, // DSCP CS6
|
||||||
|
HopLimit: 1,
|
||||||
|
IfIndex: en0.Index,
|
||||||
|
}
|
||||||
|
if _, err := p.WriteTo(ospf, &cm, &allSPFRouters); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
+208
@@ -0,0 +1,208 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
//go:generate go run gen.go
|
||||||
|
|
||||||
|
// This program generates system adaptation constants and types,
|
||||||
|
// internet protocol constants and tables by reading template files
|
||||||
|
// and IANA protocol registries.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := genzsys(); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := geniana(); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func genzsys() error {
|
||||||
|
defs := "defs_" + runtime.GOOS + ".go"
|
||||||
|
f, err := os.Open(defs)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
|
||||||
|
b, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// The ipv6 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 ipv6\n"), []byte("// +build "+runtime.GOOS+"\n\npackage ipv6\n"), 1)
|
||||||
|
case runtime.GOOS == "linux" && (runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le"):
|
||||||
|
b = bytes.Replace(b, []byte("package ipv6\n"), []byte("// +build "+runtime.GOOS+","+runtime.GOARCH+"\n\npackage ipv6\n"), 1)
|
||||||
|
}
|
||||||
|
b, err = format.Source(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
var registries = []struct {
|
||||||
|
url string
|
||||||
|
parse func(io.Writer, io.Reader) error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml",
|
||||||
|
parseICMPv6Parameters,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func geniana() error {
|
||||||
|
var bb bytes.Buffer
|
||||||
|
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 ipv6\n\n")
|
||||||
|
for _, r := range registries {
|
||||||
|
resp, err := http.Get(r.url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
||||||
|
}
|
||||||
|
if err := r.parse(&bb, resp.Body); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&bb, "\n")
|
||||||
|
}
|
||||||
|
b, err := format.Source(bb.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseICMPv6Parameters(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var icp icmpv6Parameters
|
||||||
|
if err := dec.Decode(&icp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prs := icp.escape()
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, pr := range prs {
|
||||||
|
if pr.Name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Name, pr.Value)
|
||||||
|
fmt.Fprintf(w, "// %s\n", pr.OrigName)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n\n")
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||||
|
fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
|
||||||
|
for _, pr := range prs {
|
||||||
|
if pr.Name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigName))
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "}\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type icmpv6Parameters struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
Registries []struct {
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Records []struct {
|
||||||
|
Value string `xml:"value"`
|
||||||
|
Name string `xml:"name"`
|
||||||
|
} `xml:"record"`
|
||||||
|
} `xml:"registry"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonICMPv6ParamRecord struct {
|
||||||
|
OrigName string
|
||||||
|
Name string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (icp *icmpv6Parameters) escape() []canonICMPv6ParamRecord {
|
||||||
|
id := -1
|
||||||
|
for i, r := range icp.Registries {
|
||||||
|
if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
|
||||||
|
id = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if id < 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
prs := make([]canonICMPv6ParamRecord, len(icp.Registries[id].Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"Messages", "",
|
||||||
|
"Message", "",
|
||||||
|
"ICMP", "",
|
||||||
|
"+", "P",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, pr := range icp.Registries[id].Records {
|
||||||
|
if strings.Contains(pr.Name, "Reserved") ||
|
||||||
|
strings.Contains(pr.Name, "Unassigned") ||
|
||||||
|
strings.Contains(pr.Name, "Deprecated") ||
|
||||||
|
strings.Contains(pr.Name, "Experiment") ||
|
||||||
|
strings.Contains(pr.Name, "experiment") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ss := strings.Split(pr.Name, "\n")
|
||||||
|
if len(ss) > 1 {
|
||||||
|
prs[i].Name = strings.Join(ss, " ")
|
||||||
|
} else {
|
||||||
|
prs[i].Name = ss[0]
|
||||||
|
}
|
||||||
|
s := strings.TrimSpace(prs[i].Name)
|
||||||
|
prs[i].OrigName = s
|
||||||
|
prs[i].Name = sr.Replace(s)
|
||||||
|
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||||
|
}
|
||||||
|
return prs
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
// 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 "syscall"
|
||||||
|
|
||||||
|
// TrafficClass returns the traffic class field value for outgoing
|
||||||
|
// packets.
|
||||||
|
func (c *genericOpt) TrafficClass() (int, error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return getInt(fd, &sockOpts[ssoTrafficClass])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTrafficClass sets the traffic class field value for future
|
||||||
|
// outgoing packets.
|
||||||
|
func (c *genericOpt) SetTrafficClass(tclass int) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setInt(fd, &sockOpts[ssoTrafficClass], tclass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HopLimit returns the hop limit field value for outgoing packets.
|
||||||
|
func (c *genericOpt) HopLimit() (int, error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return getInt(fd, &sockOpts[ssoHopLimit])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHopLimit sets the hop limit field value for future outgoing
|
||||||
|
// packets.
|
||||||
|
func (c *genericOpt) SetHopLimit(hoplim int) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setInt(fd, &sockOpts[ssoHopLimit], hoplim)
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
// TrafficClass returns the traffic class field value for outgoing
|
||||||
|
// packets.
|
||||||
|
func (c *genericOpt) TrafficClass() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTrafficClass sets the traffic class field value for future
|
||||||
|
// outgoing packets.
|
||||||
|
func (c *genericOpt) SetTrafficClass(tclass int) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// HopLimit returns the hop limit field value for outgoing packets.
|
||||||
|
func (c *genericOpt) HopLimit() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHopLimit sets the hop limit field value for future outgoing
|
||||||
|
// packets.
|
||||||
|
func (c *genericOpt) SetHopLimit(hoplim int) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Version = 6 // protocol version
|
||||||
|
HeaderLen = 40 // header length
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Header represents an IPv6 base header.
|
||||||
|
type Header struct {
|
||||||
|
Version int // protocol version
|
||||||
|
TrafficClass int // traffic class
|
||||||
|
FlowLabel int // flow label
|
||||||
|
PayloadLen int // payload length
|
||||||
|
NextHeader int // next header
|
||||||
|
HopLimit int // hop limit
|
||||||
|
Src net.IP // source address
|
||||||
|
Dst net.IP // destination address
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Header) String() string {
|
||||||
|
if h == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("ver: %v, tclass: %#x, flowlbl: %#x, payloadlen: %v, nxthdr: %v, hoplim: %v, src: %v, dst: %v", h.Version, h.TrafficClass, h.FlowLabel, h.PayloadLen, h.NextHeader, h.HopLimit, h.Src, h.Dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseHeader parses b as an IPv6 base header.
|
||||||
|
func ParseHeader(b []byte) (*Header, error) {
|
||||||
|
if len(b) < HeaderLen {
|
||||||
|
return nil, errors.New("header too short")
|
||||||
|
}
|
||||||
|
h := &Header{
|
||||||
|
Version: int(b[0]) >> 4,
|
||||||
|
TrafficClass: int(b[0]&0x0f)<<4 | int(b[1])>>4,
|
||||||
|
FlowLabel: int(b[1]&0x0f)<<16 | int(b[2])<<8 | int(b[3]),
|
||||||
|
PayloadLen: int(b[4])<<8 | int(b[5]),
|
||||||
|
NextHeader: int(b[6]),
|
||||||
|
HopLimit: int(b[7]),
|
||||||
|
}
|
||||||
|
h.Src = make(net.IP, net.IPv6len)
|
||||||
|
copy(h.Src, b[8:24])
|
||||||
|
h.Dst = make(net.IP, net.IPv6len)
|
||||||
|
copy(h.Dst, b[24:40])
|
||||||
|
return h, nil
|
||||||
|
}
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
// 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_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
wireHeaderFromKernel = [ipv6.HeaderLen]byte{
|
||||||
|
0x69, 0x8b, 0xee, 0xf1,
|
||||||
|
0xca, 0xfe, 0x2c, 0x01,
|
||||||
|
0x20, 0x01, 0x0d, 0xb8,
|
||||||
|
0x00, 0x01, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x20, 0x01, 0x0d, 0xb8,
|
||||||
|
0x00, 0x02, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x01,
|
||||||
|
}
|
||||||
|
|
||||||
|
testHeader = &ipv6.Header{
|
||||||
|
Version: ipv6.Version,
|
||||||
|
TrafficClass: iana.DiffServAF43,
|
||||||
|
FlowLabel: 0xbeef1,
|
||||||
|
PayloadLen: 0xcafe,
|
||||||
|
NextHeader: iana.ProtocolIPv6Frag,
|
||||||
|
HopLimit: 1,
|
||||||
|
Src: net.ParseIP("2001:db8:1::1"),
|
||||||
|
Dst: net.ParseIP("2001:db8:2::1"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseHeader(t *testing.T) {
|
||||||
|
h, err := ipv6.ParseHeader(wireHeaderFromKernel[:])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(h, testHeader) {
|
||||||
|
t.Fatalf("got %#v; want %#v", h, testHeader)
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errOpNoSupport = errors.New("operation not supported")
|
||||||
|
|
||||||
|
func boolint(b bool) int {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func netAddrToIP16(a net.Addr) net.IP {
|
||||||
|
switch v := a.(type) {
|
||||||
|
case *net.UDPAddr:
|
||||||
|
if ip := v.IP.To16(); ip != nil && ip.To4() == nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
case *net.IPAddr:
|
||||||
|
if ip := v.IP.To16(); ip != nil && ip.To4() == nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build nacl plan9 solaris
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
func (c *genericOpt) sysfd() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dgramOpt) sysfd() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *payloadHandler) sysfd() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *genericOpt) sysfd() (int, error) {
|
||||||
|
switch p := c.Conn.(type) {
|
||||||
|
case *net.TCPConn, *net.UDPConn, *net.IPConn:
|
||||||
|
return sysfd(p)
|
||||||
|
}
|
||||||
|
return 0, errInvalidConnType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dgramOpt) sysfd() (int, error) {
|
||||||
|
switch p := c.PacketConn.(type) {
|
||||||
|
case *net.UDPConn, *net.IPConn:
|
||||||
|
return sysfd(p.(net.Conn))
|
||||||
|
}
|
||||||
|
return 0, errInvalidConnType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *payloadHandler) sysfd() (int, error) {
|
||||||
|
return sysfd(c.PacketConn.(net.Conn))
|
||||||
|
}
|
||||||
|
|
||||||
|
func sysfd(c net.Conn) (int, error) {
|
||||||
|
cv := reflect.ValueOf(c)
|
||||||
|
switch ce := cv.Elem(); ce.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
nfd := ce.FieldByName("conn").FieldByName("fd")
|
||||||
|
switch fe := nfd.Elem(); fe.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
fd := fe.FieldByName("sysfd")
|
||||||
|
return int(fd.Int()), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, errInvalidConnType
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *genericOpt) sysfd() (syscall.Handle, error) {
|
||||||
|
switch p := c.Conn.(type) {
|
||||||
|
case *net.TCPConn, *net.UDPConn, *net.IPConn:
|
||||||
|
return sysfd(p)
|
||||||
|
}
|
||||||
|
return syscall.InvalidHandle, errInvalidConnType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dgramOpt) sysfd() (syscall.Handle, error) {
|
||||||
|
switch p := c.PacketConn.(type) {
|
||||||
|
case *net.UDPConn, *net.IPConn:
|
||||||
|
return sysfd(p.(net.Conn))
|
||||||
|
}
|
||||||
|
return syscall.InvalidHandle, errInvalidConnType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *payloadHandler) sysfd() (syscall.Handle, error) {
|
||||||
|
return sysfd(c.PacketConn.(net.Conn))
|
||||||
|
}
|
||||||
|
|
||||||
|
func sysfd(c net.Conn) (syscall.Handle, error) {
|
||||||
|
cv := reflect.ValueOf(c)
|
||||||
|
switch ce := cv.Elem(); ce.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
netfd := ce.FieldByName("conn").FieldByName("fd")
|
||||||
|
switch fe := netfd.Elem(); fe.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
fd := fe.FieldByName("sysfd")
|
||||||
|
return syscall.Handle(fd.Uint()), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return syscall.InvalidHandle, errInvalidConnType
|
||||||
|
}
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
// go generate gen.go
|
||||||
|
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2015-07-07
|
||||||
|
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
|
||||||
|
ICMPTypeMPLControl ICMPType = 159 // MPL Control Message
|
||||||
|
)
|
||||||
|
|
||||||
|
// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2015-07-07
|
||||||
|
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",
|
||||||
|
159: "mpl control message",
|
||||||
|
}
|
||||||
+57
@@ -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 ipv6
|
||||||
|
|
||||||
|
import "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 ICMPv6 protocol number.
|
||||||
|
func (typ ICMPType) Protocol() int {
|
||||||
|
return iana.ProtocolIPv6ICMP
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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. 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 {
|
||||||
|
sysICMPv6Filter
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) accept(typ ICMPType) {
|
||||||
|
f.Filt[typ>>5] |= 1 << (uint32(typ) & 31)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) block(typ ICMPType) {
|
||||||
|
f.Filt[typ>>5] &^= 1 << (uint32(typ) & 31)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) setAll(block bool) {
|
||||||
|
for i := range f.Filt {
|
||||||
|
if block {
|
||||||
|
f.Filt[i] = 0
|
||||||
|
} else {
|
||||||
|
f.Filt[i] = 1<<32 - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) willBlock(typ ICMPType) bool {
|
||||||
|
return f.Filt[typ>>5]&(1<<(uint32(typ)&31)) == 0
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) accept(typ ICMPType) {
|
||||||
|
f.Data[typ>>5] &^= 1 << (uint32(typ) & 31)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) block(typ ICMPType) {
|
||||||
|
f.Data[typ>>5] |= 1 << (uint32(typ) & 31)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) setAll(block bool) {
|
||||||
|
for i := range f.Data {
|
||||||
|
if block {
|
||||||
|
f.Data[i] = 1<<32 - 1
|
||||||
|
} else {
|
||||||
|
f.Data[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) willBlock(typ ICMPType) bool {
|
||||||
|
return f.Data[typ>>5]&(1<<(uint32(typ)&31)) != 0
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
// 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 solaris
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) accept(typ ICMPType) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) block(typ ICMPType) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) setAll(block bool) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) willBlock(typ ICMPType) bool {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return false
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build nacl plan9
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) accept(typ ICMPType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) block(typ ICMPType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) setAll(block bool) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) willBlock(typ ICMPType) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
// 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"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
var icmpStringTests = []struct {
|
||||||
|
in ipv6.ICMPType
|
||||||
|
out string
|
||||||
|
}{
|
||||||
|
{ipv6.ICMPTypeDestinationUnreachable, "destination unreachable"},
|
||||||
|
|
||||||
|
{256, "<nil>"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestICMPString(t *testing.T) {
|
||||||
|
for _, tt := range icmpStringTests {
|
||||||
|
s := tt.in.String()
|
||||||
|
if s != tt.out {
|
||||||
|
t.Errorf("got %s; want %s", s, tt.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestICMPFilter(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
var f ipv6.ICMPFilter
|
||||||
|
for _, toggle := range []bool{false, true} {
|
||||||
|
f.SetAll(toggle)
|
||||||
|
for _, typ := range []ipv6.ICMPType{
|
||||||
|
ipv6.ICMPTypeDestinationUnreachable,
|
||||||
|
ipv6.ICMPTypeEchoReply,
|
||||||
|
ipv6.ICMPTypeNeighborSolicitation,
|
||||||
|
ipv6.ICMPTypeDuplicateAddressConfirmation,
|
||||||
|
} {
|
||||||
|
f.Accept(typ)
|
||||||
|
if f.WillBlock(typ) {
|
||||||
|
t.Errorf("ipv6.ICMPFilter.Set(%v, false) failed", typ)
|
||||||
|
}
|
||||||
|
f.Block(typ)
|
||||||
|
if !f.WillBlock(typ) {
|
||||||
|
t.Errorf("ipv6.ICMPFilter.Set(%v, true) failed", typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetICMPFilter(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip6:ipv6-icmp", "::1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
|
||||||
|
var f ipv6.ICMPFilter
|
||||||
|
f.SetAll(true)
|
||||||
|
f.Accept(ipv6.ICMPTypeEchoRequest)
|
||||||
|
f.Accept(ipv6.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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) accept(typ ICMPType) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) block(typ ICMPType) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) setAll(block bool) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPv6Filter) willBlock(typ ICMPType) bool {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return false
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
// 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 connector(t *testing.T, network, addr string, done chan<- bool) {
|
||||||
|
defer func() { done <- true }()
|
||||||
|
|
||||||
|
c, err := net.Dial(network, addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(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.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
+263
@@ -0,0 +1,263 @@
|
|||||||
|
// 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"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
var packetConnReadWriteMulticastUDPTests = []struct {
|
||||||
|
addr string
|
||||||
|
grp, src *net.UDPAddr
|
||||||
|
}{
|
||||||
|
{"[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727
|
||||||
|
|
||||||
|
{"[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771
|
||||||
|
}
|
||||||
|
|
||||||
|
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 %s", runtime.GOOS)
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip6", 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("udp6", tt.addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
grp := *tt.grp
|
||||||
|
grp.Port = c.LocalAddr().(*net.UDPAddr).Port
|
||||||
|
p := ipv6.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 MLDv2 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
cm := ipv6.ControlMessage{
|
||||||
|
TrafficClass: iana.DiffServAF11 | iana.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 {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
cm.HopLimit = i + 1
|
||||||
|
if n, err := p.WriteTo(wb, &cm, &grp); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if n != len(wb) {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
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.ParseIP("ff02::114")}, nil}, // see RFC 4727
|
||||||
|
|
||||||
|
{&net.IPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnReadWriteMulticastICMP(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 %s", runtime.GOOS)
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip6", 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("ip6:ipv6-icmp", "::")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, tt.grp.IP)
|
||||||
|
p := ipv6.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 MLDv2 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
cm := ipv6.ControlMessage{
|
||||||
|
TrafficClass: iana.DiffServAF11 | iana.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.Accept(ipv6.ICMPTypeEchoReply)
|
||||||
|
if err := p.SetICMPFilter(&f); err != nil {
|
||||||
|
t.Fatal(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.Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
psh = pshicmp
|
||||||
|
// Some platforms never allow to
|
||||||
|
// disable the kernel checksum
|
||||||
|
// processing.
|
||||||
|
p.SetChecksum(false, -1)
|
||||||
|
}
|
||||||
|
wb, err := (&icmp.Message{
|
||||||
|
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||||
|
Data: []byte("HELLO-R-U-THERE"),
|
||||||
|
},
|
||||||
|
}).Marshal(psh)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
cm.HopLimit = i + 1
|
||||||
|
if n, err := p.WriteTo(wb, &cm, 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 {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
t.Logf("rcvd cmsg: %v", cm)
|
||||||
|
if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
|
||||||
|
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+246
@@ -0,0 +1,246 @@
|
|||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
var udpMultipleGroupListenerTests = []net.Addr{
|
||||||
|
&net.UDPAddr{IP: net.ParseIP("ff02::114")}, // see RFC 4727
|
||||||
|
&net.UDPAddr{IP: net.ParseIP("ff02::1:114")},
|
||||||
|
&net.UDPAddr{IP: net.ParseIP("ff02::2:114")},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||||
|
c, err := net.ListenPacket("udp6", "[::]:0") // wildcard address with non-reusable port
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
var mift []*net.Interface
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
mift = append(mift, &ift[i])
|
||||||
|
}
|
||||||
|
for _, ifi := range mift {
|
||||||
|
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||||
|
c1, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c1.Close()
|
||||||
|
|
||||||
|
c2, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c2.Close()
|
||||||
|
|
||||||
|
var ps [2]*ipv6.PacketConn
|
||||||
|
ps[0] = ipv6.NewPacketConn(c1)
|
||||||
|
ps[1] = ipv6.NewPacketConn(c2)
|
||||||
|
var mift []*net.Interface
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, p := range ps {
|
||||||
|
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mift = append(mift, &ift[i])
|
||||||
|
}
|
||||||
|
for _, ifi := range mift {
|
||||||
|
for _, p := range ps {
|
||||||
|
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
|
||||||
|
type ml struct {
|
||||||
|
c *ipv6.PacketConn
|
||||||
|
ifi *net.Interface
|
||||||
|
}
|
||||||
|
var mlt []*ml
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
ip, ok := nettest.IsMulticastCapable("ip6", &ifi)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c, err := net.ListenPacket("udp6", fmt.Sprintf("[%s%%%s]:1024", ip.String(), ifi.Name)) // unicast address with non-reusable port
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||||
|
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.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip6:ipv6-icmp", "::") // wildcard address
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
|
||||||
|
var mift []*net.Interface
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
mift = append(mift, &ift[i])
|
||||||
|
}
|
||||||
|
for _, ifi := range mift {
|
||||||
|
if err := p.LeaveGroup(ifi, &gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin", "dragonfly", "openbsd": // platforms that return fe80::1%lo0: bind: can't assign requested address
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
|
||||||
|
type ml struct {
|
||||||
|
c *ipv6.PacketConn
|
||||||
|
ifi *net.Interface
|
||||||
|
}
|
||||||
|
var mlt []*ml
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
ip, ok := nettest.IsMulticastCapable("ip6", &ifi)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c, err := net.ListenPacket("ip6:ipv6-icmp", fmt.Sprintf("%s%%%s", ip.String(), ifi.Name)) // unicast address
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||||
|
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.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+157
@@ -0,0 +1,157 @@
|
|||||||
|
// 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"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
var packetConnMulticastSocketOptionTests = []struct {
|
||||||
|
net, proto, addr string
|
||||||
|
grp, src net.Addr
|
||||||
|
}{
|
||||||
|
{"udp6", "", "[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727
|
||||||
|
{"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff02::115")}, nil}, // see RFC 4727
|
||||||
|
|
||||||
|
{"udp6", "", "[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771
|
||||||
|
{"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff30::8000:2")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnMulticastSocketOptions(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip6", 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 == "ip6" && !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 := ipv6.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
|
if tt.src == nil {
|
||||||
|
testMulticastSocketOptions(t, p, ifi, tt.grp)
|
||||||
|
} else {
|
||||||
|
testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type testIPv6MulticastConn interface {
|
||||||
|
MulticastHopLimit() (int, error)
|
||||||
|
SetMulticastHopLimit(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 testIPv6MulticastConn, ifi *net.Interface, grp net.Addr) {
|
||||||
|
const hoplim = 255
|
||||||
|
if err := c.SetMulticastHopLimit(hoplim); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v, err := c.MulticastHopLimit(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
} else if v != hoplim {
|
||||||
|
t.Errorf("got %v; want %v", v, hoplim)
|
||||||
|
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 testIPv6MulticastConn, 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 MLDv2 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
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
// A payloadHandler represents the IPv6 datagram payload handler.
|
||||||
|
type payloadHandler struct {
|
||||||
|
net.PacketConn
|
||||||
|
rawOpt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil }
|
||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
// 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,!windows
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadFrom reads a payload of the received IPv6 datagram, from the
|
||||||
|
// endpoint c, copying the payload into b. It returns the number of
|
||||||
|
// bytes copied into b, the control message cm and the source address
|
||||||
|
// src of the received datagram.
|
||||||
|
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, nil, nil, syscall.EINVAL
|
||||||
|
}
|
||||||
|
oob := newControlMessage(&c.rawOpt)
|
||||||
|
var oobn int
|
||||||
|
switch c := c.PacketConn.(type) {
|
||||||
|
case *net.UDPConn:
|
||||||
|
if n, oobn, _, src, err = c.ReadMsgUDP(b, oob); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
case *net.IPConn:
|
||||||
|
if n, oobn, _, src, err = c.ReadMsgIP(b, oob); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0, nil, nil, errInvalidConnType
|
||||||
|
}
|
||||||
|
if cm, err = parseControlMessage(oob[:oobn]); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
if cm != nil {
|
||||||
|
cm.Src = netAddrToIP16(src)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo writes a payload of the IPv6 datagram, to the destination
|
||||||
|
// address dst through the endpoint c, copying the payload from b. It
|
||||||
|
// returns the number of bytes written. The control message cm allows
|
||||||
|
// the IPv6 header fields and the datagram path to be specified. 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() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
oob := marshalControlMessage(cm)
|
||||||
|
if dst == nil {
|
||||||
|
return 0, errMissingAddress
|
||||||
|
}
|
||||||
|
switch c := c.PacketConn.(type) {
|
||||||
|
case *net.UDPConn:
|
||||||
|
n, _, err = c.WriteMsgUDP(b, oob, dst.(*net.UDPAddr))
|
||||||
|
case *net.IPConn:
|
||||||
|
n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
|
||||||
|
default:
|
||||||
|
return 0, errInvalidConnType
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
// 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 windows
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadFrom reads a payload of the received IPv6 datagram, from the
|
||||||
|
// endpoint c, copying the payload into b. It returns the number of
|
||||||
|
// bytes copied into b, the control message cm and the source address
|
||||||
|
// src of the received datagram.
|
||||||
|
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, nil, nil, syscall.EINVAL
|
||||||
|
}
|
||||||
|
if n, src, err = c.PacketConn.ReadFrom(b); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo writes a payload of the IPv6 datagram, to the destination
|
||||||
|
// address dst through the endpoint c, copying the payload from b. It
|
||||||
|
// returns the number of bytes written. The control message cm allows
|
||||||
|
// the IPv6 header fields and the datagram path to be specified. 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() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
if dst == nil {
|
||||||
|
return 0, errMissingAddress
|
||||||
|
}
|
||||||
|
return c.PacketConn.WriteTo(b, dst)
|
||||||
|
}
|
||||||
+185
@@ -0,0 +1,185 @@
|
|||||||
|
// 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"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
|
||||||
|
c, err := net.ListenPacket("udp6", "[::1]:0")
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return c, dst, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkReadWriteNetUDP(b *testing.B) {
|
||||||
|
if !supportsIPv6 {
|
||||||
|
b.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
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 BenchmarkReadWriteIPv6UDP(b *testing.B) {
|
||||||
|
if !supportsIPv6 {
|
||||||
|
b.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
c, dst, err := benchmarkUDPListener()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||||
|
if err := p.SetControlMessage(cf, true); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
|
||||||
|
|
||||||
|
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
benchmarkReadWriteIPv6UDP(b, p, wb, rb, dst, ifi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkReadWriteIPv6UDP(b *testing.B, p *ipv6.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
|
||||||
|
cm := ipv6.ControlMessage{
|
||||||
|
TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
|
||||||
|
HopLimit: 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)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("udp6", "[::1]:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
|
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
|
||||||
|
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||||
|
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 := ipv6.ControlMessage{
|
||||||
|
TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
|
||||||
|
Src: net.IPv6loopback,
|
||||||
|
}
|
||||||
|
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("got %v; want %v", n, len(wb))
|
||||||
|
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()
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
// Sticky socket options
|
||||||
|
const (
|
||||||
|
ssoTrafficClass = iota // header field for unicast packet, RFC 3542
|
||||||
|
ssoHopLimit // header field for unicast packet, RFC 3493
|
||||||
|
ssoMulticastInterface // outbound interface for multicast packet, RFC 3493
|
||||||
|
ssoMulticastHopLimit // header field for multicast packet, RFC 3493
|
||||||
|
ssoMulticastLoopback // loopback for multicast packet, RFC 3493
|
||||||
|
ssoReceiveTrafficClass // header field on received packet, RFC 3542
|
||||||
|
ssoReceiveHopLimit // header field on received packet, RFC 2292 or 3542
|
||||||
|
ssoReceivePacketInfo // incbound or outbound packet path, RFC 2292 or 3542
|
||||||
|
ssoReceivePathMTU // path mtu, RFC 3542
|
||||||
|
ssoPathMTU // path mtu, RFC 3542
|
||||||
|
ssoChecksum // packet checksum, RFC 2292 or 3542
|
||||||
|
ssoICMPFilter // icmp filter, RFC 2292 or 3542
|
||||||
|
ssoJoinGroup // any-source multicast, RFC 3493
|
||||||
|
ssoLeaveGroup // any-source multicast, RFC 3493
|
||||||
|
ssoJoinSourceGroup // source-specific multicast
|
||||||
|
ssoLeaveSourceGroup // source-specific multicast
|
||||||
|
ssoBlockSourceGroup // any-source or source-specific multicast
|
||||||
|
ssoUnblockSourceGroup // any-source or source-specific multicast
|
||||||
|
ssoMax
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sticky socket option value types
|
||||||
|
const (
|
||||||
|
ssoTypeInt = iota + 1
|
||||||
|
ssoTypeInterface
|
||||||
|
ssoTypeICMPFilter
|
||||||
|
ssoTypeMTUInfo
|
||||||
|
ssoTypeIPMreq
|
||||||
|
ssoTypeGroupReq
|
||||||
|
ssoTypeGroupSourceReq
|
||||||
|
)
|
||||||
|
|
||||||
|
// A sockOpt represents a binding for sticky socket option.
|
||||||
|
type sockOpt struct {
|
||||||
|
level int // option level
|
||||||
|
name int // option name, must be equal or greater than 1
|
||||||
|
typ int // option value type, must be equal or greater than 1
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// 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"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setsockoptIPMreq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
|
var mreq sysIPv6Mreq
|
||||||
|
copy(mreq.Multiaddr[:], grp)
|
||||||
|
if ifi != nil {
|
||||||
|
mreq.setIfindex(ifi.Index)
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&mreq), sysSizeofIPv6Mreq))
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// 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 setsockoptIPMreq(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
|
var mreq sysIPv6Mreq
|
||||||
|
copy(mreq.Multiaddr[:], grp)
|
||||||
|
if ifi != nil {
|
||||||
|
mreq.setIfindex(ifi.Index)
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&mreq)), sysSizeofIPv6Mreq))
|
||||||
|
}
|
||||||
+17
@@ -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 ipv6
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func setsockoptGroupReq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockoptGroupSourceReq(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
// 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 ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var freebsd32o64 bool
|
||||||
|
|
||||||
|
func setsockoptGroupReq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
|
var gr sysGroupReq
|
||||||
|
if ifi != nil {
|
||||||
|
gr.Interface = uint32(ifi.Index)
|
||||||
|
}
|
||||||
|
gr.setGroup(grp)
|
||||||
|
var p unsafe.Pointer
|
||||||
|
var l sysSockoptLen
|
||||||
|
if freebsd32o64 {
|
||||||
|
var d [sysSizeofGroupReq + 4]byte
|
||||||
|
s := (*[sysSizeofGroupReq]byte)(unsafe.Pointer(&gr))
|
||||||
|
copy(d[:4], s[:4])
|
||||||
|
copy(d[8:], s[4:])
|
||||||
|
p = unsafe.Pointer(&d[0])
|
||||||
|
l = sysSizeofGroupReq + 4
|
||||||
|
} else {
|
||||||
|
p = unsafe.Pointer(&gr)
|
||||||
|
l = sysSizeofGroupReq
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, p, l))
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockoptGroupSourceReq(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||||
|
var gsr sysGroupSourceReq
|
||||||
|
if ifi != nil {
|
||||||
|
gsr.Interface = uint32(ifi.Index)
|
||||||
|
}
|
||||||
|
gsr.setSourceGroup(grp, src)
|
||||||
|
var p unsafe.Pointer
|
||||||
|
var l sysSockoptLen
|
||||||
|
if freebsd32o64 {
|
||||||
|
var d [sysSizeofGroupSourceReq + 4]byte
|
||||||
|
s := (*[sysSizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))
|
||||||
|
copy(d[:4], s[:4])
|
||||||
|
copy(d[8:], s[4:])
|
||||||
|
p = unsafe.Pointer(&d[0])
|
||||||
|
l = sysSizeofGroupSourceReq + 4
|
||||||
|
} else {
|
||||||
|
p = unsafe.Pointer(&gsr)
|
||||||
|
l = sysSizeofGroupSourceReq
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, p, l))
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func getMTUInfo(fd int, opt *sockOpt) (*net.Interface, int, error) {
|
||||||
|
return nil, 0, errOpNoSupport
|
||||||
|
}
|
||||||
+133
@@ -0,0 +1,133 @@
|
|||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
var supportsIPv6 bool = nettest.SupportsIPv6()
|
||||||
|
|
||||||
|
func TestConnInitiatorPathMTU(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
ln, err := net.Listen("tcp6", "[::1]:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
done := make(chan bool)
|
||||||
|
go acceptor(t, ln, done)
|
||||||
|
|
||||||
|
c, err := net.Dial("tcp6", ln.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
if pmtu, err := ipv6.NewConn(c).PathMTU(); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin": // older darwin kernels don't support IPV6_PATHMTU option
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
default:
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Logf("path mtu for %v: %v", c.RemoteAddr(), pmtu)
|
||||||
|
}
|
||||||
|
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConnResponderPathMTU(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
ln, err := net.Listen("tcp6", "[::1]:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
done := make(chan bool)
|
||||||
|
go connector(t, "tcp6", ln.Addr().String(), done)
|
||||||
|
|
||||||
|
c, err := ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
if pmtu, err := ipv6.NewConn(c).PathMTU(); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin": // older darwin kernels don't support IPV6_PATHMTU option
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
default:
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Logf("path mtu for %v: %v", c.RemoteAddr(), pmtu)
|
||||||
|
}
|
||||||
|
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnChecksum(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolOSPFIGP), "::") // OSPF for IPv6
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
offset := 12 // see RFC 5340
|
||||||
|
|
||||||
|
for _, toggle := range []bool{false, true} {
|
||||||
|
if err := p.SetChecksum(toggle, offset); err != nil {
|
||||||
|
if toggle {
|
||||||
|
t.Fatalf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err)
|
||||||
|
} else {
|
||||||
|
// Some platforms never allow to disable the kernel
|
||||||
|
// checksum processing.
|
||||||
|
t.Logf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if on, offset, err := p.Checksum(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
t.Logf("kernel checksum processing enabled=%v, offset=%v", on, offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+122
@@ -0,0 +1,122 @@
|
|||||||
|
// 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"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getInt(fd int, opt *sockOpt) (int, error) {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInt {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
var i int32
|
||||||
|
l := sysSockoptLen(4)
|
||||||
|
if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
|
||||||
|
return 0, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
return int(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setInt(fd int, opt *sockOpt, v int) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInt {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
i := int32(v)
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), sysSockoptLen(4)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInterface(fd int, opt *sockOpt) (*net.Interface, error) {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
var i int32
|
||||||
|
l := sysSockoptLen(4)
|
||||||
|
if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
|
||||||
|
return nil, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
ifi, err := net.InterfaceByIndex(int(i))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ifi, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setInterface(fd int, opt *sockOpt, ifi *net.Interface) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
var i int32
|
||||||
|
if ifi != nil {
|
||||||
|
i = int32(ifi.Index)
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), sysSockoptLen(4)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getICMPFilter(fd int, opt *sockOpt) (*ICMPFilter, error) {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
var f ICMPFilter
|
||||||
|
l := sysSockoptLen(sysSizeofICMPv6Filter)
|
||||||
|
if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), &l); err != nil {
|
||||||
|
return nil, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
return &f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setICMPFilter(fd int, opt *sockOpt, f *ICMPFilter) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), sysSizeofICMPv6Filter))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMTUInfo(fd int, opt *sockOpt) (*net.Interface, int, error) {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeMTUInfo {
|
||||||
|
return nil, 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
var mi sysIPv6Mtuinfo
|
||||||
|
l := sysSockoptLen(sysSizeofIPv6Mtuinfo)
|
||||||
|
if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&mi), &l); err != nil {
|
||||||
|
return nil, 0, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
if mi.Addr.Scope_id == 0 {
|
||||||
|
return nil, int(mi.Mtu), nil
|
||||||
|
}
|
||||||
|
ifi, err := net.InterfaceByIndex(int(mi.Addr.Scope_id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
return ifi, int(mi.Mtu), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setGroup(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
|
if opt.name < 1 {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
switch opt.typ {
|
||||||
|
case ssoTypeIPMreq:
|
||||||
|
return setsockoptIPMreq(fd, opt, ifi, grp)
|
||||||
|
case ssoTypeGroupReq:
|
||||||
|
return setsockoptGroupReq(fd, opt, 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, ifi, grp, src)
|
||||||
|
}
|
||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
// 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 getInt(fd syscall.Handle, opt *sockOpt) (int, error) {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInt {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
var i int32
|
||||||
|
l := int32(4)
|
||||||
|
if err := syscall.Getsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), &l); err != nil {
|
||||||
|
return 0, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
return int(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setInt(fd syscall.Handle, opt *sockOpt, v int) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInt {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
i := int32(v)
|
||||||
|
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), 4))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInterface(fd syscall.Handle, opt *sockOpt) (*net.Interface, error) {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
var i int32
|
||||||
|
l := int32(4)
|
||||||
|
if err := syscall.Getsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), &l); err != nil {
|
||||||
|
return nil, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
ifi, err := net.InterfaceByIndex(int(i))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ifi, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setInterface(fd syscall.Handle, opt *sockOpt, ifi *net.Interface) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
var i int32
|
||||||
|
if ifi != nil {
|
||||||
|
i = int32(ifi.Index)
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), 4))
|
||||||
|
}
|
||||||
|
|
||||||
|
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 getMTUInfo(fd syscall.Handle, opt *sockOpt) (*net.Interface, int, error) {
|
||||||
|
return nil, 0, 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, ifi, grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setSourceGroup(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
// 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 netbsd openbsd
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockoptLen int32
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
|
ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
|
||||||
|
ctlHopLimit: {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
|
||||||
|
ctlPacketInfo: {sysIPV6_PKTINFO, sysSizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
|
||||||
|
ctlNextHop: {sysIPV6_NEXTHOP, sysSizeofSockaddrInet6, marshalNextHop, parseNextHop},
|
||||||
|
ctlPathMTU: {sysIPV6_PATHMTU, sysSizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU},
|
||||||
|
}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoTrafficClass: {iana.ProtocolIPv6, sysIPV6_TCLASS, ssoTypeInt},
|
||||||
|
ssoHopLimit: {iana.ProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastInterface: {iana.ProtocolIPv6, sysIPV6_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastHopLimit: {iana.ProtocolIPv6, sysIPV6_MULTICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastLoopback: {iana.ProtocolIPv6, sysIPV6_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoReceiveTrafficClass: {iana.ProtocolIPv6, sysIPV6_RECVTCLASS, ssoTypeInt},
|
||||||
|
ssoReceiveHopLimit: {iana.ProtocolIPv6, sysIPV6_RECVHOPLIMIT, ssoTypeInt},
|
||||||
|
ssoReceivePacketInfo: {iana.ProtocolIPv6, sysIPV6_RECVPKTINFO, ssoTypeInt},
|
||||||
|
ssoReceivePathMTU: {iana.ProtocolIPv6, sysIPV6_RECVPATHMTU, ssoTypeInt},
|
||||||
|
ssoPathMTU: {iana.ProtocolIPv6, sysIPV6_PATHMTU, ssoTypeMTUInfo},
|
||||||
|
ssoChecksum: {iana.ProtocolIPv6, sysIPV6_CHECKSUM, ssoTypeInt},
|
||||||
|
ssoICMPFilter: {iana.ProtocolIPv6ICMP, sysICMP6_FILTER, ssoTypeICMPFilter},
|
||||||
|
ssoJoinGroup: {iana.ProtocolIPv6, sysIPV6_JOIN_GROUP, ssoTypeIPMreq},
|
||||||
|
ssoLeaveGroup: {iana.ProtocolIPv6, sysIPV6_LEAVE_GROUP, ssoTypeIPMreq},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (sa *sysSockaddrInet6) setSockaddr(ip net.IP, i int) {
|
||||||
|
sa.Len = sysSizeofSockaddrInet6
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
sa.Scope_id = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *sysInet6Pktinfo) setIfindex(i int) {
|
||||||
|
pi.Ifindex = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mreq *sysIPv6Mreq) setIfindex(i int) {
|
||||||
|
mreq.Interface = uint32(i)
|
||||||
|
}
|
||||||
+135
@@ -0,0 +1,135 @@
|
|||||||
|
// 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"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockoptLen int32
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
|
ctlHopLimit: {sysIPV6_2292HOPLIMIT, 4, marshal2292HopLimit, parseHopLimit},
|
||||||
|
ctlPacketInfo: {sysIPV6_2292PKTINFO, sysSizeofInet6Pktinfo, marshal2292PacketInfo, parsePacketInfo},
|
||||||
|
}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoHopLimit: {iana.ProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastInterface: {iana.ProtocolIPv6, sysIPV6_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastHopLimit: {iana.ProtocolIPv6, sysIPV6_MULTICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastLoopback: {iana.ProtocolIPv6, sysIPV6_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoReceiveHopLimit: {iana.ProtocolIPv6, sysIPV6_2292HOPLIMIT, ssoTypeInt},
|
||||||
|
ssoReceivePacketInfo: {iana.ProtocolIPv6, sysIPV6_2292PKTINFO, ssoTypeInt},
|
||||||
|
ssoChecksum: {iana.ProtocolIPv6, sysIPV6_CHECKSUM, ssoTypeInt},
|
||||||
|
ssoICMPFilter: {iana.ProtocolIPv6ICMP, sysICMP6_FILTER, ssoTypeICMPFilter},
|
||||||
|
ssoJoinGroup: {iana.ProtocolIPv6, sysIPV6_JOIN_GROUP, ssoTypeIPMreq},
|
||||||
|
ssoLeaveGroup: {iana.ProtocolIPv6, sysIPV6_LEAVE_GROUP, ssoTypeIPMreq},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Seems like kern.osreldate is veiled on latest OS X. We use
|
||||||
|
// kern.osrelease instead.
|
||||||
|
osver, err := syscall.Sysctl("kern.osrelease")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
for i = range osver {
|
||||||
|
if osver[i] == '.' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The IP_PKTINFO and protocol-independent multicast API were
|
||||||
|
// introduced in OS X 10.7 (Darwin 11.0.0). But it looks like
|
||||||
|
// those features require OS X 10.8 (Darwin 12.0.0) and above.
|
||||||
|
// See http://support.apple.com/kb/HT1633.
|
||||||
|
if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '2' {
|
||||||
|
ctlOpts[ctlTrafficClass].name = sysIPV6_TCLASS
|
||||||
|
ctlOpts[ctlTrafficClass].length = 4
|
||||||
|
ctlOpts[ctlTrafficClass].marshal = marshalTrafficClass
|
||||||
|
ctlOpts[ctlTrafficClass].parse = parseTrafficClass
|
||||||
|
ctlOpts[ctlHopLimit].name = sysIPV6_HOPLIMIT
|
||||||
|
ctlOpts[ctlHopLimit].marshal = marshalHopLimit
|
||||||
|
ctlOpts[ctlPacketInfo].name = sysIPV6_PKTINFO
|
||||||
|
ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
|
||||||
|
ctlOpts[ctlNextHop].name = sysIPV6_NEXTHOP
|
||||||
|
ctlOpts[ctlNextHop].length = sysSizeofSockaddrInet6
|
||||||
|
ctlOpts[ctlNextHop].marshal = marshalNextHop
|
||||||
|
ctlOpts[ctlNextHop].parse = parseNextHop
|
||||||
|
ctlOpts[ctlPathMTU].name = sysIPV6_PATHMTU
|
||||||
|
ctlOpts[ctlPathMTU].length = sysSizeofIPv6Mtuinfo
|
||||||
|
ctlOpts[ctlPathMTU].marshal = marshalPathMTU
|
||||||
|
ctlOpts[ctlPathMTU].parse = parsePathMTU
|
||||||
|
sockOpts[ssoTrafficClass].level = iana.ProtocolIPv6
|
||||||
|
sockOpts[ssoTrafficClass].name = sysIPV6_TCLASS
|
||||||
|
sockOpts[ssoTrafficClass].typ = ssoTypeInt
|
||||||
|
sockOpts[ssoReceiveTrafficClass].level = iana.ProtocolIPv6
|
||||||
|
sockOpts[ssoReceiveTrafficClass].name = sysIPV6_RECVTCLASS
|
||||||
|
sockOpts[ssoReceiveTrafficClass].typ = ssoTypeInt
|
||||||
|
sockOpts[ssoReceiveHopLimit].name = sysIPV6_RECVHOPLIMIT
|
||||||
|
sockOpts[ssoReceivePacketInfo].name = sysIPV6_RECVPKTINFO
|
||||||
|
sockOpts[ssoReceivePathMTU].level = iana.ProtocolIPv6
|
||||||
|
sockOpts[ssoReceivePathMTU].name = sysIPV6_RECVPATHMTU
|
||||||
|
sockOpts[ssoReceivePathMTU].typ = ssoTypeInt
|
||||||
|
sockOpts[ssoPathMTU].level = iana.ProtocolIPv6
|
||||||
|
sockOpts[ssoPathMTU].name = sysIPV6_PATHMTU
|
||||||
|
sockOpts[ssoPathMTU].typ = ssoTypeMTUInfo
|
||||||
|
sockOpts[ssoJoinGroup].name = sysMCAST_JOIN_GROUP
|
||||||
|
sockOpts[ssoJoinGroup].typ = ssoTypeGroupReq
|
||||||
|
sockOpts[ssoLeaveGroup].name = sysMCAST_LEAVE_GROUP
|
||||||
|
sockOpts[ssoLeaveGroup].typ = ssoTypeGroupReq
|
||||||
|
sockOpts[ssoJoinSourceGroup].level = iana.ProtocolIPv6
|
||||||
|
sockOpts[ssoJoinSourceGroup].name = sysMCAST_JOIN_SOURCE_GROUP
|
||||||
|
sockOpts[ssoJoinSourceGroup].typ = ssoTypeGroupSourceReq
|
||||||
|
sockOpts[ssoLeaveSourceGroup].level = iana.ProtocolIPv6
|
||||||
|
sockOpts[ssoLeaveSourceGroup].name = sysMCAST_LEAVE_SOURCE_GROUP
|
||||||
|
sockOpts[ssoLeaveSourceGroup].typ = ssoTypeGroupSourceReq
|
||||||
|
sockOpts[ssoBlockSourceGroup].level = iana.ProtocolIPv6
|
||||||
|
sockOpts[ssoBlockSourceGroup].name = sysMCAST_BLOCK_SOURCE
|
||||||
|
sockOpts[ssoBlockSourceGroup].typ = ssoTypeGroupSourceReq
|
||||||
|
sockOpts[ssoUnblockSourceGroup].level = iana.ProtocolIPv6
|
||||||
|
sockOpts[ssoUnblockSourceGroup].name = sysMCAST_UNBLOCK_SOURCE
|
||||||
|
sockOpts[ssoUnblockSourceGroup].typ = ssoTypeGroupSourceReq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sa *sysSockaddrInet6) setSockaddr(ip net.IP, i int) {
|
||||||
|
sa.Len = sysSizeofSockaddrInet6
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
sa.Scope_id = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *sysInet6Pktinfo) setIfindex(i int) {
|
||||||
|
pi.Ifindex = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mreq *sysIPv6Mreq) setIfindex(i int) {
|
||||||
|
mreq.Interface = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gr *sysGroupReq) setGroup(grp net.IP) {
|
||||||
|
sa := (*sysSockaddrInet6)(unsafe.Pointer(&gr.Pad_cgo_0[0]))
|
||||||
|
sa.Len = sysSizeofSockaddrInet6
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
|
||||||
|
sa := (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Pad_cgo_0[0]))
|
||||||
|
sa.Len = sysSizeofSockaddrInet6
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
sa = (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Pad_cgo_1[0]))
|
||||||
|
sa.Len = sysSizeofSockaddrInet6
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], src)
|
||||||
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
// 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"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockoptLen int32
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
|
ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
|
||||||
|
ctlHopLimit: {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
|
||||||
|
ctlPacketInfo: {sysIPV6_PKTINFO, sysSizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
|
||||||
|
ctlNextHop: {sysIPV6_NEXTHOP, sysSizeofSockaddrInet6, marshalNextHop, parseNextHop},
|
||||||
|
ctlPathMTU: {sysIPV6_PATHMTU, sysSizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU},
|
||||||
|
}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoTrafficClass: {iana.ProtocolIPv6, sysIPV6_TCLASS, ssoTypeInt},
|
||||||
|
ssoHopLimit: {iana.ProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastInterface: {iana.ProtocolIPv6, sysIPV6_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastHopLimit: {iana.ProtocolIPv6, sysIPV6_MULTICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastLoopback: {iana.ProtocolIPv6, sysIPV6_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoReceiveTrafficClass: {iana.ProtocolIPv6, sysIPV6_RECVTCLASS, ssoTypeInt},
|
||||||
|
ssoReceiveHopLimit: {iana.ProtocolIPv6, sysIPV6_RECVHOPLIMIT, ssoTypeInt},
|
||||||
|
ssoReceivePacketInfo: {iana.ProtocolIPv6, sysIPV6_RECVPKTINFO, ssoTypeInt},
|
||||||
|
ssoReceivePathMTU: {iana.ProtocolIPv6, sysIPV6_RECVPATHMTU, ssoTypeInt},
|
||||||
|
ssoPathMTU: {iana.ProtocolIPv6, sysIPV6_PATHMTU, ssoTypeMTUInfo},
|
||||||
|
ssoChecksum: {iana.ProtocolIPv6, sysIPV6_CHECKSUM, ssoTypeInt},
|
||||||
|
ssoICMPFilter: {iana.ProtocolIPv6ICMP, sysICMP6_FILTER, ssoTypeICMPFilter},
|
||||||
|
ssoJoinGroup: {iana.ProtocolIPv6, sysMCAST_JOIN_GROUP, ssoTypeGroupReq},
|
||||||
|
ssoLeaveGroup: {iana.ProtocolIPv6, sysMCAST_LEAVE_GROUP, ssoTypeGroupReq},
|
||||||
|
ssoJoinSourceGroup: {iana.ProtocolIPv6, sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||||
|
ssoLeaveSourceGroup: {iana.ProtocolIPv6, sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||||
|
ssoBlockSourceGroup: {iana.ProtocolIPv6, sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||||
|
ssoUnblockSourceGroup: {iana.ProtocolIPv6, sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
|
||||||
|
archs, _ := syscall.Sysctl("kern.supported_archs")
|
||||||
|
for _, s := range strings.Fields(archs) {
|
||||||
|
if s == "amd64" {
|
||||||
|
freebsd32o64 = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sa *sysSockaddrInet6) setSockaddr(ip net.IP, i int) {
|
||||||
|
sa.Len = sysSizeofSockaddrInet6
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
sa.Scope_id = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *sysInet6Pktinfo) setIfindex(i int) {
|
||||||
|
pi.Ifindex = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mreq *sysIPv6Mreq) setIfindex(i int) {
|
||||||
|
mreq.Interface = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gr *sysGroupReq) setGroup(grp net.IP) {
|
||||||
|
sa := (*sysSockaddrInet6)(unsafe.Pointer(&gr.Group))
|
||||||
|
sa.Len = sysSizeofSockaddrInet6
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
|
||||||
|
sa := (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Group))
|
||||||
|
sa.Len = sysSizeofSockaddrInet6
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
sa = (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Source))
|
||||||
|
sa.Len = sysSizeofSockaddrInet6
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], src)
|
||||||
|
}
|
||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
// 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"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockoptLen int32
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
|
ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
|
||||||
|
ctlHopLimit: {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
|
||||||
|
ctlPacketInfo: {sysIPV6_PKTINFO, sysSizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
|
||||||
|
ctlPathMTU: {sysIPV6_PATHMTU, sysSizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU},
|
||||||
|
}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoTrafficClass: {iana.ProtocolIPv6, sysIPV6_TCLASS, ssoTypeInt},
|
||||||
|
ssoHopLimit: {iana.ProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastInterface: {iana.ProtocolIPv6, sysIPV6_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastHopLimit: {iana.ProtocolIPv6, sysIPV6_MULTICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastLoopback: {iana.ProtocolIPv6, sysIPV6_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoReceiveTrafficClass: {iana.ProtocolIPv6, sysIPV6_RECVTCLASS, ssoTypeInt},
|
||||||
|
ssoReceiveHopLimit: {iana.ProtocolIPv6, sysIPV6_RECVHOPLIMIT, ssoTypeInt},
|
||||||
|
ssoReceivePacketInfo: {iana.ProtocolIPv6, sysIPV6_RECVPKTINFO, ssoTypeInt},
|
||||||
|
ssoReceivePathMTU: {iana.ProtocolIPv6, sysIPV6_RECVPATHMTU, ssoTypeInt},
|
||||||
|
ssoPathMTU: {iana.ProtocolIPv6, sysIPV6_PATHMTU, ssoTypeMTUInfo},
|
||||||
|
ssoChecksum: {iana.ProtocolReserved, sysIPV6_CHECKSUM, ssoTypeInt},
|
||||||
|
ssoICMPFilter: {iana.ProtocolIPv6ICMP, sysICMPV6_FILTER, ssoTypeICMPFilter},
|
||||||
|
ssoJoinGroup: {iana.ProtocolIPv6, sysMCAST_JOIN_GROUP, ssoTypeGroupReq},
|
||||||
|
ssoLeaveGroup: {iana.ProtocolIPv6, sysMCAST_LEAVE_GROUP, ssoTypeGroupReq},
|
||||||
|
ssoJoinSourceGroup: {iana.ProtocolIPv6, sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||||
|
ssoLeaveSourceGroup: {iana.ProtocolIPv6, sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||||
|
ssoBlockSourceGroup: {iana.ProtocolIPv6, sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||||
|
ssoUnblockSourceGroup: {iana.ProtocolIPv6, sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (sa *sysSockaddrInet6) setSockaddr(ip net.IP, i int) {
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
sa.Scope_id = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *sysInet6Pktinfo) setIfindex(i int) {
|
||||||
|
pi.Ifindex = int32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mreq *sysIPv6Mreq) setIfindex(i int) {
|
||||||
|
mreq.Ifindex = int32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gr *sysGroupReq) setGroup(grp net.IP) {
|
||||||
|
sa := (*sysSockaddrInet6)(unsafe.Pointer(&gr.Group))
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
|
||||||
|
sa := (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Group))
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
sa = (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Source))
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], src)
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// 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 nacl plan9 solaris
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
type sysSockoptLen int32
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{}
|
||||||
|
)
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// See ws2tcpip.h.
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x4
|
||||||
|
sysIPV6_MULTICAST_IF = 0x9
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0xa
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0xb
|
||||||
|
sysIPV6_JOIN_GROUP = 0xc
|
||||||
|
sysIPV6_LEAVE_GROUP = 0xd
|
||||||
|
sysIPV6_PKTINFO = 0x13
|
||||||
|
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Family uint16
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoHopLimit: {iana.ProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastInterface: {iana.ProtocolIPv6, sysIPV6_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastHopLimit: {iana.ProtocolIPv6, sysIPV6_MULTICAST_HOPS, ssoTypeInt},
|
||||||
|
ssoMulticastLoopback: {iana.ProtocolIPv6, sysIPV6_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoJoinGroup: {iana.ProtocolIPv6, sysIPV6_JOIN_GROUP, ssoTypeIPMreq},
|
||||||
|
ssoLeaveGroup: {iana.ProtocolIPv6, sysIPV6_LEAVE_GROUP, ssoTypeIPMreq},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (sa *sysSockaddrInet6) setSockaddr(ip net.IP, i int) {
|
||||||
|
sa.Family = syscall.AF_INET6
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
sa.Scope_id = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mreq *sysIPv6Mreq) setIfindex(i int) {
|
||||||
|
mreq.Interface = uint32(i)
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysGETSOCKOPT = 0xf
|
||||||
|
sysSETSOCKOPT = 0xe
|
||||||
|
)
|
||||||
|
|
||||||
|
func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
|
||||||
|
|
||||||
|
func getsockopt(fd, level, name int, v unsafe.Pointer, l *sysSockoptLen) error {
|
||||||
|
if _, errno := socketcall(sysGETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
||||||
|
return error(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockopt(fd, level, name int, v unsafe.Pointer, l sysSockoptLen) error {
|
||||||
|
if _, errno := socketcall(sysSETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
|
||||||
|
return error(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux,!386 netbsd openbsd
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getsockopt(fd, level, name int, v unsafe.Pointer, l *sysSockoptLen) error {
|
||||||
|
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
||||||
|
return error(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockopt(fd, level, name int, v unsafe.Pointer, l sysSockoptLen) error {
|
||||||
|
if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
|
||||||
|
return error(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// 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 go1.2
|
||||||
|
|
||||||
|
TEXT ·socketcall(SB),4,$0-36
|
||||||
|
JMP syscall·socketcall(SB)
|
||||||
+185
@@ -0,0 +1,185 @@
|
|||||||
|
// 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"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("udp6", "[::1]:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
|
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cm := ipv6.ControlMessage{
|
||||||
|
TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
|
||||||
|
Src: net.IPv6loopback,
|
||||||
|
}
|
||||||
|
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||||
|
ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
|
||||||
|
if ifi != nil {
|
||||||
|
cm.IfIndex = ifi.Index
|
||||||
|
}
|
||||||
|
wb := []byte("HELLO-R-U-THERE")
|
||||||
|
|
||||||
|
for i, toggle := range []bool{true, false, true} {
|
||||||
|
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||||
|
if nettest.ProtocolNotSupported(err) {
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cm.HopLimit = i + 1
|
||||||
|
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if n != len(wb) {
|
||||||
|
t.Fatalf("got %v; want %v", n, len(wb))
|
||||||
|
}
|
||||||
|
rb := make([]byte, 128)
|
||||||
|
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip6:ipv6-icmp", "::1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
|
dst, err := net.ResolveIPAddr("ip6", "::1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP)
|
||||||
|
cm := ipv6.ControlMessage{
|
||||||
|
TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
|
||||||
|
Src: net.IPv6loopback,
|
||||||
|
}
|
||||||
|
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||||
|
ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
|
||||||
|
if ifi != nil {
|
||||||
|
cm.IfIndex = ifi.Index
|
||||||
|
}
|
||||||
|
|
||||||
|
var f ipv6.ICMPFilter
|
||||||
|
f.SetAll(true)
|
||||||
|
f.Accept(ipv6.ICMPTypeEchoReply)
|
||||||
|
if err := p.SetICMPFilter(&f); err != nil {
|
||||||
|
t.Fatal(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.Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
psh = pshicmp
|
||||||
|
// Some platforms never allow to disable the
|
||||||
|
// kernel checksum processing.
|
||||||
|
p.SetChecksum(false, -1)
|
||||||
|
}
|
||||||
|
wb, err := (&icmp.Message{
|
||||||
|
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||||
|
Data: []byte("HELLO-R-U-THERE"),
|
||||||
|
},
|
||||||
|
}).Marshal(psh)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||||
|
if nettest.ProtocolNotSupported(err) {
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cm.HopLimit = i + 1
|
||||||
|
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if n != len(wb) {
|
||||||
|
t.Fatalf("got %v; want %v", n, len(wb))
|
||||||
|
}
|
||||||
|
rb := make([]byte, 128)
|
||||||
|
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n, cm, _, err := p.ReadFrom(rb); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
t.Logf("rcvd cmsg: %v", cm)
|
||||||
|
if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
|
||||||
|
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+111
@@ -0,0 +1,111 @@
|
|||||||
|
// 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"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConnUnicastSocketOptions(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
ln, err := net.Listen("tcp6", "[::1]:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
done := make(chan bool)
|
||||||
|
go acceptor(t, ln, done)
|
||||||
|
|
||||||
|
c, err := net.Dial("tcp6", ln.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
testUnicastSocketOptions(t, ipv6.NewConn(c))
|
||||||
|
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
|
||||||
|
var packetConnUnicastSocketOptionTests = []struct {
|
||||||
|
net, proto, addr string
|
||||||
|
}{
|
||||||
|
{"udp6", "", "[::1]:0"},
|
||||||
|
{"ip6", ":ipv6-icmp", "::1"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnUnicastSocketOptions(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !supportsIPv6 {
|
||||||
|
t.Skip("ipv6 is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
m, ok := nettest.SupportsRawIPSocket()
|
||||||
|
for _, tt := range packetConnUnicastSocketOptionTests {
|
||||||
|
if tt.net == "ip6" && !ok {
|
||||||
|
t.Log(m)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
testUnicastSocketOptions(t, ipv6.NewPacketConn(c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type testIPv6UnicastConn interface {
|
||||||
|
TrafficClass() (int, error)
|
||||||
|
SetTrafficClass(int) error
|
||||||
|
HopLimit() (int, error)
|
||||||
|
SetHopLimit(int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUnicastSocketOptions(t *testing.T, c testIPv6UnicastConn) {
|
||||||
|
tclass := iana.DiffServCS0 | iana.NotECNTransport
|
||||||
|
if err := c.SetTrafficClass(tclass); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin": // older darwin kernels don't support IPV6_TCLASS option
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
goto next
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if v, err := c.TrafficClass(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if v != tclass {
|
||||||
|
t.Fatalf("got %v; want %v", v, tclass)
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
hoplim := 255
|
||||||
|
if err := c.SetHopLimit(hoplim); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if v, err := c.HopLimit(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if v != hoplim {
|
||||||
|
t.Fatalf("got %v; want %v", v, hoplim)
|
||||||
|
}
|
||||||
|
}
|
||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_darwin.go
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x4
|
||||||
|
sysIPV6_MULTICAST_IF = 0x9
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0xa
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0xb
|
||||||
|
sysIPV6_JOIN_GROUP = 0xc
|
||||||
|
sysIPV6_LEAVE_GROUP = 0xd
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE = 0xe
|
||||||
|
sysICMP6_FILTER = 0x12
|
||||||
|
sysIPV6_2292PKTINFO = 0x13
|
||||||
|
sysIPV6_2292HOPLIMIT = 0x14
|
||||||
|
sysIPV6_2292NEXTHOP = 0x15
|
||||||
|
sysIPV6_2292HOPOPTS = 0x16
|
||||||
|
sysIPV6_2292DSTOPTS = 0x17
|
||||||
|
sysIPV6_2292RTHDR = 0x18
|
||||||
|
|
||||||
|
sysIPV6_2292PKTOPTIONS = 0x19
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = 0x1a
|
||||||
|
sysIPV6_V6ONLY = 0x1b
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x23
|
||||||
|
sysIPV6_TCLASS = 0x24
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x39
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x3d
|
||||||
|
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x25
|
||||||
|
sysIPV6_RECVRTHDR = 0x26
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x27
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x28
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = 0x2a
|
||||||
|
sysIPV6_RECVPATHMTU = 0x2b
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = 0x2c
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = 0x2e
|
||||||
|
sysIPV6_HOPLIMIT = 0x2f
|
||||||
|
sysIPV6_NEXTHOP = 0x30
|
||||||
|
sysIPV6_HOPOPTS = 0x31
|
||||||
|
sysIPV6_DSTOPTS = 0x32
|
||||||
|
sysIPV6_RTHDR = 0x33
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = 0x3b
|
||||||
|
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_PREFER_TEMPADDR = 0x3f
|
||||||
|
|
||||||
|
sysIPV6_MSFILTER = 0x4a
|
||||||
|
sysMCAST_JOIN_GROUP = 0x50
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x51
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x52
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x53
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x54
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x55
|
||||||
|
|
||||||
|
sysIPV6_BOUND_IF = 0x7d
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = 0x0
|
||||||
|
sysIPV6_PORTRANGE_HIGH = 0x1
|
||||||
|
sysIPV6_PORTRANGE_LOW = 0x2
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x84
|
||||||
|
sysSizeofGroupSourceReq = 0x104
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
X__ss_pad1 [6]int8
|
||||||
|
X__ss_align int64
|
||||||
|
X__ss_pad2 [112]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Filt [8]uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [128]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [128]byte
|
||||||
|
Pad_cgo_1 [128]byte
|
||||||
|
}
|
||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_dragonfly.go
|
||||||
|
|
||||||
|
// +build dragonfly
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x4
|
||||||
|
sysIPV6_MULTICAST_IF = 0x9
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0xa
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0xb
|
||||||
|
sysIPV6_JOIN_GROUP = 0xc
|
||||||
|
sysIPV6_LEAVE_GROUP = 0xd
|
||||||
|
sysIPV6_PORTRANGE = 0xe
|
||||||
|
sysICMP6_FILTER = 0x12
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = 0x1a
|
||||||
|
sysIPV6_V6ONLY = 0x1b
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x23
|
||||||
|
sysIPV6_RECVPKTINFO = 0x24
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x25
|
||||||
|
sysIPV6_RECVRTHDR = 0x26
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x27
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x28
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = 0x2a
|
||||||
|
sysIPV6_RECVPATHMTU = 0x2b
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = 0x2c
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = 0x2e
|
||||||
|
sysIPV6_HOPLIMIT = 0x2f
|
||||||
|
sysIPV6_NEXTHOP = 0x30
|
||||||
|
sysIPV6_HOPOPTS = 0x31
|
||||||
|
sysIPV6_DSTOPTS = 0x32
|
||||||
|
sysIPV6_RTHDR = 0x33
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x39
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = 0x3b
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_PREFER_TEMPADDR = 0x3f
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = 0x0
|
||||||
|
sysIPV6_PORTRANGE_HIGH = 0x1
|
||||||
|
sysIPV6_PORTRANGE_LOW = 0x2
|
||||||
|
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Filt [8]uint32
|
||||||
|
}
|
||||||
+122
@@ -0,0 +1,122 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_freebsd.go
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x4
|
||||||
|
sysIPV6_MULTICAST_IF = 0x9
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0xa
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0xb
|
||||||
|
sysIPV6_JOIN_GROUP = 0xc
|
||||||
|
sysIPV6_LEAVE_GROUP = 0xd
|
||||||
|
sysIPV6_PORTRANGE = 0xe
|
||||||
|
sysICMP6_FILTER = 0x12
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = 0x1a
|
||||||
|
sysIPV6_V6ONLY = 0x1b
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x24
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x25
|
||||||
|
sysIPV6_RECVRTHDR = 0x26
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x27
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x28
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = 0x2a
|
||||||
|
sysIPV6_RECVPATHMTU = 0x2b
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = 0x2c
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = 0x2e
|
||||||
|
sysIPV6_HOPLIMIT = 0x2f
|
||||||
|
sysIPV6_NEXTHOP = 0x30
|
||||||
|
sysIPV6_HOPOPTS = 0x31
|
||||||
|
sysIPV6_DSTOPTS = 0x32
|
||||||
|
sysIPV6_RTHDR = 0x33
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x39
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = 0x3b
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_PREFER_TEMPADDR = 0x3f
|
||||||
|
|
||||||
|
sysIPV6_BINDANY = 0x40
|
||||||
|
|
||||||
|
sysIPV6_MSFILTER = 0x4a
|
||||||
|
|
||||||
|
sysMCAST_JOIN_GROUP = 0x50
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x51
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x52
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x53
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x54
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x55
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = 0x0
|
||||||
|
sysIPV6_PORTRANGE_HIGH = 0x1
|
||||||
|
sysIPV6_PORTRANGE_LOW = 0x2
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x84
|
||||||
|
sysSizeofGroupSourceReq = 0x104
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
X__ss_pad1 [6]int8
|
||||||
|
X__ss_align int64
|
||||||
|
X__ss_pad2 [112]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Group sysSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Group sysSockaddrStorage
|
||||||
|
Source sysSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Filt [8]uint32
|
||||||
|
}
|
||||||
+124
@@ -0,0 +1,124 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_freebsd.go
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x4
|
||||||
|
sysIPV6_MULTICAST_IF = 0x9
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0xa
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0xb
|
||||||
|
sysIPV6_JOIN_GROUP = 0xc
|
||||||
|
sysIPV6_LEAVE_GROUP = 0xd
|
||||||
|
sysIPV6_PORTRANGE = 0xe
|
||||||
|
sysICMP6_FILTER = 0x12
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = 0x1a
|
||||||
|
sysIPV6_V6ONLY = 0x1b
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x24
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x25
|
||||||
|
sysIPV6_RECVRTHDR = 0x26
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x27
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x28
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = 0x2a
|
||||||
|
sysIPV6_RECVPATHMTU = 0x2b
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = 0x2c
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = 0x2e
|
||||||
|
sysIPV6_HOPLIMIT = 0x2f
|
||||||
|
sysIPV6_NEXTHOP = 0x30
|
||||||
|
sysIPV6_HOPOPTS = 0x31
|
||||||
|
sysIPV6_DSTOPTS = 0x32
|
||||||
|
sysIPV6_RTHDR = 0x33
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x39
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = 0x3b
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_PREFER_TEMPADDR = 0x3f
|
||||||
|
|
||||||
|
sysIPV6_BINDANY = 0x40
|
||||||
|
|
||||||
|
sysIPV6_MSFILTER = 0x4a
|
||||||
|
|
||||||
|
sysMCAST_JOIN_GROUP = 0x50
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x51
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x52
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x53
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x54
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x55
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = 0x0
|
||||||
|
sysIPV6_PORTRANGE_HIGH = 0x1
|
||||||
|
sysIPV6_PORTRANGE_LOW = 0x2
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x88
|
||||||
|
sysSizeofGroupSourceReq = 0x108
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
X__ss_pad1 [6]int8
|
||||||
|
X__ss_align int64
|
||||||
|
X__ss_pad2 [112]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysSockaddrStorage
|
||||||
|
Source sysSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Filt [8]uint32
|
||||||
|
}
|
||||||
+124
@@ -0,0 +1,124 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_freebsd.go
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x4
|
||||||
|
sysIPV6_MULTICAST_IF = 0x9
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0xa
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0xb
|
||||||
|
sysIPV6_JOIN_GROUP = 0xc
|
||||||
|
sysIPV6_LEAVE_GROUP = 0xd
|
||||||
|
sysIPV6_PORTRANGE = 0xe
|
||||||
|
sysICMP6_FILTER = 0x12
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = 0x1a
|
||||||
|
sysIPV6_V6ONLY = 0x1b
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x24
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x25
|
||||||
|
sysIPV6_RECVRTHDR = 0x26
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x27
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x28
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = 0x2a
|
||||||
|
sysIPV6_RECVPATHMTU = 0x2b
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = 0x2c
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = 0x2e
|
||||||
|
sysIPV6_HOPLIMIT = 0x2f
|
||||||
|
sysIPV6_NEXTHOP = 0x30
|
||||||
|
sysIPV6_HOPOPTS = 0x31
|
||||||
|
sysIPV6_DSTOPTS = 0x32
|
||||||
|
sysIPV6_RTHDR = 0x33
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x39
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = 0x3b
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_PREFER_TEMPADDR = 0x3f
|
||||||
|
|
||||||
|
sysIPV6_BINDANY = 0x40
|
||||||
|
|
||||||
|
sysIPV6_MSFILTER = 0x4a
|
||||||
|
|
||||||
|
sysMCAST_JOIN_GROUP = 0x50
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x51
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x52
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x53
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x54
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x55
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = 0x0
|
||||||
|
sysIPV6_PORTRANGE_HIGH = 0x1
|
||||||
|
sysIPV6_PORTRANGE_LOW = 0x2
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x88
|
||||||
|
sysSizeofGroupSourceReq = 0x108
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
X__ss_pad1 [6]int8
|
||||||
|
X__ss_align int64
|
||||||
|
X__ss_pad2 [112]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysSockaddrStorage
|
||||||
|
Source sysSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Filt [8]uint32
|
||||||
|
}
|
||||||
+152
@@ -0,0 +1,152 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_linux.go
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_ADDRFORM = 0x1
|
||||||
|
sysIPV6_2292PKTINFO = 0x2
|
||||||
|
sysIPV6_2292HOPOPTS = 0x3
|
||||||
|
sysIPV6_2292DSTOPTS = 0x4
|
||||||
|
sysIPV6_2292RTHDR = 0x5
|
||||||
|
sysIPV6_2292PKTOPTIONS = 0x6
|
||||||
|
sysIPV6_CHECKSUM = 0x7
|
||||||
|
sysIPV6_2292HOPLIMIT = 0x8
|
||||||
|
sysIPV6_NEXTHOP = 0x9
|
||||||
|
sysIPV6_FLOWINFO = 0xb
|
||||||
|
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x10
|
||||||
|
sysIPV6_MULTICAST_IF = 0x11
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0x12
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0x13
|
||||||
|
sysIPV6_ADD_MEMBERSHIP = 0x14
|
||||||
|
sysIPV6_DROP_MEMBERSHIP = 0x15
|
||||||
|
sysMCAST_JOIN_GROUP = 0x2a
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x2d
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x2e
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x2b
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x2c
|
||||||
|
sysMCAST_MSFILTER = 0x30
|
||||||
|
sysIPV6_ROUTER_ALERT = 0x16
|
||||||
|
sysIPV6_MTU_DISCOVER = 0x17
|
||||||
|
sysIPV6_MTU = 0x18
|
||||||
|
sysIPV6_RECVERR = 0x19
|
||||||
|
sysIPV6_V6ONLY = 0x1a
|
||||||
|
sysIPV6_JOIN_ANYCAST = 0x1b
|
||||||
|
sysIPV6_LEAVE_ANYCAST = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_FLOWLABEL_MGR = 0x20
|
||||||
|
sysIPV6_FLOWINFO_SEND = 0x21
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x22
|
||||||
|
sysIPV6_XFRM_POLICY = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x31
|
||||||
|
sysIPV6_PKTINFO = 0x32
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x33
|
||||||
|
sysIPV6_HOPLIMIT = 0x34
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x35
|
||||||
|
sysIPV6_HOPOPTS = 0x36
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x37
|
||||||
|
sysIPV6_RECVRTHDR = 0x38
|
||||||
|
sysIPV6_RTHDR = 0x39
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x3a
|
||||||
|
sysIPV6_DSTOPTS = 0x3b
|
||||||
|
sysIPV6_RECVPATHMTU = 0x3c
|
||||||
|
sysIPV6_PATHMTU = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x42
|
||||||
|
sysIPV6_TCLASS = 0x43
|
||||||
|
|
||||||
|
sysIPV6_ADDR_PREFERENCES = 0x48
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_TMP = 0x1
|
||||||
|
sysIPV6_PREFER_SRC_PUBLIC = 0x2
|
||||||
|
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
|
||||||
|
sysIPV6_PREFER_SRC_COA = 0x4
|
||||||
|
sysIPV6_PREFER_SRC_HOME = 0x400
|
||||||
|
sysIPV6_PREFER_SRC_CGA = 0x8
|
||||||
|
sysIPV6_PREFER_SRC_NONCGA = 0x800
|
||||||
|
|
||||||
|
sysIPV6_MINHOPCOUNT = 0x49
|
||||||
|
|
||||||
|
sysIPV6_ORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_RECVORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_TRANSPARENT = 0x4b
|
||||||
|
sysIPV6_UNICAST_IF = 0x4c
|
||||||
|
|
||||||
|
sysICMPV6_FILTER = 0x1
|
||||||
|
|
||||||
|
sysICMPV6_FILTER_BLOCK = 0x1
|
||||||
|
sysICMPV6_FILTER_PASS = 0x2
|
||||||
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
sysSizeofIPv6FlowlabelReq = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x84
|
||||||
|
sysSizeofGroupSourceReq = 0x104
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysKernelSockaddrStorage struct {
|
||||||
|
Family uint16
|
||||||
|
X__data [126]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Family uint16
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6FlowlabelReq struct {
|
||||||
|
Dst [16]byte /* in6_addr */
|
||||||
|
Label uint32
|
||||||
|
Action uint8
|
||||||
|
Share uint8
|
||||||
|
Flags uint16
|
||||||
|
Expires uint16
|
||||||
|
Linger uint16
|
||||||
|
X__flr_pad uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
Source sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Data [8]uint32
|
||||||
|
}
|
||||||
+154
@@ -0,0 +1,154 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_linux.go
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_ADDRFORM = 0x1
|
||||||
|
sysIPV6_2292PKTINFO = 0x2
|
||||||
|
sysIPV6_2292HOPOPTS = 0x3
|
||||||
|
sysIPV6_2292DSTOPTS = 0x4
|
||||||
|
sysIPV6_2292RTHDR = 0x5
|
||||||
|
sysIPV6_2292PKTOPTIONS = 0x6
|
||||||
|
sysIPV6_CHECKSUM = 0x7
|
||||||
|
sysIPV6_2292HOPLIMIT = 0x8
|
||||||
|
sysIPV6_NEXTHOP = 0x9
|
||||||
|
sysIPV6_FLOWINFO = 0xb
|
||||||
|
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x10
|
||||||
|
sysIPV6_MULTICAST_IF = 0x11
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0x12
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0x13
|
||||||
|
sysIPV6_ADD_MEMBERSHIP = 0x14
|
||||||
|
sysIPV6_DROP_MEMBERSHIP = 0x15
|
||||||
|
sysMCAST_JOIN_GROUP = 0x2a
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x2d
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x2e
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x2b
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x2c
|
||||||
|
sysMCAST_MSFILTER = 0x30
|
||||||
|
sysIPV6_ROUTER_ALERT = 0x16
|
||||||
|
sysIPV6_MTU_DISCOVER = 0x17
|
||||||
|
sysIPV6_MTU = 0x18
|
||||||
|
sysIPV6_RECVERR = 0x19
|
||||||
|
sysIPV6_V6ONLY = 0x1a
|
||||||
|
sysIPV6_JOIN_ANYCAST = 0x1b
|
||||||
|
sysIPV6_LEAVE_ANYCAST = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_FLOWLABEL_MGR = 0x20
|
||||||
|
sysIPV6_FLOWINFO_SEND = 0x21
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x22
|
||||||
|
sysIPV6_XFRM_POLICY = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x31
|
||||||
|
sysIPV6_PKTINFO = 0x32
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x33
|
||||||
|
sysIPV6_HOPLIMIT = 0x34
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x35
|
||||||
|
sysIPV6_HOPOPTS = 0x36
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x37
|
||||||
|
sysIPV6_RECVRTHDR = 0x38
|
||||||
|
sysIPV6_RTHDR = 0x39
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x3a
|
||||||
|
sysIPV6_DSTOPTS = 0x3b
|
||||||
|
sysIPV6_RECVPATHMTU = 0x3c
|
||||||
|
sysIPV6_PATHMTU = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x42
|
||||||
|
sysIPV6_TCLASS = 0x43
|
||||||
|
|
||||||
|
sysIPV6_ADDR_PREFERENCES = 0x48
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_TMP = 0x1
|
||||||
|
sysIPV6_PREFER_SRC_PUBLIC = 0x2
|
||||||
|
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
|
||||||
|
sysIPV6_PREFER_SRC_COA = 0x4
|
||||||
|
sysIPV6_PREFER_SRC_HOME = 0x400
|
||||||
|
sysIPV6_PREFER_SRC_CGA = 0x8
|
||||||
|
sysIPV6_PREFER_SRC_NONCGA = 0x800
|
||||||
|
|
||||||
|
sysIPV6_MINHOPCOUNT = 0x49
|
||||||
|
|
||||||
|
sysIPV6_ORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_RECVORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_TRANSPARENT = 0x4b
|
||||||
|
sysIPV6_UNICAST_IF = 0x4c
|
||||||
|
|
||||||
|
sysICMPV6_FILTER = 0x1
|
||||||
|
|
||||||
|
sysICMPV6_FILTER_BLOCK = 0x1
|
||||||
|
sysICMPV6_FILTER_PASS = 0x2
|
||||||
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
sysSizeofIPv6FlowlabelReq = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x88
|
||||||
|
sysSizeofGroupSourceReq = 0x108
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysKernelSockaddrStorage struct {
|
||||||
|
Family uint16
|
||||||
|
X__data [126]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Family uint16
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6FlowlabelReq struct {
|
||||||
|
Dst [16]byte /* in6_addr */
|
||||||
|
Label uint32
|
||||||
|
Action uint8
|
||||||
|
Share uint8
|
||||||
|
Flags uint16
|
||||||
|
Expires uint16
|
||||||
|
Linger uint16
|
||||||
|
X__flr_pad uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
Source sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Data [8]uint32
|
||||||
|
}
|
||||||
+152
@@ -0,0 +1,152 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_linux.go
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_ADDRFORM = 0x1
|
||||||
|
sysIPV6_2292PKTINFO = 0x2
|
||||||
|
sysIPV6_2292HOPOPTS = 0x3
|
||||||
|
sysIPV6_2292DSTOPTS = 0x4
|
||||||
|
sysIPV6_2292RTHDR = 0x5
|
||||||
|
sysIPV6_2292PKTOPTIONS = 0x6
|
||||||
|
sysIPV6_CHECKSUM = 0x7
|
||||||
|
sysIPV6_2292HOPLIMIT = 0x8
|
||||||
|
sysIPV6_NEXTHOP = 0x9
|
||||||
|
sysIPV6_FLOWINFO = 0xb
|
||||||
|
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x10
|
||||||
|
sysIPV6_MULTICAST_IF = 0x11
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0x12
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0x13
|
||||||
|
sysIPV6_ADD_MEMBERSHIP = 0x14
|
||||||
|
sysIPV6_DROP_MEMBERSHIP = 0x15
|
||||||
|
sysMCAST_JOIN_GROUP = 0x2a
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x2d
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x2e
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x2b
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x2c
|
||||||
|
sysMCAST_MSFILTER = 0x30
|
||||||
|
sysIPV6_ROUTER_ALERT = 0x16
|
||||||
|
sysIPV6_MTU_DISCOVER = 0x17
|
||||||
|
sysIPV6_MTU = 0x18
|
||||||
|
sysIPV6_RECVERR = 0x19
|
||||||
|
sysIPV6_V6ONLY = 0x1a
|
||||||
|
sysIPV6_JOIN_ANYCAST = 0x1b
|
||||||
|
sysIPV6_LEAVE_ANYCAST = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_FLOWLABEL_MGR = 0x20
|
||||||
|
sysIPV6_FLOWINFO_SEND = 0x21
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x22
|
||||||
|
sysIPV6_XFRM_POLICY = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x31
|
||||||
|
sysIPV6_PKTINFO = 0x32
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x33
|
||||||
|
sysIPV6_HOPLIMIT = 0x34
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x35
|
||||||
|
sysIPV6_HOPOPTS = 0x36
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x37
|
||||||
|
sysIPV6_RECVRTHDR = 0x38
|
||||||
|
sysIPV6_RTHDR = 0x39
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x3a
|
||||||
|
sysIPV6_DSTOPTS = 0x3b
|
||||||
|
sysIPV6_RECVPATHMTU = 0x3c
|
||||||
|
sysIPV6_PATHMTU = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x42
|
||||||
|
sysIPV6_TCLASS = 0x43
|
||||||
|
|
||||||
|
sysIPV6_ADDR_PREFERENCES = 0x48
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_TMP = 0x1
|
||||||
|
sysIPV6_PREFER_SRC_PUBLIC = 0x2
|
||||||
|
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
|
||||||
|
sysIPV6_PREFER_SRC_COA = 0x4
|
||||||
|
sysIPV6_PREFER_SRC_HOME = 0x400
|
||||||
|
sysIPV6_PREFER_SRC_CGA = 0x8
|
||||||
|
sysIPV6_PREFER_SRC_NONCGA = 0x800
|
||||||
|
|
||||||
|
sysIPV6_MINHOPCOUNT = 0x49
|
||||||
|
|
||||||
|
sysIPV6_ORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_RECVORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_TRANSPARENT = 0x4b
|
||||||
|
sysIPV6_UNICAST_IF = 0x4c
|
||||||
|
|
||||||
|
sysICMPV6_FILTER = 0x1
|
||||||
|
|
||||||
|
sysICMPV6_FILTER_BLOCK = 0x1
|
||||||
|
sysICMPV6_FILTER_PASS = 0x2
|
||||||
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
sysSizeofIPv6FlowlabelReq = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x84
|
||||||
|
sysSizeofGroupSourceReq = 0x104
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysKernelSockaddrStorage struct {
|
||||||
|
Family uint16
|
||||||
|
X__data [126]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Family uint16
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6FlowlabelReq struct {
|
||||||
|
Dst [16]byte /* in6_addr */
|
||||||
|
Label uint32
|
||||||
|
Action uint8
|
||||||
|
Share uint8
|
||||||
|
Flags uint16
|
||||||
|
Expires uint16
|
||||||
|
Linger uint16
|
||||||
|
X__flr_pad uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
Source sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Data [8]uint32
|
||||||
|
}
|
||||||
+156
@@ -0,0 +1,156 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_linux.go
|
||||||
|
|
||||||
|
// +build linux,arm64
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_ADDRFORM = 0x1
|
||||||
|
sysIPV6_2292PKTINFO = 0x2
|
||||||
|
sysIPV6_2292HOPOPTS = 0x3
|
||||||
|
sysIPV6_2292DSTOPTS = 0x4
|
||||||
|
sysIPV6_2292RTHDR = 0x5
|
||||||
|
sysIPV6_2292PKTOPTIONS = 0x6
|
||||||
|
sysIPV6_CHECKSUM = 0x7
|
||||||
|
sysIPV6_2292HOPLIMIT = 0x8
|
||||||
|
sysIPV6_NEXTHOP = 0x9
|
||||||
|
sysIPV6_FLOWINFO = 0xb
|
||||||
|
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x10
|
||||||
|
sysIPV6_MULTICAST_IF = 0x11
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0x12
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0x13
|
||||||
|
sysIPV6_ADD_MEMBERSHIP = 0x14
|
||||||
|
sysIPV6_DROP_MEMBERSHIP = 0x15
|
||||||
|
sysMCAST_JOIN_GROUP = 0x2a
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x2d
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x2e
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x2b
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x2c
|
||||||
|
sysMCAST_MSFILTER = 0x30
|
||||||
|
sysIPV6_ROUTER_ALERT = 0x16
|
||||||
|
sysIPV6_MTU_DISCOVER = 0x17
|
||||||
|
sysIPV6_MTU = 0x18
|
||||||
|
sysIPV6_RECVERR = 0x19
|
||||||
|
sysIPV6_V6ONLY = 0x1a
|
||||||
|
sysIPV6_JOIN_ANYCAST = 0x1b
|
||||||
|
sysIPV6_LEAVE_ANYCAST = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_FLOWLABEL_MGR = 0x20
|
||||||
|
sysIPV6_FLOWINFO_SEND = 0x21
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x22
|
||||||
|
sysIPV6_XFRM_POLICY = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x31
|
||||||
|
sysIPV6_PKTINFO = 0x32
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x33
|
||||||
|
sysIPV6_HOPLIMIT = 0x34
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x35
|
||||||
|
sysIPV6_HOPOPTS = 0x36
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x37
|
||||||
|
sysIPV6_RECVRTHDR = 0x38
|
||||||
|
sysIPV6_RTHDR = 0x39
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x3a
|
||||||
|
sysIPV6_DSTOPTS = 0x3b
|
||||||
|
sysIPV6_RECVPATHMTU = 0x3c
|
||||||
|
sysIPV6_PATHMTU = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x42
|
||||||
|
sysIPV6_TCLASS = 0x43
|
||||||
|
|
||||||
|
sysIPV6_ADDR_PREFERENCES = 0x48
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_TMP = 0x1
|
||||||
|
sysIPV6_PREFER_SRC_PUBLIC = 0x2
|
||||||
|
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
|
||||||
|
sysIPV6_PREFER_SRC_COA = 0x4
|
||||||
|
sysIPV6_PREFER_SRC_HOME = 0x400
|
||||||
|
sysIPV6_PREFER_SRC_CGA = 0x8
|
||||||
|
sysIPV6_PREFER_SRC_NONCGA = 0x800
|
||||||
|
|
||||||
|
sysIPV6_MINHOPCOUNT = 0x49
|
||||||
|
|
||||||
|
sysIPV6_ORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_RECVORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_TRANSPARENT = 0x4b
|
||||||
|
sysIPV6_UNICAST_IF = 0x4c
|
||||||
|
|
||||||
|
sysICMPV6_FILTER = 0x1
|
||||||
|
|
||||||
|
sysICMPV6_FILTER_BLOCK = 0x1
|
||||||
|
sysICMPV6_FILTER_PASS = 0x2
|
||||||
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
sysSizeofIPv6FlowlabelReq = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x88
|
||||||
|
sysSizeofGroupSourceReq = 0x108
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysKernelSockaddrStorage struct {
|
||||||
|
Family uint16
|
||||||
|
X__data [126]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Family uint16
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6FlowlabelReq struct {
|
||||||
|
Dst [16]byte /* in6_addr */
|
||||||
|
Label uint32
|
||||||
|
Action uint8
|
||||||
|
Share uint8
|
||||||
|
Flags uint16
|
||||||
|
Expires uint16
|
||||||
|
Linger uint16
|
||||||
|
X__flr_pad uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
Source sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Data [8]uint32
|
||||||
|
}
|
||||||
+156
@@ -0,0 +1,156 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_linux.go
|
||||||
|
|
||||||
|
// +build linux,ppc64
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_ADDRFORM = 0x1
|
||||||
|
sysIPV6_2292PKTINFO = 0x2
|
||||||
|
sysIPV6_2292HOPOPTS = 0x3
|
||||||
|
sysIPV6_2292DSTOPTS = 0x4
|
||||||
|
sysIPV6_2292RTHDR = 0x5
|
||||||
|
sysIPV6_2292PKTOPTIONS = 0x6
|
||||||
|
sysIPV6_CHECKSUM = 0x7
|
||||||
|
sysIPV6_2292HOPLIMIT = 0x8
|
||||||
|
sysIPV6_NEXTHOP = 0x9
|
||||||
|
sysIPV6_FLOWINFO = 0xb
|
||||||
|
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x10
|
||||||
|
sysIPV6_MULTICAST_IF = 0x11
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0x12
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0x13
|
||||||
|
sysIPV6_ADD_MEMBERSHIP = 0x14
|
||||||
|
sysIPV6_DROP_MEMBERSHIP = 0x15
|
||||||
|
sysMCAST_JOIN_GROUP = 0x2a
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x2d
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x2e
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x2b
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x2c
|
||||||
|
sysMCAST_MSFILTER = 0x30
|
||||||
|
sysIPV6_ROUTER_ALERT = 0x16
|
||||||
|
sysIPV6_MTU_DISCOVER = 0x17
|
||||||
|
sysIPV6_MTU = 0x18
|
||||||
|
sysIPV6_RECVERR = 0x19
|
||||||
|
sysIPV6_V6ONLY = 0x1a
|
||||||
|
sysIPV6_JOIN_ANYCAST = 0x1b
|
||||||
|
sysIPV6_LEAVE_ANYCAST = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_FLOWLABEL_MGR = 0x20
|
||||||
|
sysIPV6_FLOWINFO_SEND = 0x21
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x22
|
||||||
|
sysIPV6_XFRM_POLICY = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x31
|
||||||
|
sysIPV6_PKTINFO = 0x32
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x33
|
||||||
|
sysIPV6_HOPLIMIT = 0x34
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x35
|
||||||
|
sysIPV6_HOPOPTS = 0x36
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x37
|
||||||
|
sysIPV6_RECVRTHDR = 0x38
|
||||||
|
sysIPV6_RTHDR = 0x39
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x3a
|
||||||
|
sysIPV6_DSTOPTS = 0x3b
|
||||||
|
sysIPV6_RECVPATHMTU = 0x3c
|
||||||
|
sysIPV6_PATHMTU = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x42
|
||||||
|
sysIPV6_TCLASS = 0x43
|
||||||
|
|
||||||
|
sysIPV6_ADDR_PREFERENCES = 0x48
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_TMP = 0x1
|
||||||
|
sysIPV6_PREFER_SRC_PUBLIC = 0x2
|
||||||
|
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
|
||||||
|
sysIPV6_PREFER_SRC_COA = 0x4
|
||||||
|
sysIPV6_PREFER_SRC_HOME = 0x400
|
||||||
|
sysIPV6_PREFER_SRC_CGA = 0x8
|
||||||
|
sysIPV6_PREFER_SRC_NONCGA = 0x800
|
||||||
|
|
||||||
|
sysIPV6_MINHOPCOUNT = 0x49
|
||||||
|
|
||||||
|
sysIPV6_ORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_RECVORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_TRANSPARENT = 0x4b
|
||||||
|
sysIPV6_UNICAST_IF = 0x4c
|
||||||
|
|
||||||
|
sysICMPV6_FILTER = 0x1
|
||||||
|
|
||||||
|
sysICMPV6_FILTER_BLOCK = 0x1
|
||||||
|
sysICMPV6_FILTER_PASS = 0x2
|
||||||
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
sysSizeofIPv6FlowlabelReq = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x88
|
||||||
|
sysSizeofGroupSourceReq = 0x108
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysKernelSockaddrStorage struct {
|
||||||
|
Family uint16
|
||||||
|
X__data [126]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Family uint16
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6FlowlabelReq struct {
|
||||||
|
Dst [16]byte /* in6_addr */
|
||||||
|
Label uint32
|
||||||
|
Action uint8
|
||||||
|
Share uint8
|
||||||
|
Flags uint16
|
||||||
|
Expires uint16
|
||||||
|
Linger uint16
|
||||||
|
X__flr_pad uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
Source sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Data [8]uint32
|
||||||
|
}
|
||||||
+156
@@ -0,0 +1,156 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_linux.go
|
||||||
|
|
||||||
|
// +build linux,ppc64le
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_ADDRFORM = 0x1
|
||||||
|
sysIPV6_2292PKTINFO = 0x2
|
||||||
|
sysIPV6_2292HOPOPTS = 0x3
|
||||||
|
sysIPV6_2292DSTOPTS = 0x4
|
||||||
|
sysIPV6_2292RTHDR = 0x5
|
||||||
|
sysIPV6_2292PKTOPTIONS = 0x6
|
||||||
|
sysIPV6_CHECKSUM = 0x7
|
||||||
|
sysIPV6_2292HOPLIMIT = 0x8
|
||||||
|
sysIPV6_NEXTHOP = 0x9
|
||||||
|
sysIPV6_FLOWINFO = 0xb
|
||||||
|
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x10
|
||||||
|
sysIPV6_MULTICAST_IF = 0x11
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0x12
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0x13
|
||||||
|
sysIPV6_ADD_MEMBERSHIP = 0x14
|
||||||
|
sysIPV6_DROP_MEMBERSHIP = 0x15
|
||||||
|
sysMCAST_JOIN_GROUP = 0x2a
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x2d
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x2e
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x2b
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x2c
|
||||||
|
sysMCAST_MSFILTER = 0x30
|
||||||
|
sysIPV6_ROUTER_ALERT = 0x16
|
||||||
|
sysIPV6_MTU_DISCOVER = 0x17
|
||||||
|
sysIPV6_MTU = 0x18
|
||||||
|
sysIPV6_RECVERR = 0x19
|
||||||
|
sysIPV6_V6ONLY = 0x1a
|
||||||
|
sysIPV6_JOIN_ANYCAST = 0x1b
|
||||||
|
sysIPV6_LEAVE_ANYCAST = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_FLOWLABEL_MGR = 0x20
|
||||||
|
sysIPV6_FLOWINFO_SEND = 0x21
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x22
|
||||||
|
sysIPV6_XFRM_POLICY = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x31
|
||||||
|
sysIPV6_PKTINFO = 0x32
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x33
|
||||||
|
sysIPV6_HOPLIMIT = 0x34
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x35
|
||||||
|
sysIPV6_HOPOPTS = 0x36
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x37
|
||||||
|
sysIPV6_RECVRTHDR = 0x38
|
||||||
|
sysIPV6_RTHDR = 0x39
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x3a
|
||||||
|
sysIPV6_DSTOPTS = 0x3b
|
||||||
|
sysIPV6_RECVPATHMTU = 0x3c
|
||||||
|
sysIPV6_PATHMTU = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x42
|
||||||
|
sysIPV6_TCLASS = 0x43
|
||||||
|
|
||||||
|
sysIPV6_ADDR_PREFERENCES = 0x48
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_TMP = 0x1
|
||||||
|
sysIPV6_PREFER_SRC_PUBLIC = 0x2
|
||||||
|
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
|
||||||
|
sysIPV6_PREFER_SRC_COA = 0x4
|
||||||
|
sysIPV6_PREFER_SRC_HOME = 0x400
|
||||||
|
sysIPV6_PREFER_SRC_CGA = 0x8
|
||||||
|
sysIPV6_PREFER_SRC_NONCGA = 0x800
|
||||||
|
|
||||||
|
sysIPV6_MINHOPCOUNT = 0x49
|
||||||
|
|
||||||
|
sysIPV6_ORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_RECVORIGDSTADDR = 0x4a
|
||||||
|
sysIPV6_TRANSPARENT = 0x4b
|
||||||
|
sysIPV6_UNICAST_IF = 0x4c
|
||||||
|
|
||||||
|
sysICMPV6_FILTER = 0x1
|
||||||
|
|
||||||
|
sysICMPV6_FILTER_BLOCK = 0x1
|
||||||
|
sysICMPV6_FILTER_PASS = 0x2
|
||||||
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
sysSizeofIPv6FlowlabelReq = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofGroupReq = 0x88
|
||||||
|
sysSizeofGroupSourceReq = 0x108
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysKernelSockaddrStorage struct {
|
||||||
|
Family uint16
|
||||||
|
X__data [126]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Family uint16
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6FlowlabelReq struct {
|
||||||
|
Dst [16]byte /* in6_addr */
|
||||||
|
Label uint32
|
||||||
|
Action uint8
|
||||||
|
Share uint8
|
||||||
|
Flags uint16
|
||||||
|
Expires uint16
|
||||||
|
Linger uint16
|
||||||
|
X__flr_pad uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Group sysKernelSockaddrStorage
|
||||||
|
Source sysKernelSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Data [8]uint32
|
||||||
|
}
|
||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_netbsd.go
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x4
|
||||||
|
sysIPV6_MULTICAST_IF = 0x9
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0xa
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0xb
|
||||||
|
sysIPV6_JOIN_GROUP = 0xc
|
||||||
|
sysIPV6_LEAVE_GROUP = 0xd
|
||||||
|
sysIPV6_PORTRANGE = 0xe
|
||||||
|
sysICMP6_FILTER = 0x12
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = 0x1a
|
||||||
|
sysIPV6_V6ONLY = 0x1b
|
||||||
|
|
||||||
|
sysIPV6_IPSEC_POLICY = 0x1c
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x24
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x25
|
||||||
|
sysIPV6_RECVRTHDR = 0x26
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x27
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x28
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = 0x2a
|
||||||
|
sysIPV6_RECVPATHMTU = 0x2b
|
||||||
|
sysIPV6_PATHMTU = 0x2c
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = 0x2e
|
||||||
|
sysIPV6_HOPLIMIT = 0x2f
|
||||||
|
sysIPV6_NEXTHOP = 0x30
|
||||||
|
sysIPV6_HOPOPTS = 0x31
|
||||||
|
sysIPV6_DSTOPTS = 0x32
|
||||||
|
sysIPV6_RTHDR = 0x33
|
||||||
|
|
||||||
|
sysIPV6_RECVTCLASS = 0x39
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = 0x0
|
||||||
|
sysIPV6_PORTRANGE_HIGH = 0x1
|
||||||
|
sysIPV6_PORTRANGE_LOW = 0x2
|
||||||
|
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Filt [8]uint32
|
||||||
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_openbsd.go
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x4
|
||||||
|
sysIPV6_MULTICAST_IF = 0x9
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0xa
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0xb
|
||||||
|
sysIPV6_JOIN_GROUP = 0xc
|
||||||
|
sysIPV6_LEAVE_GROUP = 0xd
|
||||||
|
sysIPV6_PORTRANGE = 0xe
|
||||||
|
sysICMP6_FILTER = 0x12
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = 0x1a
|
||||||
|
sysIPV6_V6ONLY = 0x1b
|
||||||
|
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x23
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x24
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x25
|
||||||
|
sysIPV6_RECVRTHDR = 0x26
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x27
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x28
|
||||||
|
|
||||||
|
sysIPV6_USE_MIN_MTU = 0x2a
|
||||||
|
sysIPV6_RECVPATHMTU = 0x2b
|
||||||
|
|
||||||
|
sysIPV6_PATHMTU = 0x2c
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = 0x2e
|
||||||
|
sysIPV6_HOPLIMIT = 0x2f
|
||||||
|
sysIPV6_NEXTHOP = 0x30
|
||||||
|
sysIPV6_HOPOPTS = 0x31
|
||||||
|
sysIPV6_DSTOPTS = 0x32
|
||||||
|
sysIPV6_RTHDR = 0x33
|
||||||
|
|
||||||
|
sysIPV6_AUTH_LEVEL = 0x35
|
||||||
|
sysIPV6_ESP_TRANS_LEVEL = 0x36
|
||||||
|
sysIPV6_ESP_NETWORK_LEVEL = 0x37
|
||||||
|
sysIPSEC6_OUTSA = 0x38
|
||||||
|
sysIPV6_RECVTCLASS = 0x39
|
||||||
|
|
||||||
|
sysIPV6_AUTOFLOWLABEL = 0x3b
|
||||||
|
sysIPV6_IPCOMP_LEVEL = 0x3c
|
||||||
|
|
||||||
|
sysIPV6_TCLASS = 0x3d
|
||||||
|
sysIPV6_DONTFRAG = 0x3e
|
||||||
|
sysIPV6_PIPEX = 0x3f
|
||||||
|
|
||||||
|
sysIPV6_RTABLE = 0x1021
|
||||||
|
|
||||||
|
sysIPV6_PORTRANGE_DEFAULT = 0x0
|
||||||
|
sysIPV6_PORTRANGE_HIGH = 0x1
|
||||||
|
sysIPV6_PORTRANGE_LOW = 0x2
|
||||||
|
|
||||||
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
Filt [8]uint32
|
||||||
|
}
|
||||||
+105
@@ -0,0 +1,105 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_solaris.go
|
||||||
|
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIPV6_UNICAST_HOPS = 0x5
|
||||||
|
sysIPV6_MULTICAST_IF = 0x6
|
||||||
|
sysIPV6_MULTICAST_HOPS = 0x7
|
||||||
|
sysIPV6_MULTICAST_LOOP = 0x8
|
||||||
|
sysIPV6_JOIN_GROUP = 0x9
|
||||||
|
sysIPV6_LEAVE_GROUP = 0xa
|
||||||
|
|
||||||
|
sysIPV6_PKTINFO = 0xb
|
||||||
|
|
||||||
|
sysIPV6_HOPLIMIT = 0xc
|
||||||
|
sysIPV6_NEXTHOP = 0xd
|
||||||
|
sysIPV6_HOPOPTS = 0xe
|
||||||
|
sysIPV6_DSTOPTS = 0xf
|
||||||
|
|
||||||
|
sysIPV6_RTHDR = 0x10
|
||||||
|
sysIPV6_RTHDRDSTOPTS = 0x11
|
||||||
|
|
||||||
|
sysIPV6_RECVPKTINFO = 0x12
|
||||||
|
sysIPV6_RECVHOPLIMIT = 0x13
|
||||||
|
sysIPV6_RECVHOPOPTS = 0x14
|
||||||
|
|
||||||
|
sysIPV6_RECVRTHDR = 0x16
|
||||||
|
|
||||||
|
sysIPV6_RECVRTHDRDSTOPTS = 0x17
|
||||||
|
|
||||||
|
sysIPV6_CHECKSUM = 0x18
|
||||||
|
sysIPV6_RECVTCLASS = 0x19
|
||||||
|
sysIPV6_USE_MIN_MTU = 0x20
|
||||||
|
sysIPV6_DONTFRAG = 0x21
|
||||||
|
sysIPV6_SEC_OPT = 0x22
|
||||||
|
sysIPV6_SRC_PREFERENCES = 0x23
|
||||||
|
sysIPV6_RECVPATHMTU = 0x24
|
||||||
|
sysIPV6_PATHMTU = 0x25
|
||||||
|
sysIPV6_TCLASS = 0x26
|
||||||
|
sysIPV6_V6ONLY = 0x27
|
||||||
|
|
||||||
|
sysIPV6_RECVDSTOPTS = 0x28
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_HOME = 0x1
|
||||||
|
sysIPV6_PREFER_SRC_COA = 0x2
|
||||||
|
sysIPV6_PREFER_SRC_PUBLIC = 0x4
|
||||||
|
sysIPV6_PREFER_SRC_TMP = 0x8
|
||||||
|
sysIPV6_PREFER_SRC_NONCGA = 0x10
|
||||||
|
sysIPV6_PREFER_SRC_CGA = 0x20
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_MIPMASK = 0x3
|
||||||
|
sysIPV6_PREFER_SRC_MIPDEFAULT = 0x1
|
||||||
|
sysIPV6_PREFER_SRC_TMPMASK = 0xc
|
||||||
|
sysIPV6_PREFER_SRC_TMPDEFAULT = 0x4
|
||||||
|
sysIPV6_PREFER_SRC_CGAMASK = 0x30
|
||||||
|
sysIPV6_PREFER_SRC_CGADEFAULT = 0x10
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_MASK = 0x3f
|
||||||
|
|
||||||
|
sysIPV6_PREFER_SRC_DEFAULT = 0x15
|
||||||
|
|
||||||
|
sysIPV6_BOUND_IF = 0x41
|
||||||
|
sysIPV6_UNSPEC_SRC = 0x42
|
||||||
|
|
||||||
|
sysICMP6_FILTER = 0x1
|
||||||
|
|
||||||
|
sysSizeofSockaddrInet6 = 0x20
|
||||||
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x24
|
||||||
|
|
||||||
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
|
||||||
|
sysSizeofICMPv6Filter = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrInet6 struct {
|
||||||
|
Family uint16
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
X__sin6_src_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
X__icmp6_filt [8]uint32
|
||||||
|
}
|
||||||
@@ -52,7 +52,7 @@ pluby <phill.luby@newredo.com>
|
|||||||
pyfisch <pyfisch@gmail.com>
|
pyfisch <pyfisch@gmail.com>
|
||||||
qbit <qbit@deftly.net>
|
qbit <qbit@deftly.net>
|
||||||
ralder <ralder@yandex.ru>
|
ralder <ralder@yandex.ru>
|
||||||
rumpelsepp <stefan@sevenbyte.org>
|
rumpelsepp <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org>
|
||||||
sciurius <jvromans@squirrel.nl>
|
sciurius <jvromans@squirrel.nl>
|
||||||
seehuhn <voss@seehuhn.de>
|
seehuhn <voss@seehuhn.de>
|
||||||
snnd <dw@risu.io>
|
snnd <dw@risu.io>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user